2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "IScsiImpl.h"
17 CHAR16 mVendorStorageName
[] = L
"ISCSI_CONFIG_IFR_NVDATA";
18 ISCSI_FORM_CALLBACK_INFO
*mCallbackInfo
= NULL
;
20 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath
= {
26 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
27 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
34 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
36 (UINT8
) (END_DEVICE_PATH_LENGTH
),
37 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
44 Convert the IP address into a dotted string.
46 @param[in] Ip The IP address.
47 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.
48 @param[out] Str The formatted IP string.
53 IN EFI_IP_ADDRESS
*Ip
,
58 EFI_IPv4_ADDRESS
*Ip4
;
59 EFI_IPv6_ADDRESS
*Ip6
;
63 CHAR16 FormatString
[8];
70 (UINTN
) 2 * IP4_STR_MAX_SIZE
,
84 for (Index
= 0; Index
< 15; Index
= Index
+ 2) {
87 Ip6
->Addr
[Index
] == 0 &&
88 Ip6
->Addr
[Index
+ 1] == 0
91 // Deal with the case of ::.
102 while ((Index
< 15) && (Ip6
->Addr
[Index
] == 0) && (Ip6
->Addr
[Index
+ 1] == 0)) {
110 // :: is at the end of the address.
119 if (Ip6
->Addr
[Index
] == 0) {
120 Number
= UnicodeSPrint (Str
, 2 * IP_STR_MAX_SIZE
, L
"%x:", (UINTN
) Ip6
->Addr
[Index
+ 1]);
122 if (Ip6
->Addr
[Index
+ 1] < 0x10) {
123 CopyMem (FormatString
, L
"%x0%x:", StrSize (L
"%x0%x:"));
125 CopyMem (FormatString
, L
"%x%x:", StrSize (L
"%x%x:"));
128 Number
= UnicodeSPrint (
131 (CONST CHAR16
*) FormatString
,
132 (UINTN
) Ip6
->Addr
[Index
],
133 (UINTN
) Ip6
->Addr
[Index
+ 1]
139 if (Index
+ 2 == 16) {
141 if (*(Str
- 1) == L
':') {
149 Check whether the input IP address is valid.
151 @param[in] Ip The IP address.
152 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.
154 @retval TRUE The input IP address is valid.
155 @retval FALSE Otherwise
160 IN EFI_IP_ADDRESS
*Ip
,
164 if (IpMode
== IP_MODE_IP4
) {
165 if (IP4_IS_UNSPECIFIED (NTOHL (Ip
->Addr
[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip
->Addr
[0]))) {
169 } else if (IpMode
== IP_MODE_IP6
) {
170 return NetIp6IsValidUnicast (&Ip
->v6
);
172 DEBUG ((DEBUG_ERROR
, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode
));
178 Parse IsId in string format and convert it to binary.
180 @param[in] String The buffer of the string to be parsed.
181 @param[in, out] IsId The buffer to store IsId.
183 @retval EFI_SUCCESS The operation finished successfully.
184 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
188 IScsiParseIsIdFromString (
189 IN CONST CHAR16
*String
,
197 CHAR16 PortString
[ISCSI_NAME_IFR_MAX_SIZE
];
200 if ((String
== NULL
) || (IsId
== NULL
)) {
201 return EFI_INVALID_PARAMETER
;
204 IsIdStr
= (CHAR16
*) String
;
206 if (StrLen (IsIdStr
) != 6 && StrLen (IsIdStr
) != 12) {
209 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
210 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"
214 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
220 return EFI_INVALID_PARAMETER
;
223 if (StrLen (IsIdStr
) == 12) {
227 for (Index
= 3; Index
< 6; Index
++) {
228 CopyMem (TempStr
, IsIdStr
, sizeof (TempStr
));
232 // Convert the string to IsId. StrHexToUintn stops at the first character
233 // that is not a valid hex character, '\0' here.
235 NodeVal
= StrHexToUintn (TempStr
);
237 IsId
[Index
] = (UINT8
) NodeVal
;
239 IsIdStr
= IsIdStr
+ 2;
246 Convert IsId from binary to string format.
248 @param[out] String The buffer to store the converted string.
249 @param[in] IsId The buffer to store IsId.
251 @retval EFI_SUCCESS The string converted successfully.
252 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
256 IScsiConvertIsIdToString (
264 if ((String
== NULL
) || (IsId
== NULL
)) {
265 return EFI_INVALID_PARAMETER
;
268 for (Index
= 0; Index
< 6; Index
++) {
269 if (IsId
[Index
] <= 0xF) {
270 Number
= UnicodeSPrint (
272 2 * ISID_CONFIGURABLE_STORAGE
,
277 Number
= UnicodeSPrint (
279 2 * ISID_CONFIGURABLE_STORAGE
,
286 String
= String
+ Number
;
295 Get the Offset value specified by the input String.
297 @param[in] Configuration A null-terminated Unicode string in
298 <ConfigString> format.
299 @param[in] String The string is "&OFFSET=".
300 @param[out] Value The Offset value.
302 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
304 @retval EFI_SUCCESS Value of <Number> is outputted in Number
310 IN CONST EFI_STRING Configuration
,
330 StringPtr
= StrStr (Configuration
, String
);
331 ASSERT(StringPtr
!= NULL
);
332 StringPtr
+= StrLen (String
);
335 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
338 Length
= StringPtr
- TmpPtr
;
341 Str
= AllocateZeroPool (Len
* sizeof (CHAR16
));
343 Status
= EFI_OUT_OF_RESOURCES
;
347 CopyMem (Str
, TmpPtr
, Len
* sizeof (CHAR16
));
348 *(Str
+ Length
) = L
'\0';
351 Buf
= (UINT8
*) AllocateZeroPool (Len
);
353 Status
= EFI_OUT_OF_RESOURCES
;
357 ZeroMem (TmpStr
, sizeof (TmpStr
));
358 for (Index
= 0; Index
< Length
; Index
++) {
359 TmpStr
[0] = Str
[Length
- Index
- 1];
360 DigitUint8
= (UINT8
) StrHexToUint64 (TmpStr
);
361 if ((Index
& 1) == 0) {
362 Buf
[Index
/2] = DigitUint8
;
364 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
372 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
376 Status
= EFI_SUCCESS
;
387 Get the attempt config data from global structure by the ConfigIndex.
389 @param[in] AttemptConfigIndex The unique index indicates the attempt.
391 @return Pointer to the attempt config data.
392 @retval NULL The attempt configuration data cannot be found.
395 ISCSI_ATTEMPT_CONFIG_NVDATA
*
396 IScsiConfigGetAttemptByConfigIndex (
397 IN UINT8 AttemptConfigIndex
401 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
403 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
404 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
405 if (Attempt
->AttemptConfigIndex
== AttemptConfigIndex
) {
415 Get the existing attempt config data from global structure by the NicIndex.
417 @param[in] NewAttempt The created new attempt
418 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
421 @return Pointer to the existing attempt config data which
422 has the same NICIndex as the new created attempt.
423 @retval NULL The attempt with NicIndex does not exist.
426 ISCSI_ATTEMPT_CONFIG_NVDATA
*
427 IScsiConfigGetAttemptByNic (
428 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*NewAttempt
,
433 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
435 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
436 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
437 if (Attempt
!= NewAttempt
&& Attempt
->NicIndex
== NewAttempt
->NicIndex
&&
438 Attempt
->SessionConfigData
.Enabled
== IScsiMode
) {
447 Extract the Index of the attempt list.
449 @param[in] AttemptNameList The Name list of the Attempts.
450 @param[out] AttemptIndexList The Index list of the Attempts.
451 @param[in] IsAddAttempts If TRUE, Indicates add one or more attempts.
452 If FALSE, Indicates delete attempts or change attempt order.
454 @retval EFI_SUCCESS The Attempt list is valid.
455 @retval EFI_INVALID_PARAMETERS The Attempt List is invalid.
459 IScsiGetAttemptIndexList (
460 IN CHAR16
*AttemptNameList
,
461 OUT UINT8
*AttemptIndexList
,
462 IN BOOLEAN IsAddAttempts
465 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
473 if ((AttemptNameList
== NULL
) || (*AttemptNameList
== L
'\0')) {
474 return EFI_INVALID_PARAMETER
;
477 AttemptStr
= AttemptNameList
;
478 Len
= StrLen (L
"attempt:");
480 while (*AttemptStr
!= L
'\0') {
481 AttemptStr
= StrStr (AttemptStr
, L
"attempt:");
482 if (AttemptStr
== NULL
) {
483 return EFI_INVALID_PARAMETER
;
486 AttemptIndex
= (UINT8
)(*AttemptStr
- L
'0');
487 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
489 if ((AttemptConfigData
!= NULL
) || ((AttemptIndex
) > PcdGet8 (PcdMaxIScsiAttemptNumber
))) {
490 return EFI_INVALID_PARAMETER
;
493 if (AttemptConfigData
== NULL
) {
494 return EFI_INVALID_PARAMETER
;
498 AttemptIndexList
[Index
] = AttemptIndex
;
506 Convert the iSCSI configuration data into the IFR data.
508 @param[in] Attempt The iSCSI attempt config data.
509 @param[in, out] IfrNvData The IFR nv data.
513 IScsiConvertAttemptConfigDataToIfrNvData (
514 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
,
515 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
518 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
519 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
524 // Normal session configuration parameters.
526 SessionConfigData
= &Attempt
->SessionConfigData
;
527 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
528 IfrNvData
->IpMode
= SessionConfigData
->IpMode
;
529 DnsMode
= SessionConfigData
->DnsMode
;
531 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
532 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
533 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
535 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
536 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
537 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->LocalIp
);
538 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
539 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->SubnetMask
);
540 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
541 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Gateway
);
542 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
543 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
544 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
545 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->TargetIp
);
548 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
549 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
550 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
551 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
552 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->TargetIp
);
556 AsciiStrToUnicodeStrS (
557 SessionConfigData
->TargetName
,
558 IfrNvData
->TargetName
,
559 sizeof (IfrNvData
->TargetName
) / sizeof (IfrNvData
->TargetName
[0])
563 AsciiStrToUnicodeStrS (
564 SessionConfigData
->TargetUrl
,
566 sizeof (IfrNvData
->TargetIp
) / sizeof (IfrNvData
->TargetIp
[0])
570 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
571 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
573 IfrNvData
->ConnectRetryCount
= SessionConfigData
->ConnectRetryCount
;
574 IfrNvData
->ConnectTimeout
= SessionConfigData
->ConnectTimeout
;
577 // Authentication parameters.
579 IfrNvData
->AuthenticationType
= Attempt
->AuthenticationType
;
581 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
582 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
583 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
584 AsciiStrToUnicodeStrS (
585 AuthConfigData
->CHAPName
,
587 sizeof (IfrNvData
->CHAPName
) / sizeof (IfrNvData
->CHAPName
[0])
589 AsciiStrToUnicodeStrS (
590 AuthConfigData
->CHAPSecret
,
591 IfrNvData
->CHAPSecret
,
592 sizeof (IfrNvData
->CHAPSecret
) / sizeof (IfrNvData
->CHAPSecret
[0])
594 AsciiStrToUnicodeStrS (
595 AuthConfigData
->ReverseCHAPName
,
596 IfrNvData
->ReverseCHAPName
,
597 sizeof (IfrNvData
->ReverseCHAPName
) / sizeof (IfrNvData
->ReverseCHAPName
[0])
599 AsciiStrToUnicodeStrS (
600 AuthConfigData
->ReverseCHAPSecret
,
601 IfrNvData
->ReverseCHAPSecret
,
602 sizeof (IfrNvData
->ReverseCHAPSecret
) / sizeof (IfrNvData
->ReverseCHAPSecret
[0])
609 AsciiStrToUnicodeStrS (
610 Attempt
->AttemptName
,
611 IfrNvData
->AttemptName
,
612 sizeof (IfrNvData
->AttemptName
) / sizeof (IfrNvData
->AttemptName
[0])
617 Convert the iSCSI configuration data into the IFR data Which will be used
618 to extract the iSCSI Keyword configuration in <ConfigAltResp> format.
620 @param[in, out] IfrNvData The IFR nv data.
625 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (
626 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
630 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
631 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
632 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
633 CHAR16 AttemptNameList
[ATTEMPT_NAME_LIST_SIZE
];
634 ISCSI_NIC_INFO
*NicInfo
;
635 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
641 ZeroMem (AttemptNameList
, sizeof (AttemptNameList
));
643 if ((mPrivate
!= NULL
) && (mPrivate
->AttemptCount
!= 0)) {
644 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
645 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
647 // Normal session configuration parameters.
649 SessionConfigData
= &Attempt
->SessionConfigData
;
651 ASSERT ((Attempt
->AttemptConfigIndex
> 0) && (Attempt
->AttemptConfigIndex
<= FixedPcdGet8 (PcdMaxIScsiAttemptNumber
)));
652 Index
= Attempt
->AttemptConfigIndex
- 1;
655 // Save the attempt to AttemptNameList as Attempt:1 Attempt:2
657 AsciiStrToUnicodeStrS (
658 Attempt
->AttemptName
,
659 AttemptNameList
+ StrLen (AttemptNameList
),
660 ATTEMPT_NAME_LIST_SIZE
- StrLen (AttemptNameList
)
663 StringLen
= StrLen (AttemptNameList
);
664 ASSERT (StringLen
> 2);
665 *(AttemptNameList
+ StringLen
- 2) = L
':';
666 *(AttemptNameList
+ StringLen
) = L
' ';
668 AsciiStrToUnicodeStrS (
669 Attempt
->AttemptName
,
670 IfrNvData
->ISCSIAttemptName
+ ATTEMPT_NAME_SIZE
* Index
,
671 ATTEMPT_NAME_LIST_SIZE
- ATTEMPT_NAME_SIZE
* Index
674 IfrNvData
->ISCSIBootEnableList
[Index
] = SessionConfigData
->Enabled
;
675 IfrNvData
->ISCSIIpAddressTypeList
[Index
] = SessionConfigData
->IpMode
;
677 IfrNvData
->ISCSIInitiatorInfoViaDHCP
[Index
] = SessionConfigData
->InitiatorInfoFromDhcp
;
678 IfrNvData
->ISCSITargetInfoViaDHCP
[Index
] = SessionConfigData
->TargetInfoFromDhcp
;
679 IfrNvData
->ISCSIConnectRetry
[Index
] = SessionConfigData
->ConnectRetryCount
;
680 IfrNvData
->ISCSIConnectTimeout
[Index
] = SessionConfigData
->ConnectTimeout
;
681 IfrNvData
->ISCSITargetTcpPort
[Index
] = SessionConfigData
->TargetPort
;
683 if (SessionConfigData
->IpMode
== IP_MODE_IP4
) {
684 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
685 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
);
686 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
687 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
);
688 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
689 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
);
690 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
691 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
692 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
);
694 } else if (SessionConfigData
->IpMode
== IP_MODE_IP6
) {
695 ZeroMem (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, sizeof (IfrNvData
->TargetIp
));
696 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
697 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
698 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
);
702 AsciiStrToUnicodeStrS (
703 SessionConfigData
->TargetName
,
704 IfrNvData
->Keyword
[Index
].ISCSITargetName
,
708 if (SessionConfigData
->DnsMode
) {
709 AsciiStrToUnicodeStrS (
710 SessionConfigData
->TargetUrl
,
711 IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
,
712 sizeof (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
) / sizeof (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
[0])
716 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->Keyword
[Index
].ISCSILun
);
717 IScsiConvertIsIdToString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, SessionConfigData
->IsId
);
719 IfrNvData
->ISCSIAuthenticationMethod
[Index
] = Attempt
->AuthenticationType
;
721 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
722 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
723 IfrNvData
->ISCSIChapType
[Index
] = AuthConfigData
->CHAPType
;
724 AsciiStrToUnicodeStrS (
725 AuthConfigData
->CHAPName
,
726 IfrNvData
->Keyword
[Index
].ISCSIChapUsername
,
727 ISCSI_CHAP_NAME_STORAGE
730 AsciiStrToUnicodeStrS (
731 AuthConfigData
->CHAPSecret
,
732 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
733 ISCSI_CHAP_SECRET_STORAGE
736 AsciiStrToUnicodeStrS (
737 AuthConfigData
->ReverseCHAPName
,
738 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
739 ISCSI_CHAP_NAME_STORAGE
742 AsciiStrToUnicodeStrS (
743 AuthConfigData
->ReverseCHAPSecret
,
744 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
745 ISCSI_CHAP_SECRET_STORAGE
749 CopyMem(IfrNvData
->ISCSIDisplayAttemptList
, AttemptNameList
, ATTEMPT_NAME_LIST_SIZE
);
751 ZeroMem (IfrNvData
->ISCSIMacAddr
, sizeof (IfrNvData
->ISCSIMacAddr
));
752 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
753 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
755 &NicInfo
->PermanentAddress
,
756 NicInfo
->HwAddressSize
,
761 IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
),
763 StrLen (MacString
) * sizeof (CHAR16
)
766 *(IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
)) = L
'/';
769 StringLen
= StrLen (IfrNvData
->ISCSIMacAddr
);
771 *(IfrNvData
->ISCSIMacAddr
+ StringLen
- 1) = L
'\0';
777 Convert the IFR data to iSCSI configuration data.
779 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
780 @param[in, out] Attempt The iSCSI attempt config data.
782 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
783 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
784 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
785 @retval EFI_ABORTED The operation is aborted.
786 @retval EFI_SUCCESS The operation is completed successfully.
790 IScsiConvertIfrNvDataToAttemptConfigData (
791 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
792 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
795 EFI_IP_ADDRESS HostIp
;
796 EFI_IP_ADDRESS SubnetMask
;
797 EFI_IP_ADDRESS Gateway
;
799 CHAR16
*AttemptName1
;
800 CHAR16
*AttemptName2
;
801 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
802 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
803 CHAR16 IScsiMode
[64];
805 ISCSI_NIC_INFO
*NicInfo
;
807 UINT8
*AttemptConfigOrder
;
808 UINTN AttemptConfigOrderSize
;
809 UINT8
*AttemptOrderTmp
;
813 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
814 return EFI_INVALID_PARAMETER
;
818 // Update those fields which don't have INTERACTIVE attribute.
820 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
821 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
822 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
824 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
825 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
826 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
828 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
829 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
832 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
835 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
837 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
838 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
842 // Only do full parameter validation if iSCSI is enabled on this device.
844 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
845 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
847 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
849 L
"Connection Establishing Timeout is less than minimum value 100ms.",
853 return EFI_INVALID_PARAMETER
;
857 // Validate the address configuration of the Initiator if DHCP isn't
860 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
861 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
862 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
863 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
865 if ((Gateway
.Addr
[0] != 0)) {
866 if (SubnetMask
.Addr
[0] == 0) {
868 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
870 L
"Gateway address is set but subnet mask is zero.",
874 return EFI_INVALID_PARAMETER
;
875 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
877 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
879 L
"Local IP and Gateway are not in the same subnet.",
883 return EFI_INVALID_PARAMETER
;
888 // Validate target configuration if DHCP isn't deployed.
890 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
891 if (!Attempt
->SessionConfigData
.DnsMode
) {
892 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
894 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
896 L
"Target IP is invalid!",
899 return EFI_INVALID_PARAMETER
;
902 if (Attempt
->SessionConfigData
.TargetUrl
[0] == '\0') {
904 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
906 L
"iSCSI target Url should not be NULL!",
909 return EFI_INVALID_PARAMETER
;
914 // Validate iSCSI target name configuration again:
915 // The format of iSCSI target name is already verified in IScsiFormCallback() when
916 // user input the name; here we only check the case user does not input the name.
918 if (Attempt
->SessionConfigData
.TargetName
[0] == '\0') {
920 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
922 L
"iSCSI target name is NULL!",
925 return EFI_INVALID_PARAMETER
;
930 // Validate the authentication info.
932 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
933 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
935 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
937 L
"CHAP Name or CHAP Secret is invalid!",
941 return EFI_INVALID_PARAMETER
;
944 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
945 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
948 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
950 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
953 return EFI_INVALID_PARAMETER
;
958 // Check whether this attempt uses NIC which is already used by existing attempt.
960 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
961 if (SameNicAttempt
!= NULL
) {
962 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
963 if (AttemptName1
== NULL
) {
964 return EFI_OUT_OF_RESOURCES
;
967 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
968 if (AttemptName2
== NULL
) {
969 FreePool (AttemptName1
);
970 return EFI_OUT_OF_RESOURCES
;
973 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
974 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
977 mPrivate
->PortString
,
978 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
979 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
985 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
987 mPrivate
->PortString
,
991 FreePool (AttemptName1
);
992 FreePool (AttemptName2
);
997 // Update the iSCSI Mode data and record it in attempt help info.
999 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
1000 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
1001 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1002 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
1003 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1004 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
1007 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
1008 UnicodeSPrint (IpMode
, 64, L
"IP4");
1009 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
1010 UnicodeSPrint (IpMode
, 64, L
"IP6");
1011 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
1012 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
1015 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
1016 if (NicInfo
== NULL
) {
1017 return EFI_NOT_FOUND
;
1020 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
1021 if (MacString
== NULL
) {
1022 return EFI_OUT_OF_RESOURCES
;
1025 AsciiStrToUnicodeStrS (Attempt
->MacString
, MacString
, ISCSI_MAX_MAC_STRING_LEN
);
1028 mPrivate
->PortString
,
1029 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1030 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
1033 NicInfo
->DeviceNumber
,
1034 NicInfo
->FunctionNumber
,
1039 Attempt
->AttemptTitleHelpToken
= HiiSetString (
1040 mCallbackInfo
->RegisteredHandle
,
1041 Attempt
->AttemptTitleHelpToken
,
1042 mPrivate
->PortString
,
1045 if (Attempt
->AttemptTitleHelpToken
== 0) {
1046 FreePool (MacString
);
1047 return EFI_OUT_OF_RESOURCES
;
1051 // Check whether this attempt is an existing one.
1053 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
1054 if (ExistAttempt
!= NULL
) {
1055 ASSERT (ExistAttempt
== Attempt
);
1057 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
1058 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1061 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1063 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1064 if (mPrivate
->MpioCount
< 1) {
1068 if (--mPrivate
->MpioCount
== 0) {
1069 mPrivate
->EnableMpio
= FALSE
;
1071 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1072 if (mPrivate
->SinglePathCount
< 1) {
1075 mPrivate
->SinglePathCount
--;
1078 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
1079 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1081 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1083 if (mPrivate
->SinglePathCount
< 1) {
1087 mPrivate
->EnableMpio
= TRUE
;
1088 mPrivate
->MpioCount
++;
1089 mPrivate
->SinglePathCount
--;
1091 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
1092 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1094 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1096 if (mPrivate
->MpioCount
< 1) {
1100 if (--mPrivate
->MpioCount
== 0) {
1101 mPrivate
->EnableMpio
= FALSE
;
1103 mPrivate
->SinglePathCount
++;
1105 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
1106 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
++;
1114 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1115 mPrivate
->SinglePathCount
++;
1119 } else if (ExistAttempt
== NULL
) {
1121 // When a new attempt is created, pointer of the attempt is saved to
1122 // mCallbackInfo->Current in IScsiConfigProcessDefault. If input Attempt
1123 // does not match any existing attempt, it should be a new created attempt.
1124 // Save it to system now.
1128 // Save current order number for this attempt.
1130 AttemptConfigOrder
= IScsiGetVariableAndSize (
1133 &AttemptConfigOrderSize
1136 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1140 // Append the new created attempt order to the end.
1142 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
1143 if (AttemptOrderTmp
== NULL
) {
1144 if (AttemptConfigOrder
!= NULL
) {
1145 FreePool (AttemptConfigOrder
);
1147 return EFI_OUT_OF_RESOURCES
;
1150 if (AttemptConfigOrder
!= NULL
) {
1151 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
1152 FreePool (AttemptConfigOrder
);
1155 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
1156 AttemptConfigOrder
= AttemptOrderTmp
;
1157 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
1159 Status
= gRT
->SetVariable (
1162 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1163 AttemptConfigOrderSize
,
1166 FreePool (AttemptConfigOrder
);
1167 if (EFI_ERROR (Status
)) {
1172 // Insert new created attempt to array.
1174 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
1175 mPrivate
->AttemptCount
++;
1177 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1179 // This new Attempt is enabled for MPIO; enable the multipath mode.
1181 mPrivate
->EnableMpio
= TRUE
;
1182 mPrivate
->MpioCount
++;
1183 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1184 mPrivate
->SinglePathCount
++;
1187 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
) {
1247 } else if ((OffSet
>= ATTEMPT_BOOTENABLE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
)) {
1248 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_BOOTENABLE_VAR_OFFSET
) + 1);
1249 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1250 if (Attempt
== NULL
) {
1251 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) {
1315 mPrivate
->SinglePathCount
--;
1318 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
1319 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1321 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1323 if (mPrivate
->SinglePathCount
< 1) {
1327 mPrivate
->EnableMpio
= TRUE
;
1328 mPrivate
->MpioCount
++;
1329 mPrivate
->SinglePathCount
--;
1331 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
1332 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1334 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1336 if (mPrivate
->MpioCount
< 1) {
1340 if (--mPrivate
->MpioCount
== 0) {
1341 mPrivate
->EnableMpio
= FALSE
;
1343 mPrivate
->SinglePathCount
++;
1345 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
1346 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
1348 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1350 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1351 mPrivate
->EnableMpio
= TRUE
;
1352 mPrivate
->MpioCount
++;
1354 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1355 mPrivate
->SinglePathCount
++;
1358 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1360 } else if ((OffSet
>= ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_RETRY_VAR_OFFSET
)) {
1361 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) + 1);
1362 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1363 if (Attempt
== NULL
) {
1364 return EFI_INVALID_PARAMETER
;
1366 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->ISCSIIpAddressTypeList
[AttemptIndex
- 1];
1367 if (Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
1368 Attempt
->AutoConfigureMode
= 0;
1371 } else if ((OffSet
>= ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
)) {
1372 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) + 1);
1373 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1374 if (Attempt
== NULL
) {
1375 return EFI_INVALID_PARAMETER
;
1378 if (IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1] > CONNECT_MAX_RETRY
) {
1380 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1382 L
"The minimum value is 0 and the maximum is 16. 0 means no retry.",
1385 return EFI_INVALID_PARAMETER
;
1387 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1];
1389 } else if ((OffSet
>= ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
)) {
1390 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) / 2 + 1);
1391 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1392 if (Attempt
== NULL
) {
1393 return EFI_INVALID_PARAMETER
;
1396 if ((IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1] < CONNECT_MIN_TIMEOUT
) ||
1397 (IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1] > CONNECT_MAX_TIMEOUT
)) {
1399 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1401 L
"The minimum value is 100 milliseconds and the maximum is 20 seconds.",
1404 return EFI_INVALID_PARAMETER
;
1407 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1];
1408 if (Attempt
->SessionConfigData
.ConnectTimeout
== 0) {
1409 Attempt
->SessionConfigData
.ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1412 } else if ((OffSet
>= ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
)) {
1413 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) + 1);
1414 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1415 if (Attempt
== NULL
) {
1416 return EFI_INVALID_PARAMETER
;
1418 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->ISCSIInitiatorInfoViaDHCP
[AttemptIndex
- 1];
1420 } else if ((OffSet
>= ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
)) {
1421 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) + 1);
1422 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1423 if (Attempt
== NULL
) {
1424 return EFI_INVALID_PARAMETER
;
1427 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1428 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->ISCSITargetInfoViaDHCP
[AttemptIndex
- 1];
1431 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1433 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1436 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
;
1445 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1446 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->ISCSITargetTcpPort
[AttemptIndex
- 1];
1447 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
1448 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1452 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1454 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1457 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];
1469 } else if ((OffSet
>= ATTEMPT_CHARTYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ISID_VAR_OFFSET
)) {
1470 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CHARTYPE_VAR_OFFSET
) + 1);
1471 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1472 if (Attempt
== NULL
) {
1473 return EFI_INVALID_PARAMETER
;
1475 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1476 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->ISCSIChapType
[AttemptIndex
- 1];
1479 } else if (OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) {
1480 Index
= (UINT8
) ((OffSet
- ATTEMPT_ISID_VAR_OFFSET
) / sizeof (KEYWORD_STR
));
1481 AttemptIndex
= Index
+ 1;
1482 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1483 if (Attempt
== NULL
) {
1484 return EFI_INVALID_PARAMETER
;
1487 OffSet
= OffSet
- Index
* sizeof (KEYWORD_STR
);
1489 if ((OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
)) {
1490 IScsiParseIsIdFromString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, Attempt
->SessionConfigData
.IsId
);
1492 } else if ((OffSet
>= ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
)) {
1493 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1497 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
, &HostIp
.v4
);
1498 if (EFI_ERROR (Status
) || ((Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1499 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
)))) {
1501 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1503 L
"Invalid IP address!",
1506 return EFI_INVALID_PARAMETER
;
1508 CopyMem (&Attempt
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
1512 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1514 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1517 return EFI_INVALID_PARAMETER
;
1520 } else if ((OffSet
>= ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
)) {
1521 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1522 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
, &SubnetMask
.v4
);
1523 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
1525 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1527 L
"Invalid Subnet Mask!",
1530 return EFI_INVALID_PARAMETER
;
1532 CopyMem (&Attempt
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
1536 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1538 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1541 return EFI_INVALID_PARAMETER
;
1544 } else if ((OffSet
>= ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_NAME_VAR_OFFSET
)) {
1545 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1546 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
, &Gateway
.v4
);
1547 if (EFI_ERROR (Status
) ||
1548 ((Gateway
.Addr
[0] != 0) && (Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1549 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
)))) {
1551 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1553 L
"Invalid Gateway!",
1556 return EFI_INVALID_PARAMETER
;
1558 CopyMem (&Attempt
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
1562 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1564 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1567 return EFI_INVALID_PARAMETER
;
1570 } else if ((OffSet
>= ATTEMPT_TARGET_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
)) {
1571 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1572 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
1573 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
1574 if (EFI_ERROR (Status
)) {
1576 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1578 L
"Invalid iSCSI Name!",
1582 AsciiStrCpyS (Attempt
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
1584 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1585 if (Attempt
->SessionConfigData
.TargetName
[0] == L
'\0') {
1587 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1589 L
"iSCSI target name is NULL!",
1592 return EFI_INVALID_PARAMETER
;
1597 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1599 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1602 return EFI_INVALID_PARAMETER
;
1605 } else if ((OffSet
>= ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_LUN_VAR_OFFSET
)) {
1606 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1607 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, IpString
, sizeof (IpString
));
1608 Status
= IScsiAsciiStrToIp (IpString
, Attempt
->SessionConfigData
.IpMode
, &HostIp
);
1609 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, Attempt
->SessionConfigData
.IpMode
)) {
1610 Attempt
->SessionConfigData
.DnsMode
= TRUE
;
1611 ZeroMem (&Attempt
->SessionConfigData
.TargetIp
, sizeof (Attempt
->SessionConfigData
.TargetIp
));
1612 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, Attempt
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
1614 Attempt
->SessionConfigData
.DnsMode
= FALSE
;
1615 CopyMem (&Attempt
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
1619 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1621 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1624 return EFI_INVALID_PARAMETER
;
1627 } else if ((OffSet
>= ATTEMPT_LUN_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
)) {
1628 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.TargetInfoFromDhcp
== 0)) {
1632 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSILun
, LunString
, ISCSI_LUN_STR_MAX_LEN
);
1633 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
1634 if (EFI_ERROR (Status
)) {
1636 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1638 L
"Invalid LUN string, Examples are: 4752-3A4F-6b7e-2F99, 6734-9-156f-127, 4186-9!",
1642 CopyMem (&Attempt
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
1646 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1648 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1651 return EFI_INVALID_PARAMETER
;
1654 } else if ((OffSet
>= ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_SECRET_VAR_OFFSET
)) {
1655 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1656 UnicodeStrToAsciiStrS (
1657 IfrNvData
->Keyword
[Index
].ISCSIChapUsername
,
1658 Attempt
->AuthConfigData
.CHAP
.CHAPName
,
1659 ISCSI_CHAP_NAME_STORAGE
1662 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1663 if (IfrNvData
->Keyword
[Index
].ISCSIChapUsername
[0] == L
'\0') {
1665 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1667 L
"CHAP Name is invalid!",
1670 return EFI_INVALID_PARAMETER
;
1675 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1677 L
"Invalid Configuration, Check value of AuthenticationType!",
1680 return EFI_INVALID_PARAMETER
;
1683 } else if ((OffSet
>= ATTEMPT_CHAR_SECRET_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
)) {
1684 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1685 ChapSecretLen
= (UINT8
)StrLen (IfrNvData
->Keyword
[Index
].ISCSIChapSecret
);
1686 UnicodeStrToAsciiStrS (
1687 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
1688 Attempt
->AuthConfigData
.CHAP
.CHAPSecret
,
1689 ISCSI_CHAP_SECRET_STORAGE
1692 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1693 if ((ChapSecretLen
< ISCSI_CHAP_SECRET_MIN_LEN
) || (ChapSecretLen
> ISCSI_CHAP_SECRET_MAX_LEN
)) {
1695 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1697 L
"The Chap Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1700 return EFI_INVALID_PARAMETER
;
1705 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1707 L
"Invalid Configuration, Check value of AuthenticationType!",
1710 return EFI_INVALID_PARAMETER
;
1713 } else if ((OffSet
>= ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
)) {
1714 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1715 UnicodeStrToAsciiStrS (
1716 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
1717 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPName
,
1718 ISCSI_CHAP_NAME_STORAGE
1720 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1721 if (IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
[0] == L
'\0') {
1723 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1725 L
"Reverse CHAP Name is invalid!",
1728 return EFI_INVALID_PARAMETER
;
1733 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1735 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1738 return EFI_INVALID_PARAMETER
;
1741 } else if (OffSet
>= ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
) {
1742 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1743 ReverseChapSecretLen
= (UINT8
)StrLen (IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
);
1744 UnicodeStrToAsciiStrS (
1745 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
1746 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
1747 ISCSI_CHAP_SECRET_STORAGE
1750 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1751 if ((ReverseChapSecretLen
< ISCSI_CHAP_SECRET_MIN_LEN
) || (ReverseChapSecretLen
> ISCSI_CHAP_SECRET_MAX_LEN
)) {
1753 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1755 L
"The Reverse CHAP Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1758 return EFI_INVALID_PARAMETER
;
1763 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1765 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1768 return EFI_INVALID_PARAMETER
;
1776 // Record the user configuration information in NVR.
1778 ASSERT (Attempt
!= NULL
);
1779 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1780 return gRT
->SetVariable (
1781 mPrivate
->PortString
,
1782 &gEfiIScsiInitiatorNameProtocolGuid
,
1783 ISCSI_CONFIG_VAR_ATTR
,
1784 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1791 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
1794 @param[in] StartLabelNumber The number of start label.
1795 @param[out] StartOpCodeHandle Points to the start opcode handle.
1796 @param[out] StartLabel Points to the created start opcode.
1797 @param[out] EndOpCodeHandle Points to the end opcode handle.
1798 @param[out] EndLabel Points to the created end opcode.
1800 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
1802 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1803 @retval EFI_SUCCESS The operation is completed successfully.
1808 IN UINT16 StartLabelNumber
,
1809 OUT VOID
**StartOpCodeHandle
,
1810 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
1811 OUT VOID
**EndOpCodeHandle
,
1812 OUT EFI_IFR_GUID_LABEL
**EndLabel
1816 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
1817 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
1819 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
1820 return EFI_INVALID_PARAMETER
;
1823 *StartOpCodeHandle
= NULL
;
1824 *EndOpCodeHandle
= NULL
;
1825 Status
= EFI_OUT_OF_RESOURCES
;
1828 // Initialize the container for dynamic opcodes.
1830 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1831 if (*StartOpCodeHandle
== NULL
) {
1835 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1836 if (*EndOpCodeHandle
== NULL
) {
1841 // Create Hii Extend Label OpCode as the start opcode.
1843 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1847 sizeof (EFI_IFR_GUID_LABEL
)
1849 if (InternalStartLabel
== NULL
) {
1853 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1854 InternalStartLabel
->Number
= StartLabelNumber
;
1857 // Create Hii Extend Label OpCode as the end opcode.
1859 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1863 sizeof (EFI_IFR_GUID_LABEL
)
1865 if (InternalEndLabel
== NULL
) {
1869 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1870 InternalEndLabel
->Number
= LABEL_END
;
1872 *StartLabel
= InternalStartLabel
;
1873 *EndLabel
= InternalEndLabel
;
1879 if (*StartOpCodeHandle
!= NULL
) {
1880 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
1883 if (*EndOpCodeHandle
!= NULL
) {
1884 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
1890 Update the MAIN form to display the configured attempts.
1894 IScsiConfigUpdateAttempt (
1899 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1900 VOID
*StartOpCodeHandle
;
1901 EFI_IFR_GUID_LABEL
*StartLabel
;
1902 VOID
*EndOpCodeHandle
;
1903 EFI_IFR_GUID_LABEL
*EndLabel
;
1906 Status
= IScsiCreateOpCode (
1907 ATTEMPT_ENTRY_LABEL
,
1913 if (EFI_ERROR (Status
)) {
1917 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1918 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1919 if (AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
1921 // Update Attempt Help Info.
1923 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", (UINTN
) AttemptConfigData
->AttemptConfigIndex
);
1924 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1925 mCallbackInfo
->RegisteredHandle
,
1927 mPrivate
->PortString
,
1930 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1934 HiiCreateGotoOpCode (
1935 StartOpCodeHandle
, // Container for dynamic created opcodes
1936 FORMID_ATTEMPT_FORM
, // Form ID
1937 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1938 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1939 EFI_IFR_FLAG_CALLBACK
, // Question flag
1940 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1946 mCallbackInfo
->RegisteredHandle
, // HII handle
1947 &gIScsiConfigGuid
, // Formset GUID
1948 FORMID_MAIN_FORM
, // Form ID
1949 StartOpCodeHandle
, // Label for where to insert opcodes
1950 EndOpCodeHandle
// Replace data
1953 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1954 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1958 Callback function when user presses "Add an Attempt".
1960 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1962 @retval EFI_SUCCESS The operation is completed successfully.
1966 IScsiConfigAddAttempt (
1971 ISCSI_NIC_INFO
*NicInfo
;
1972 EFI_STRING_ID PortTitleToken
;
1973 EFI_STRING_ID PortTitleHelpToken
;
1974 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1976 VOID
*StartOpCodeHandle
;
1977 EFI_IFR_GUID_LABEL
*StartLabel
;
1978 VOID
*EndOpCodeHandle
;
1979 EFI_IFR_GUID_LABEL
*EndLabel
;
1981 Status
= IScsiCreateOpCode (
1988 if (EFI_ERROR (Status
)) {
1993 // Ask user to select a MAC for this attempt.
1995 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
1996 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
1998 &NicInfo
->PermanentAddress
,
1999 NicInfo
->HwAddressSize
,
2004 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
2005 PortTitleToken
= HiiSetString (
2006 mCallbackInfo
->RegisteredHandle
,
2008 mPrivate
->PortString
,
2011 if (PortTitleToken
== 0) {
2012 Status
= EFI_INVALID_PARAMETER
;
2017 mPrivate
->PortString
,
2018 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2019 L
"PFA: Bus %d | Dev %d | Func %d",
2021 NicInfo
->DeviceNumber
,
2022 NicInfo
->FunctionNumber
2024 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
2025 if (PortTitleHelpToken
== 0) {
2026 Status
= EFI_INVALID_PARAMETER
;
2030 HiiCreateGotoOpCode (
2031 StartOpCodeHandle
, // Container for dynamic created opcodes
2032 FORMID_ATTEMPT_FORM
,
2035 EFI_IFR_FLAG_CALLBACK
, // Question flag
2036 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
2040 Status
= HiiUpdateForm (
2041 mCallbackInfo
->RegisteredHandle
, // HII handle
2042 &gIScsiConfigGuid
, // Formset GUID
2043 FORMID_MAC_FORM
, // Form ID
2044 StartOpCodeHandle
, // Label for where to insert opcodes
2045 EndOpCodeHandle
// Replace data
2049 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2050 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2056 Add the attempts by keyword 'iSCSIAddAttempts', you can use this keyword with
2057 value 'attempt:1 attempt:2' etc to add one or more attempts once. This is different
2058 with IScsiConfigAddAttempt function which is used to add attempt by UI configuration.
2060 @param[in] AttemptList The new attempt List will be added.
2062 @retval EFI_SUCCESS The operation to add attempt list successfully.
2063 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2064 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2065 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2070 IScsiConfigAddAttemptsByKeywords (
2071 IN UINT8
*AttemptList
2078 UINT8
*AttemptConfigOrder
;
2079 UINTN AttemptConfigOrderSize
;
2080 UINT8
*AttemptConfigOrderTmp
;
2081 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2082 ISCSI_NIC_INFO
*NicInfo
;
2083 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2084 CHAR16 IScsiMode
[64];
2088 Nic
= mPrivate
->CurrentNic
;
2089 NicInfo
= IScsiGetNicInfoByIndex (Nic
);
2090 if (NicInfo
== NULL
) {
2091 return EFI_NOT_FOUND
;
2095 // The MAC info will be recorded in Config Data.
2098 &NicInfo
->PermanentAddress
,
2099 NicInfo
->HwAddressSize
,
2104 for (Index
= 0; Index
< PcdGet8 (PcdMaxIScsiAttemptNumber
); Index
++) {
2105 if (AttemptList
[Index
] == 0) {
2112 Number
= AttemptList
[Index
];
2115 mPrivate
->PortString
,
2116 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2122 mPrivate
->PortString
,
2123 &gEfiIScsiInitiatorNameProtocolGuid
,
2124 (VOID
**)&AttemptConfigData
,
2127 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2128 return EFI_INVALID_PARAMETER
;
2131 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2132 AttemptConfigData
->NicIndex
= NicInfo
->NicIndex
;
2133 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, ISCSI_MAX_MAC_STRING_LEN
);
2136 // Generate OUI-format ISID based on MAC address.
2138 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2139 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2140 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2143 // Configure the iSCSI Mode and IpMode to default.
2144 // Add Attempt Help Info.
2146 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
2147 UnicodeSPrint (IpMode
, 64, L
"IP4");
2149 mPrivate
->PortString
,
2150 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2151 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
2154 NicInfo
->DeviceNumber
,
2155 NicInfo
->FunctionNumber
,
2160 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2161 mCallbackInfo
->RegisteredHandle
,
2163 mPrivate
->PortString
,
2166 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2167 return EFI_OUT_OF_RESOURCES
;
2171 // Get current Attempt order and number.
2173 AttemptConfigOrder
= IScsiGetVariableAndSize (
2176 &AttemptConfigOrderSize
2178 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2182 // Append the new created attempt order to the end.
2184 AttemptConfigOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
2185 if (AttemptConfigOrderTmp
== NULL
) {
2186 if (AttemptConfigOrder
!= NULL
) {
2187 FreePool (AttemptConfigOrder
);
2189 return EFI_OUT_OF_RESOURCES
;
2191 if (AttemptConfigOrder
!= NULL
) {
2192 CopyMem (AttemptConfigOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
2193 FreePool (AttemptConfigOrder
);
2196 AttemptConfigOrderTmp
[TotalNumber
- 1] = Number
;
2197 AttemptConfigOrder
= AttemptConfigOrderTmp
;
2198 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
2200 Status
= gRT
->SetVariable (
2203 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2204 AttemptConfigOrderSize
,
2207 FreePool (AttemptConfigOrder
);
2208 if (EFI_ERROR (Status
)) {
2213 // Record the attempt in global link list.
2215 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2216 mPrivate
->AttemptCount
++;
2217 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", AttemptConfigData
->AttemptConfigIndex
);
2219 mPrivate
->PortString
,
2220 &gEfiIScsiInitiatorNameProtocolGuid
,
2221 ISCSI_CONFIG_VAR_ATTR
,
2222 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2232 Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword.
2234 @param[in] IfrNvData The IFR NV data.
2236 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2237 @retval EFI_SUCCESS The operation is completed successfully.
2238 @retval EFI_ABOTRED This operation is aborted cause of error
2240 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2245 IScsiConfigDeleteAttempts (
2246 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2252 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2253 UINT8
*AttemptConfigOrder
;
2254 UINTN AttemptConfigOrderSize
;
2255 UINT8
*AttemptNewOrder
;
2256 UINT8 AttemptConfigIndex
;
2261 LIST_ENTRY
*NextEntry
;
2262 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
2266 AttemptConfigOrder
= IScsiGetVariableAndSize (
2269 &AttemptConfigOrderSize
2271 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
2272 return EFI_NOT_FOUND
;
2275 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
2276 if (AttemptNewOrder
== NULL
) {
2277 Status
= EFI_OUT_OF_RESOURCES
;
2281 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2284 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
2285 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
2291 // Delete the attempt.
2294 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2297 // Remove this attempt from UI configured attempt list.
2299 RemoveEntryList (&AttemptConfigData
->Link
);
2300 mPrivate
->AttemptCount
--;
2302 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
2303 if (mPrivate
->MpioCount
< 1) {
2304 Status
= EFI_ABORTED
;
2309 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
2311 if (--mPrivate
->MpioCount
== 0) {
2312 mPrivate
->EnableMpio
= FALSE
;
2314 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
2315 if (mPrivate
->SinglePathCount
< 1) {
2316 Status
= EFI_ABORTED
;
2320 mPrivate
->SinglePathCount
--;
2323 AttemptConfigIndex
= AttemptConfigData
->AttemptConfigIndex
;
2324 FreePool (AttemptConfigData
);
2327 // Create a new Attempt
2329 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
2330 if (AttemptConfigData
== NULL
) {
2331 return EFI_OUT_OF_RESOURCES
;
2333 ConfigData
= &AttemptConfigData
->SessionConfigData
;
2334 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
2335 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
2336 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
2338 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
2339 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
2341 // Configure the Attempt index and set variable.
2343 AttemptConfigData
->AttemptConfigIndex
= AttemptConfigIndex
;
2346 // Set the attempt name to default.
2349 mPrivate
->PortString
,
2350 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2352 (UINTN
) AttemptConfigData
->AttemptConfigIndex
2354 UnicodeStrToAsciiStrS (mPrivate
->PortString
, AttemptConfigData
->AttemptName
, ATTEMPT_NAME_SIZE
);
2356 mPrivate
->PortString
,
2357 &gEfiIScsiInitiatorNameProtocolGuid
,
2358 ISCSI_CONFIG_VAR_ATTR
,
2359 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2364 // Mark the attempt order in NVR to be deleted - 0.
2366 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
2367 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
2368 AttemptConfigOrder
[NewIndex
] = 0;
2374 if (mCallbackInfo
->Current
== AttemptConfigData
) {
2375 mCallbackInfo
->Current
= NULL
;
2377 FreePool (AttemptConfigData
);
2380 // Check next Attempt.
2386 // Construct AttemptNewOrder.
2388 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
2389 if (AttemptConfigOrder
[Index
] != 0) {
2390 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
2395 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
2398 // Update AttemptOrder in NVR.
2400 Status
= gRT
->SetVariable (
2404 NewTotal
* sizeof (UINT8
),
2409 if (AttemptConfigOrder
!= NULL
) {
2410 FreePool (AttemptConfigOrder
);
2413 if (AttemptNewOrder
!= NULL
) {
2414 FreePool (AttemptNewOrder
);
2422 Callback function when user presses "Delete Attempts".
2424 @param[in] IfrNvData The IFR nv data.
2426 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2427 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
2428 @retval EFI_SUCCESS The operation is completed successfully.
2432 IScsiConfigDisplayDeleteAttempts (
2433 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2437 UINT8
*AttemptConfigOrder
;
2438 UINTN AttemptConfigOrderSize
;
2440 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2442 VOID
*StartOpCodeHandle
;
2443 EFI_IFR_GUID_LABEL
*StartLabel
;
2444 VOID
*EndOpCodeHandle
;
2445 EFI_IFR_GUID_LABEL
*EndLabel
;
2448 Status
= IScsiCreateOpCode (
2455 if (EFI_ERROR (Status
)) {
2459 AttemptConfigOrder
= IScsiGetVariableAndSize (
2462 &AttemptConfigOrderSize
2464 if (AttemptConfigOrder
!= NULL
) {
2466 // Create the check box opcode to be deleted.
2470 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2471 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2472 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
2474 HiiCreateCheckBoxOpCode(
2476 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
2477 CONFIGURATION_VARSTORE_ID
,
2478 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
2479 AttemptConfigData
->AttemptTitleToken
,
2480 AttemptConfigData
->AttemptTitleHelpToken
,
2488 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
2493 FreePool (AttemptConfigOrder
);
2496 Status
= HiiUpdateForm (
2497 mCallbackInfo
->RegisteredHandle
, // HII handle
2498 &gIScsiConfigGuid
, // Formset GUID
2499 FORMID_DELETE_FORM
, // Form ID
2500 StartOpCodeHandle
, // Label for where to insert opcodes
2501 EndOpCodeHandle
// Replace data
2504 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2505 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2512 Callback function when user presses "Change Attempt Order".
2514 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2515 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2517 @retval EFI_SUCCESS The operation is completed successfully.
2521 IScsiConfigDisplayOrderAttempts (
2528 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2529 VOID
*StartOpCodeHandle
;
2530 EFI_IFR_GUID_LABEL
*StartLabel
;
2531 VOID
*EndOpCodeHandle
;
2532 EFI_IFR_GUID_LABEL
*EndLabel
;
2533 VOID
*OptionsOpCodeHandle
;
2535 Status
= IScsiCreateOpCode (
2542 if (EFI_ERROR (Status
)) {
2545 ASSERT (StartOpCodeHandle
!= NULL
);
2547 OptionsOpCodeHandle
= NULL
;
2550 // If no attempt to be ordered, update the original form and exit.
2552 if (mPrivate
->AttemptCount
== 0) {
2557 // Create Option OpCode.
2559 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
2560 if (OptionsOpCodeHandle
== NULL
) {
2561 Status
= EFI_OUT_OF_RESOURCES
;
2567 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2568 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2569 HiiCreateOneOfOptionOpCode (
2570 OptionsOpCodeHandle
,
2571 AttemptConfigData
->AttemptTitleToken
,
2573 EFI_IFR_NUMERIC_SIZE_1
,
2574 AttemptConfigData
->AttemptConfigIndex
2579 ASSERT (Index
== mPrivate
->AttemptCount
);
2581 HiiCreateOrderedListOpCode (
2582 StartOpCodeHandle
, // Container for dynamic created opcodes
2583 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
2584 CONFIGURATION_VARSTORE_ID
, // VarStore ID
2585 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
2586 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
2587 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
2589 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
2590 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
2591 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
2592 OptionsOpCodeHandle
, // Option Opcode list
2593 NULL
// Default Opcode is NULL
2597 Status
= HiiUpdateForm (
2598 mCallbackInfo
->RegisteredHandle
, // HII handle
2599 &gIScsiConfigGuid
, // Formset GUID
2600 FORMID_ORDER_FORM
, // Form ID
2601 StartOpCodeHandle
, // Label for where to insert opcodes
2602 EndOpCodeHandle
// Replace data
2606 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2607 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2608 if (OptionsOpCodeHandle
!= NULL
) {
2609 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
2616 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.
2618 @param[in] IfrNvData The IFR nv data.
2620 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2622 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2623 @retval EFI_SUCCESS The operation is completed successfully.
2627 IScsiConfigOrderAttempts (
2628 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2634 UINT8 AttemptConfigIndex
;
2635 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2636 UINT8
*AttemptConfigOrder
;
2637 UINT8
*AttemptConfigOrderTmp
;
2638 UINTN AttemptConfigOrderSize
;
2640 AttemptConfigOrder
= IScsiGetVariableAndSize (
2643 &AttemptConfigOrderSize
2645 if (AttemptConfigOrder
== NULL
) {
2646 return EFI_NOT_FOUND
;
2649 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
2650 if (AttemptConfigOrderTmp
== NULL
) {
2651 Status
= EFI_OUT_OF_RESOURCES
;
2655 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
2657 // The real content ends with 0.
2659 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
2663 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
2664 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
2665 if (AttemptConfigData
== NULL
) {
2666 Status
= EFI_NOT_FOUND
;
2671 // Reorder the Attempt List.
2673 RemoveEntryList (&AttemptConfigData
->Link
);
2674 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2676 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
2679 // Mark it to be deleted - 0.
2681 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2682 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
2683 AttemptConfigOrder
[Indexj
] = 0;
2690 // Adjust the attempt order in NVR.
2692 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2693 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2694 if (AttemptConfigOrder
[Indexj
] != 0) {
2695 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
2696 AttemptConfigOrder
[Indexj
] = 0;
2702 Status
= gRT
->SetVariable (
2705 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2706 AttemptConfigOrderSize
,
2707 AttemptConfigOrderTmp
2711 if (AttemptConfigOrderTmp
!= NULL
) {
2712 FreePool (AttemptConfigOrderTmp
);
2715 FreePool (AttemptConfigOrder
);
2721 Callback function when a user presses "Attempt *" or when a user selects a NIC to
2722 create the new attempt.
2724 @param[in] KeyValue A unique value which is sent to the original
2725 exporting driver so that it can identify the type
2727 @param[in] IfrNvData The IFR nv data.
2729 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2731 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2732 @retval EFI_UNSUPPORTED Can not create more attempts.
2733 @retval EFI_SUCCESS The operation is completed successfully.
2737 IScsiConfigProcessDefault (
2738 IN EFI_QUESTION_ID KeyValue
,
2739 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2743 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2744 UINT8 CurrentAttemptConfigIndex
;
2745 ISCSI_NIC_INFO
*NicInfo
;
2747 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2748 UINT8
*AttemptConfigOrder
;
2749 UINTN AttemptConfigOrderSize
;
2753 AttemptConfigData
= NULL
;
2755 // Is User creating a new attempt?
2759 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
2760 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
2762 // User has pressed "Add an Attempt" and then selects a NIC.
2765 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
2766 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
2769 // User has pressed "Attempt *".
2774 // Don't process anything.
2781 // Determine which NIC user has selected for the new created attempt.
2783 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
2784 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
2785 if (NicInfo
== NULL
) {
2786 return EFI_NOT_FOUND
;
2790 // Create an attempt following the initialized attempt order.
2792 AttemptConfigOrder
= IScsiGetVariableAndSize (
2793 L
"InitialAttemptOrder",
2795 &AttemptConfigOrderSize
2798 if (AttemptConfigOrder
== NULL
) {
2799 return EFI_NOT_FOUND
;
2802 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2804 mPrivate
->PortString
,
2805 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2807 (UINTN
) AttemptConfigOrder
[Index
]
2810 mPrivate
->PortString
,
2811 &gEfiIScsiInitiatorNameProtocolGuid
,
2812 (VOID
**)&AttemptConfigData
,
2815 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2822 if (Index
> PcdGet8 (PcdMaxIScsiAttemptNumber
)) {
2824 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2826 L
"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",
2829 return EFI_UNSUPPORTED
;
2832 if (AttemptConfigOrder
!= NULL
) {
2833 FreePool (AttemptConfigOrder
);
2837 // Record the MAC info in Config Data.
2840 &NicInfo
->PermanentAddress
,
2841 NicInfo
->HwAddressSize
,
2846 ASSERT (AttemptConfigData
!= NULL
);
2847 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, sizeof (AttemptConfigData
->MacString
));
2848 AttemptConfigData
->NicIndex
= NicIndex
;
2849 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2852 // Generate OUI-format ISID based on MAC address.
2854 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2855 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2856 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2859 // Add the help info for the new attempt.
2862 mPrivate
->PortString
,
2863 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2864 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
2867 NicInfo
->DeviceNumber
,
2868 NicInfo
->FunctionNumber
2871 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2872 mCallbackInfo
->RegisteredHandle
,
2874 mPrivate
->PortString
,
2877 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2878 FreePool (AttemptConfigData
);
2879 return EFI_OUT_OF_RESOURCES
;
2884 // Determine which Attempt user has selected to configure.
2885 // Get the attempt configuration data.
2887 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
2889 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
2890 if (AttemptConfigData
== NULL
) {
2891 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
2892 return EFI_NOT_FOUND
;
2897 // Clear the old IFR data to avoid sharing it with other attempts.
2899 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
2900 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
2901 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
2902 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
2903 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
2906 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
2909 // Update current attempt to be a new created attempt or an existing attempt.
2911 mCallbackInfo
->Current
= AttemptConfigData
;
2919 This function allows the caller to request the current
2920 configuration for one or more named elements. The resulting
2921 string is in <ConfigAltResp> format. Also, any and all alternative
2922 configuration strings shall be appended to the end of the
2923 current configuration string. If they are, they must appear
2924 after the current configuration. They must contain the same
2925 routing (GUID, NAME, PATH) as the current configuration string.
2926 They must have an additional description indicating the type of
2927 alternative configuration the string represents,
2928 "ALTCFG=<StringToken>". That <StringToken> (when
2929 converted from Hex UNICODE to binary) is a reference to a
2930 string in the associated string pack.
2932 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2934 @param[in] Request A null-terminated Unicode string in
2935 <ConfigRequest> format. Note that this
2936 includes the routing information as well as
2937 the configurable name / value pairs. It is
2938 invalid for this string to be in
2939 <MultiConfigRequest> format.
2941 @param[out] Progress On return, points to a character in the
2942 Request string. Points to the string's null
2943 terminator if request was successful. Points
2944 to the most recent "&" before the first
2945 failing name / value pair (or the beginning
2946 of the string if the failure is in the first
2947 name / value pair) if the request was not successful.
2949 @param[out] Results A null-terminated Unicode string in
2950 <ConfigAltResp> format which has all values
2951 filled in for the names in the Request string.
2952 String to be allocated by the called function.
2954 @retval EFI_SUCCESS The Results string is filled with the
2955 values corresponding to all requested
2958 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2959 parts of the results that must be
2960 stored awaiting possible future
2963 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
2964 for the Request parameter
2965 would result in this type of
2966 error. In this case, the
2967 Progress parameter would be
2970 @retval EFI_NOT_FOUND Routing data doesn't match any
2971 known driver. Progress set to the
2972 first character in the routing header.
2973 Note: There is no requirement that the
2974 driver validate the routing data. It
2975 must skip the <ConfigHdr> in order to
2978 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
2979 to most recent "&" before the
2980 error or the beginning of the
2983 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
2984 to the & before the name in
2990 IScsiFormExtractConfig (
2991 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2992 IN CONST EFI_STRING Request
,
2993 OUT EFI_STRING
*Progress
,
2994 OUT EFI_STRING
*Results
2998 CHAR8
*InitiatorName
;
3000 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3001 ISCSI_FORM_CALLBACK_INFO
*Private
;
3002 EFI_STRING ConfigRequestHdr
;
3003 EFI_STRING ConfigRequest
;
3004 BOOLEAN AllocatedRequest
;
3007 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3008 return EFI_INVALID_PARAMETER
;
3011 *Progress
= Request
;
3012 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3013 return EFI_NOT_FOUND
;
3016 ConfigRequestHdr
= NULL
;
3017 ConfigRequest
= NULL
;
3018 AllocatedRequest
= FALSE
;
3021 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3022 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3023 if (IfrNvData
== NULL
) {
3024 return EFI_OUT_OF_RESOURCES
;
3028 if (Private
->Current
!= NULL
) {
3029 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
3033 // Extract all AttemptConfigData to Keyword stroage of IfrNvData.
3035 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData
);
3037 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3038 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3039 if (InitiatorName
== NULL
) {
3040 FreePool (IfrNvData
);
3041 return EFI_OUT_OF_RESOURCES
;
3044 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3045 if (EFI_ERROR (Status
)) {
3046 IfrNvData
->InitiatorName
[0] = L
'\0';
3048 AsciiStrToUnicodeStrS (
3050 IfrNvData
->InitiatorName
,
3051 sizeof (IfrNvData
->InitiatorName
) / sizeof (IfrNvData
->InitiatorName
[0])
3056 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
3058 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3059 ConfigRequest
= Request
;
3060 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3062 // Request has no request element, construct full request string.
3063 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3064 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3066 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
3067 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3068 ConfigRequest
= AllocateZeroPool (Size
);
3069 if (ConfigRequest
== NULL
) {
3070 FreePool (IfrNvData
);
3071 FreePool (InitiatorName
);
3072 return EFI_OUT_OF_RESOURCES
;
3074 AllocatedRequest
= TRUE
;
3075 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3076 FreePool (ConfigRequestHdr
);
3079 Status
= gHiiConfigRouting
->BlockToConfig (
3082 (UINT8
*) IfrNvData
,
3087 FreePool (IfrNvData
);
3088 FreePool (InitiatorName
);
3091 // Free the allocated config request string.
3093 if (AllocatedRequest
) {
3094 FreePool (ConfigRequest
);
3095 ConfigRequest
= NULL
;
3098 // Set Progress string to the original request string.
3100 if (Request
== NULL
) {
3102 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3103 *Progress
= Request
+ StrLen (Request
);
3112 This function applies changes in a driver's configuration.
3113 Input is a Configuration, which has the routing data for this
3114 driver followed by name / value configuration pairs. The driver
3115 must apply those pairs to its configurable storage. If the
3116 driver's configuration is stored in a linear block of data
3117 and the driver's name / value pairs are in <BlockConfig>
3118 format, it may use the ConfigToBlock helper function (above) to
3121 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3123 @param[in] Configuration A null-terminated Unicode string in
3124 <ConfigString> format.
3126 @param[out] Progress A pointer to a string filled in with the
3127 offset of the most recent '&' before the
3128 first failing name / value pair (or the
3129 beginning of the string if the failure
3130 is in the first name / value pair) or
3131 the terminating NULL if all was
3134 @retval EFI_SUCCESS The results have been distributed or are
3135 awaiting distribution.
3137 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
3138 parts of the results that must be
3139 stored awaiting possible future
3142 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
3143 Results parameter would result
3144 in this type of error.
3146 @retval EFI_NOT_FOUND Target for the specified routing data
3152 IScsiFormRouteConfig (
3153 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3154 IN CONST EFI_STRING Configuration
,
3155 OUT EFI_STRING
*Progress
3159 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3160 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3162 LIST_ENTRY
*NextEntry
;
3163 ISCSI_NIC_INFO
*NicInfo
;
3165 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
3166 CHAR8
*InitiatorName
;
3177 Status
= EFI_SUCCESS
;
3179 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
3180 return EFI_INVALID_PARAMETER
;
3184 // Check routing data in <ConfigHdr>.
3185 // Note: if only one Storage is used, then this checking could be skipped.
3187 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3188 *Progress
= Configuration
;
3189 return EFI_NOT_FOUND
;
3192 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3193 if (IfrNvData
== NULL
) {
3194 return EFI_OUT_OF_RESOURCES
;
3197 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3198 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3199 if (InitiatorName
== NULL
) {
3200 Status
= EFI_OUT_OF_RESOURCES
;
3205 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
3207 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3208 Status
= gHiiConfigRouting
->ConfigToBlock (
3211 (UINT8
*) IfrNvData
,
3215 if (EFI_ERROR (Status
)) {
3219 if (IfrNvData
->InitiatorName
[0] != L
'\0') {
3220 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, InitiatorName
, ISCSI_NAME_MAX_SIZE
);
3221 BufferSize
= AsciiStrSize (InitiatorName
);
3223 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3224 if (EFI_ERROR (Status
)) {
3226 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3228 L
"Invalid iSCSI Name!",
3234 Status
= IScsiGetValue (Configuration
, L
"&OFFSET=", &OffSet
);
3235 if (EFI_ERROR (Status
)) {
3239 if (OffSet
>= ATTEMPT_MAC_ADDR_VAR_OFFSET
) {
3240 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3241 if (EFI_ERROR (Status
)) {
3243 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3245 L
"Error: please configure iSCSI initiator name first!",
3254 if (IfrNvData
->ISCSIAddAttemptList
[0] != L
'\0') {
3255 Status
=IScsiGetAttemptIndexList (IfrNvData
->ISCSIAddAttemptList
, IfrNvData
->AddAttemptList
, TRUE
);
3256 if (EFI_ERROR (Status
)) {
3258 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3260 L
"Error: The add attempt list is invalid",
3266 Status
= IScsiConfigAddAttemptsByKeywords (IfrNvData
->AddAttemptList
);
3267 if (EFI_ERROR (Status
)) {
3271 } else if (IfrNvData
->ISCSIDeleteAttemptList
[0] != L
'\0') {
3272 AttemptList
=(UINT8
*) AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM
+ 1) * sizeof (UINT8
));
3273 if (AttemptList
== NULL
) {
3274 Status
= EFI_OUT_OF_RESOURCES
;
3277 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIDeleteAttemptList
, AttemptList
, FALSE
);
3278 if (EFI_ERROR (Status
)) {
3280 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3282 L
"Error: The delete attempt list is invalid",
3289 // Mark the attempt which will be delete in the global list.
3291 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
3292 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3293 while (AttemptList
[Index
] != 0) {
3294 if (AttemptConfigData
->AttemptConfigIndex
== AttemptList
[Index
]) {
3295 IfrNvData
->DeleteAttemptList
[Index2
] = 1;
3304 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3305 if (EFI_ERROR (Status
)) {
3309 FreePool (AttemptList
);
3311 } else if (IfrNvData
->ISCSIAttemptOrder
[0] != L
'\0') {
3312 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIAttemptOrder
, IfrNvData
->DynamicOrderedList
, FALSE
);
3313 if (EFI_ERROR (Status
)) {
3315 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3317 L
"Error: The new attempt order list is invalid",
3323 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3324 if (EFI_ERROR (Status
)) {
3328 } else if (IfrNvData
->ISCSIMacAddr
[0] != L
'\0') {
3329 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
3330 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3332 &NicInfo
->PermanentAddress
,
3333 NicInfo
->HwAddressSize
,
3337 if (!StrCmp(MacString
, IfrNvData
->ISCSIMacAddr
)) {
3338 mPrivate
->CurrentNic
= NicInfo
->NicIndex
;
3343 if ((NicInfo
== NULL
) || (NicInfo
->NicIndex
== 0)) {
3344 Status
= EFI_NOT_FOUND
;
3349 Status
= IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData
, OffSet
);
3350 if (EFI_ERROR (Status
)) {
3356 IScsiConfigUpdateAttempt ();
3359 if (InitiatorName
!= NULL
) {
3360 FreePool (InitiatorName
);
3363 if (IfrNvData
!= NULL
) {
3364 FreePool (IfrNvData
);
3372 This function is called to provide results data to the driver.
3373 This data consists of a unique key that is used to identify
3374 which data is either being passed back or being asked for.
3376 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3377 @param[in] Action Specifies the type of action taken by the browser.
3378 @param[in] QuestionId A unique value which is sent to the original
3379 exporting driver so that it can identify the type
3380 of data to expect. The format of the data tends to
3381 vary based on the opcode that generated the callback.
3382 @param[in] Type The type of value for the question.
3383 @param[in, out] Value A pointer to the data being sent to the original
3385 @param[out] ActionRequest On return, points to the action requested by the
3388 @retval EFI_SUCCESS The callback successfully handled the action.
3389 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3390 variable and its data.
3391 @retval EFI_DEVICE_ERROR The variable could not be saved.
3392 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3398 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3399 IN EFI_BROWSER_ACTION Action
,
3400 IN EFI_QUESTION_ID QuestionId
,
3402 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
3403 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3406 ISCSI_FORM_CALLBACK_INFO
*Private
;
3409 CHAR8 IpString
[ISCSI_NAME_MAX_SIZE
];
3410 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
3412 EFI_IP_ADDRESS HostIp
;
3413 EFI_IP_ADDRESS SubnetMask
;
3414 EFI_IP_ADDRESS Gateway
;
3415 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3416 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
3419 ISCSI_NIC_INFO
*NicInfo
;
3423 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
3425 // Do nothing for UEFI OPEN/CLOSE Action
3430 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
3432 // All other type return unsupported.
3434 return EFI_UNSUPPORTED
;
3437 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
3438 return EFI_INVALID_PARAMETER
;
3441 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3444 // Retrieve uncommitted data from Browser
3447 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3448 IfrNvData
= AllocateZeroPool (BufferSize
);
3449 if (IfrNvData
== NULL
) {
3450 return EFI_OUT_OF_RESOURCES
;
3453 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
3454 if (IScsiName
== NULL
) {
3455 FreePool (IfrNvData
);
3456 return EFI_OUT_OF_RESOURCES
;
3459 Status
= EFI_SUCCESS
;
3461 ZeroMem (&OldIfrNvData
, BufferSize
);
3463 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
3465 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
3467 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3468 switch (QuestionId
) {
3469 case KEY_ADD_ATTEMPT
:
3471 // Check whether iSCSI initiator name is configured already.
3473 mPrivate
->InitiatorNameLength
= ISCSI_NAME_MAX_SIZE
;
3474 Status
= gIScsiInitiatorName
.Get (
3475 &gIScsiInitiatorName
,
3476 &mPrivate
->InitiatorNameLength
,
3477 mPrivate
->InitiatorName
3479 if (EFI_ERROR (Status
)) {
3481 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3483 L
"Error: please configure iSCSI initiator name first!",
3489 Status
= IScsiConfigAddAttempt ();
3492 case KEY_DELETE_ATTEMPT
:
3494 OldIfrNvData
.DeleteAttemptList
,
3495 IfrNvData
->DeleteAttemptList
,
3496 sizeof (IfrNvData
->DeleteAttemptList
)
3498 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
3501 case KEY_ORDER_ATTEMPT_CONFIG
:
3503 // Order the attempt according to user input.
3506 OldIfrNvData
.DynamicOrderedList
,
3507 IfrNvData
->DynamicOrderedList
,
3508 sizeof (IfrNvData
->DynamicOrderedList
)
3510 IScsiConfigDisplayOrderAttempts ();
3514 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
3517 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3518 switch (QuestionId
) {
3519 case KEY_INITIATOR_NAME
:
3520 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3521 BufferSize
= AsciiStrSize (IScsiName
);
3523 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
3524 if (EFI_ERROR (Status
)) {
3526 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3528 L
"Invalid iSCSI Name!",
3533 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3536 case KEY_SAVE_ATTEMPT_CONFIG
:
3537 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
3538 if (EFI_ERROR (Status
)) {
3542 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3545 case KEY_SAVE_ORDER_CHANGES
:
3547 // Sync the Attempt Order to NVR.
3549 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3550 if (EFI_ERROR (Status
)) {
3554 IScsiConfigUpdateAttempt ();
3555 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3558 case KEY_IGNORE_ORDER_CHANGES
:
3560 IfrNvData
->DynamicOrderedList
,
3561 OldIfrNvData
.DynamicOrderedList
,
3562 sizeof (IfrNvData
->DynamicOrderedList
)
3564 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3567 case KEY_SAVE_DELETE_ATTEMPT
:
3569 // Delete the Attempt Order from NVR
3571 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3572 if (EFI_ERROR (Status
)) {
3576 IScsiConfigUpdateAttempt ();
3577 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3580 case KEY_IGNORE_DELETE_ATTEMPT
:
3582 IfrNvData
->DeleteAttemptList
,
3583 OldIfrNvData
.DeleteAttemptList
,
3584 sizeof (IfrNvData
->DeleteAttemptList
)
3586 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3590 switch (Value
->u8
) {
3592 NicInfo
= IScsiGetNicInfoByIndex (Private
->Current
->NicIndex
);
3593 if(NicInfo
== NULL
) {
3597 if(!NicInfo
->Ipv6Available
) {
3599 // Current NIC doesn't Support IPv6, hence use IPv4.
3601 IfrNvData
->IpMode
= IP_MODE_IP4
;
3604 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3606 L
"Current NIC doesn't Support IPv6!",
3612 ZeroMem (IfrNvData
->LocalIp
, sizeof (IfrNvData
->LocalIp
));
3613 ZeroMem (IfrNvData
->SubnetMask
, sizeof (IfrNvData
->SubnetMask
));
3614 ZeroMem (IfrNvData
->Gateway
, sizeof (IfrNvData
->Gateway
));
3615 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
3616 Private
->Current
->AutoConfigureMode
= 0;
3617 ZeroMem (&Private
->Current
->SessionConfigData
.LocalIp
, sizeof (EFI_IP_ADDRESS
));
3618 ZeroMem (&Private
->Current
->SessionConfigData
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
3619 ZeroMem (&Private
->Current
->SessionConfigData
.Gateway
, sizeof (EFI_IP_ADDRESS
));
3620 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (EFI_IP_ADDRESS
));
3628 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
3629 if (EFI_ERROR (Status
) ||
3630 ((Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3631 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3633 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3635 L
"Invalid IP address!",
3639 Status
= EFI_INVALID_PARAMETER
;
3641 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
3646 case KEY_SUBNET_MASK
:
3647 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
3648 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
3650 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3652 L
"Invalid Subnet Mask!",
3656 Status
= EFI_INVALID_PARAMETER
;
3658 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
3664 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
3665 if (EFI_ERROR (Status
) ||
3666 ((Gateway
.Addr
[0] != 0) &&
3667 (Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3668 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3670 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3672 L
"Invalid Gateway!",
3675 Status
= EFI_INVALID_PARAMETER
;
3677 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
3683 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, IpString
, sizeof (IpString
));
3684 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
3685 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
3687 // The target is expressed in URL format or an invalid Ip address, just save.
3689 Private
->Current
->SessionConfigData
.DnsMode
= TRUE
;
3690 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (Private
->Current
->SessionConfigData
.TargetIp
));
3691 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, Private
->Current
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
3693 Private
->Current
->SessionConfigData
.DnsMode
= FALSE
;
3694 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
3699 case KEY_TARGET_NAME
:
3700 UnicodeStrToAsciiStrS (IfrNvData
->TargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3701 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
3702 if (EFI_ERROR (Status
)) {
3704 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3706 L
"Invalid iSCSI Name!",
3710 AsciiStrCpyS (Private
->Current
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
3715 case KEY_DHCP_ENABLE
:
3716 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
3717 IfrNvData
->TargetInfoFromDhcp
= 0;
3723 UnicodeStrToAsciiStrS (IfrNvData
->BootLun
, LunString
, sizeof (LunString
));
3724 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
3725 if (EFI_ERROR (Status
)) {
3727 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3729 L
"Invalid LUN string!",
3733 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
3739 switch (Value
->u8
) {
3740 case ISCSI_AUTH_TYPE_CHAP
:
3741 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
3750 UnicodeStrToAsciiStrS (
3751 IfrNvData
->CHAPName
,
3752 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
,
3753 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPName
)
3757 case KEY_CHAP_SECRET
:
3758 UnicodeStrToAsciiStrS (
3759 IfrNvData
->CHAPSecret
,
3760 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
,
3761 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
)
3765 case KEY_REVERSE_CHAP_NAME
:
3766 UnicodeStrToAsciiStrS (
3767 IfrNvData
->ReverseCHAPName
,
3768 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
,
3769 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
)
3773 case KEY_REVERSE_CHAP_SECRET
:
3774 UnicodeStrToAsciiStrS (
3775 IfrNvData
->ReverseCHAPSecret
,
3776 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
3777 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
)
3781 case KEY_CONFIG_ISID
:
3782 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3783 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3792 if (!EFI_ERROR (Status
)) {
3794 // Pass changed uncommitted data back to Form Browser.
3796 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3797 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3800 FreePool (IfrNvData
);
3801 FreePool (IScsiName
);
3808 Initialize the iSCSI configuration form.
3810 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3812 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
3813 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
3817 IScsiConfigFormInit (
3818 IN EFI_HANDLE DriverBindingHandle
3822 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
3824 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
3825 if (CallbackInfo
== NULL
) {
3826 return EFI_OUT_OF_RESOURCES
;
3829 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
3830 CallbackInfo
->Current
= NULL
;
3832 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
3833 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
3834 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
3837 // Install Device Path Protocol and Config Access protocol to driver handle.
3839 Status
= gBS
->InstallMultipleProtocolInterfaces (
3840 &CallbackInfo
->DriverHandle
,
3841 &gEfiDevicePathProtocolGuid
,
3842 &mIScsiHiiVendorDevicePath
,
3843 &gEfiHiiConfigAccessProtocolGuid
,
3844 &CallbackInfo
->ConfigAccess
,
3847 ASSERT_EFI_ERROR (Status
);
3850 // Publish our HII data.
3852 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
3854 CallbackInfo
->DriverHandle
,
3859 if (CallbackInfo
->RegisteredHandle
== NULL
) {
3860 gBS
->UninstallMultipleProtocolInterfaces (
3861 &CallbackInfo
->DriverHandle
,
3862 &gEfiDevicePathProtocolGuid
,
3863 &mIScsiHiiVendorDevicePath
,
3864 &gEfiHiiConfigAccessProtocolGuid
,
3865 &CallbackInfo
->ConfigAccess
,
3868 FreePool(CallbackInfo
);
3869 return EFI_OUT_OF_RESOURCES
;
3872 mCallbackInfo
= CallbackInfo
;
3879 Unload the iSCSI configuration form, this includes: delete all the iSCSI
3880 configuration entries, uninstall the form callback protocol, and
3881 free the resources used.
3883 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3885 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
3886 @retval Others Failed to unload the form.
3890 IScsiConfigFormUnload (
3891 IN EFI_HANDLE DriverBindingHandle
3894 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3895 ISCSI_NIC_INFO
*NicInfo
;
3899 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
3900 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
3901 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3902 FreePool (AttemptConfigData
);
3903 mPrivate
->AttemptCount
--;
3906 ASSERT (mPrivate
->AttemptCount
== 0);
3908 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
3909 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
3910 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3912 mPrivate
->NicCount
--;
3915 ASSERT (mPrivate
->NicCount
== 0);
3917 FreePool (mPrivate
);
3921 // Remove HII package list.
3923 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
3926 // Uninstall Device Path Protocol and Config Access protocol.
3928 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3929 mCallbackInfo
->DriverHandle
,
3930 &gEfiDevicePathProtocolGuid
,
3931 &mIScsiHiiVendorDevicePath
,
3932 &gEfiHiiConfigAccessProtocolGuid
,
3933 &mCallbackInfo
->ConfigAccess
,
3937 FreePool (mCallbackInfo
);