2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "IScsiImpl.h"
17 CHAR16 mVendorStorageName
[] = L
"ISCSI_CONFIG_IFR_NVDATA";
18 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
);
2295 if (AttemptConfigData
== NULL
) {
2296 Status
= EFI_NOT_FOUND
;
2301 // Remove this attempt from UI configured attempt list.
2303 RemoveEntryList (&AttemptConfigData
->Link
);
2304 mPrivate
->AttemptCount
--;
2306 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
2307 if (mPrivate
->MpioCount
< 1) {
2308 Status
= EFI_ABORTED
;
2313 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
2315 if (--mPrivate
->MpioCount
== 0) {
2316 mPrivate
->EnableMpio
= FALSE
;
2318 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
2319 if (mPrivate
->SinglePathCount
< 1) {
2320 Status
= EFI_ABORTED
;
2324 mPrivate
->SinglePathCount
--;
2327 AttemptConfigIndex
= AttemptConfigData
->AttemptConfigIndex
;
2328 FreePool (AttemptConfigData
);
2331 // Create a new Attempt
2333 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
2334 if (AttemptConfigData
== NULL
) {
2335 return EFI_OUT_OF_RESOURCES
;
2337 ConfigData
= &AttemptConfigData
->SessionConfigData
;
2338 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
2339 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
2340 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
2342 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
2343 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
2345 // Configure the Attempt index and set variable.
2347 AttemptConfigData
->AttemptConfigIndex
= AttemptConfigIndex
;
2350 // Set the attempt name to default.
2353 mPrivate
->PortString
,
2354 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2356 (UINTN
) AttemptConfigData
->AttemptConfigIndex
2358 UnicodeStrToAsciiStrS (mPrivate
->PortString
, AttemptConfigData
->AttemptName
, ATTEMPT_NAME_SIZE
);
2360 mPrivate
->PortString
,
2361 &gEfiIScsiInitiatorNameProtocolGuid
,
2362 ISCSI_CONFIG_VAR_ATTR
,
2363 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2368 // Mark the attempt order in NVR to be deleted - 0.
2370 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
2371 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
2372 AttemptConfigOrder
[NewIndex
] = 0;
2378 if (mCallbackInfo
->Current
== AttemptConfigData
) {
2379 mCallbackInfo
->Current
= NULL
;
2381 FreePool (AttemptConfigData
);
2384 // Check next Attempt.
2390 // Construct AttemptNewOrder.
2392 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
2393 if (AttemptConfigOrder
[Index
] != 0) {
2394 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
2399 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
2402 // Update AttemptOrder in NVR.
2404 Status
= gRT
->SetVariable (
2408 NewTotal
* sizeof (UINT8
),
2413 if (AttemptConfigOrder
!= NULL
) {
2414 FreePool (AttemptConfigOrder
);
2417 if (AttemptNewOrder
!= NULL
) {
2418 FreePool (AttemptNewOrder
);
2426 Callback function when user presses "Delete Attempts".
2428 @param[in] IfrNvData The IFR nv data.
2430 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2431 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
2432 @retval EFI_SUCCESS The operation is completed successfully.
2436 IScsiConfigDisplayDeleteAttempts (
2437 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2441 UINT8
*AttemptConfigOrder
;
2442 UINTN AttemptConfigOrderSize
;
2444 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2446 VOID
*StartOpCodeHandle
;
2447 EFI_IFR_GUID_LABEL
*StartLabel
;
2448 VOID
*EndOpCodeHandle
;
2449 EFI_IFR_GUID_LABEL
*EndLabel
;
2452 Status
= IScsiCreateOpCode (
2459 if (EFI_ERROR (Status
)) {
2463 AttemptConfigOrder
= IScsiGetVariableAndSize (
2466 &AttemptConfigOrderSize
2468 if (AttemptConfigOrder
!= NULL
) {
2470 // Create the check box opcode to be deleted.
2474 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2475 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2476 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
2478 HiiCreateCheckBoxOpCode(
2480 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
2481 CONFIGURATION_VARSTORE_ID
,
2482 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
2483 AttemptConfigData
->AttemptTitleToken
,
2484 AttemptConfigData
->AttemptTitleHelpToken
,
2492 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
2497 FreePool (AttemptConfigOrder
);
2500 Status
= HiiUpdateForm (
2501 mCallbackInfo
->RegisteredHandle
, // HII handle
2502 &gIScsiConfigGuid
, // Formset GUID
2503 FORMID_DELETE_FORM
, // Form ID
2504 StartOpCodeHandle
, // Label for where to insert opcodes
2505 EndOpCodeHandle
// Replace data
2508 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2509 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2516 Callback function when user presses "Change Attempt Order".
2518 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2519 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2521 @retval EFI_SUCCESS The operation is completed successfully.
2525 IScsiConfigDisplayOrderAttempts (
2532 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2533 VOID
*StartOpCodeHandle
;
2534 EFI_IFR_GUID_LABEL
*StartLabel
;
2535 VOID
*EndOpCodeHandle
;
2536 EFI_IFR_GUID_LABEL
*EndLabel
;
2537 VOID
*OptionsOpCodeHandle
;
2539 Status
= IScsiCreateOpCode (
2546 if (EFI_ERROR (Status
)) {
2549 ASSERT (StartOpCodeHandle
!= NULL
);
2551 OptionsOpCodeHandle
= NULL
;
2554 // If no attempt to be ordered, update the original form and exit.
2556 if (mPrivate
->AttemptCount
== 0) {
2561 // Create Option OpCode.
2563 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
2564 if (OptionsOpCodeHandle
== NULL
) {
2565 Status
= EFI_OUT_OF_RESOURCES
;
2571 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2572 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2573 HiiCreateOneOfOptionOpCode (
2574 OptionsOpCodeHandle
,
2575 AttemptConfigData
->AttemptTitleToken
,
2577 EFI_IFR_NUMERIC_SIZE_1
,
2578 AttemptConfigData
->AttemptConfigIndex
2583 ASSERT (Index
== mPrivate
->AttemptCount
);
2585 HiiCreateOrderedListOpCode (
2586 StartOpCodeHandle
, // Container for dynamic created opcodes
2587 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
2588 CONFIGURATION_VARSTORE_ID
, // VarStore ID
2589 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
2590 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
2591 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
2593 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
2594 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
2595 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
2596 OptionsOpCodeHandle
, // Option Opcode list
2597 NULL
// Default Opcode is NULL
2601 Status
= HiiUpdateForm (
2602 mCallbackInfo
->RegisteredHandle
, // HII handle
2603 &gIScsiConfigGuid
, // Formset GUID
2604 FORMID_ORDER_FORM
, // Form ID
2605 StartOpCodeHandle
, // Label for where to insert opcodes
2606 EndOpCodeHandle
// Replace data
2610 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2611 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2612 if (OptionsOpCodeHandle
!= NULL
) {
2613 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
2620 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.
2622 @param[in] IfrNvData The IFR nv data.
2624 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2626 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2627 @retval EFI_SUCCESS The operation is completed successfully.
2631 IScsiConfigOrderAttempts (
2632 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2638 UINT8 AttemptConfigIndex
;
2639 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2640 UINT8
*AttemptConfigOrder
;
2641 UINT8
*AttemptConfigOrderTmp
;
2642 UINTN AttemptConfigOrderSize
;
2644 AttemptConfigOrder
= IScsiGetVariableAndSize (
2647 &AttemptConfigOrderSize
2649 if (AttemptConfigOrder
== NULL
) {
2650 return EFI_NOT_FOUND
;
2653 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
2654 if (AttemptConfigOrderTmp
== NULL
) {
2655 Status
= EFI_OUT_OF_RESOURCES
;
2659 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
2661 // The real content ends with 0.
2663 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
2667 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
2668 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
2669 if (AttemptConfigData
== NULL
) {
2670 Status
= EFI_NOT_FOUND
;
2675 // Reorder the Attempt List.
2677 RemoveEntryList (&AttemptConfigData
->Link
);
2678 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2680 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
2683 // Mark it to be deleted - 0.
2685 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2686 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
2687 AttemptConfigOrder
[Indexj
] = 0;
2694 // Adjust the attempt order in NVR.
2696 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2697 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2698 if (AttemptConfigOrder
[Indexj
] != 0) {
2699 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
2700 AttemptConfigOrder
[Indexj
] = 0;
2706 Status
= gRT
->SetVariable (
2709 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2710 AttemptConfigOrderSize
,
2711 AttemptConfigOrderTmp
2715 if (AttemptConfigOrderTmp
!= NULL
) {
2716 FreePool (AttemptConfigOrderTmp
);
2719 FreePool (AttemptConfigOrder
);
2725 Callback function when a user presses "Attempt *" or when a user selects a NIC to
2726 create the new attempt.
2728 @param[in] KeyValue A unique value which is sent to the original
2729 exporting driver so that it can identify the type
2731 @param[in] IfrNvData The IFR nv data.
2733 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2735 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2736 @retval EFI_UNSUPPORTED Can not create more attempts.
2737 @retval EFI_SUCCESS The operation is completed successfully.
2741 IScsiConfigProcessDefault (
2742 IN EFI_QUESTION_ID KeyValue
,
2743 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2747 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2748 UINT8 CurrentAttemptConfigIndex
;
2749 ISCSI_NIC_INFO
*NicInfo
;
2751 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2752 UINT8
*AttemptConfigOrder
;
2753 UINTN AttemptConfigOrderSize
;
2757 AttemptConfigData
= NULL
;
2759 // Is User creating a new attempt?
2763 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
2764 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
2766 // User has pressed "Add an Attempt" and then selects a NIC.
2769 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
2770 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
2773 // User has pressed "Attempt *".
2778 // Don't process anything.
2785 // Determine which NIC user has selected for the new created attempt.
2787 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
2788 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
2789 if (NicInfo
== NULL
) {
2790 return EFI_NOT_FOUND
;
2794 // Create an attempt following the initialized attempt order.
2796 AttemptConfigOrder
= IScsiGetVariableAndSize (
2797 L
"InitialAttemptOrder",
2799 &AttemptConfigOrderSize
2802 if (AttemptConfigOrder
== NULL
) {
2803 return EFI_NOT_FOUND
;
2806 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2808 mPrivate
->PortString
,
2809 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2811 (UINTN
) AttemptConfigOrder
[Index
]
2814 mPrivate
->PortString
,
2815 &gEfiIScsiInitiatorNameProtocolGuid
,
2816 (VOID
**)&AttemptConfigData
,
2819 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2826 if (Index
> PcdGet8 (PcdMaxIScsiAttemptNumber
)) {
2828 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2830 L
"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",
2833 return EFI_UNSUPPORTED
;
2836 if (AttemptConfigOrder
!= NULL
) {
2837 FreePool (AttemptConfigOrder
);
2841 // Record the MAC info in Config Data.
2844 &NicInfo
->PermanentAddress
,
2845 NicInfo
->HwAddressSize
,
2850 ASSERT (AttemptConfigData
!= NULL
);
2851 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, sizeof (AttemptConfigData
->MacString
));
2852 AttemptConfigData
->NicIndex
= NicIndex
;
2853 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2856 // Generate OUI-format ISID based on MAC address.
2858 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2859 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2860 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2863 // Add the help info for the new attempt.
2866 mPrivate
->PortString
,
2867 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2868 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
2871 NicInfo
->DeviceNumber
,
2872 NicInfo
->FunctionNumber
2875 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2876 mCallbackInfo
->RegisteredHandle
,
2878 mPrivate
->PortString
,
2881 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2882 FreePool (AttemptConfigData
);
2883 return EFI_OUT_OF_RESOURCES
;
2888 // Determine which Attempt user has selected to configure.
2889 // Get the attempt configuration data.
2891 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
2893 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
2894 if (AttemptConfigData
== NULL
) {
2895 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
2896 return EFI_NOT_FOUND
;
2901 // Clear the old IFR data to avoid sharing it with other attempts.
2903 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
2904 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
2905 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
2906 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
2907 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
2910 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
2913 // Update current attempt to be a new created attempt or an existing attempt.
2915 mCallbackInfo
->Current
= AttemptConfigData
;
2923 This function allows the caller to request the current
2924 configuration for one or more named elements. The resulting
2925 string is in <ConfigAltResp> format. Also, any and all alternative
2926 configuration strings shall be appended to the end of the
2927 current configuration string. If they are, they must appear
2928 after the current configuration. They must contain the same
2929 routing (GUID, NAME, PATH) as the current configuration string.
2930 They must have an additional description indicating the type of
2931 alternative configuration the string represents,
2932 "ALTCFG=<StringToken>". That <StringToken> (when
2933 converted from Hex UNICODE to binary) is a reference to a
2934 string in the associated string pack.
2936 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2938 @param[in] Request A null-terminated Unicode string in
2939 <ConfigRequest> format. Note that this
2940 includes the routing information as well as
2941 the configurable name / value pairs. It is
2942 invalid for this string to be in
2943 <MultiConfigRequest> format.
2945 @param[out] Progress On return, points to a character in the
2946 Request string. Points to the string's null
2947 terminator if request was successful. Points
2948 to the most recent "&" before the first
2949 failing name / value pair (or the beginning
2950 of the string if the failure is in the first
2951 name / value pair) if the request was not successful.
2953 @param[out] Results A null-terminated Unicode string in
2954 <ConfigAltResp> format which has all values
2955 filled in for the names in the Request string.
2956 String to be allocated by the called function.
2958 @retval EFI_SUCCESS The Results string is filled with the
2959 values corresponding to all requested
2962 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2963 parts of the results that must be
2964 stored awaiting possible future
2967 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
2968 for the Request parameter
2969 would result in this type of
2970 error. In this case, the
2971 Progress parameter would be
2974 @retval EFI_NOT_FOUND Routing data doesn't match any
2975 known driver. Progress set to the
2976 first character in the routing header.
2977 Note: There is no requirement that the
2978 driver validate the routing data. It
2979 must skip the <ConfigHdr> in order to
2982 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
2983 to most recent "&" before the
2984 error or the beginning of the
2987 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
2988 to the & before the name in
2994 IScsiFormExtractConfig (
2995 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2996 IN CONST EFI_STRING Request
,
2997 OUT EFI_STRING
*Progress
,
2998 OUT EFI_STRING
*Results
3002 CHAR8
*InitiatorName
;
3004 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3005 ISCSI_FORM_CALLBACK_INFO
*Private
;
3006 EFI_STRING ConfigRequestHdr
;
3007 EFI_STRING ConfigRequest
;
3008 BOOLEAN AllocatedRequest
;
3011 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3012 return EFI_INVALID_PARAMETER
;
3015 *Progress
= Request
;
3016 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3017 return EFI_NOT_FOUND
;
3020 ConfigRequestHdr
= NULL
;
3021 ConfigRequest
= NULL
;
3022 AllocatedRequest
= FALSE
;
3025 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3026 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3027 if (IfrNvData
== NULL
) {
3028 return EFI_OUT_OF_RESOURCES
;
3032 if (Private
->Current
!= NULL
) {
3033 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
3037 // Extract all AttemptConfigData to Keyword stroage of IfrNvData.
3039 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData
);
3041 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3042 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3043 if (InitiatorName
== NULL
) {
3044 FreePool (IfrNvData
);
3045 return EFI_OUT_OF_RESOURCES
;
3048 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3049 if (EFI_ERROR (Status
)) {
3050 IfrNvData
->InitiatorName
[0] = L
'\0';
3052 AsciiStrToUnicodeStrS (
3054 IfrNvData
->InitiatorName
,
3055 sizeof (IfrNvData
->InitiatorName
) / sizeof (IfrNvData
->InitiatorName
[0])
3060 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
3062 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3063 ConfigRequest
= Request
;
3064 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3066 // Request has no request element, construct full request string.
3067 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3068 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3070 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
3071 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3072 ConfigRequest
= AllocateZeroPool (Size
);
3073 if (ConfigRequest
== NULL
) {
3074 FreePool (IfrNvData
);
3075 FreePool (InitiatorName
);
3076 return EFI_OUT_OF_RESOURCES
;
3078 AllocatedRequest
= TRUE
;
3079 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3080 FreePool (ConfigRequestHdr
);
3083 Status
= gHiiConfigRouting
->BlockToConfig (
3086 (UINT8
*) IfrNvData
,
3091 FreePool (IfrNvData
);
3092 FreePool (InitiatorName
);
3095 // Free the allocated config request string.
3097 if (AllocatedRequest
) {
3098 FreePool (ConfigRequest
);
3099 ConfigRequest
= NULL
;
3102 // Set Progress string to the original request string.
3104 if (Request
== NULL
) {
3106 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3107 *Progress
= Request
+ StrLen (Request
);
3116 This function applies changes in a driver's configuration.
3117 Input is a Configuration, which has the routing data for this
3118 driver followed by name / value configuration pairs. The driver
3119 must apply those pairs to its configurable storage. If the
3120 driver's configuration is stored in a linear block of data
3121 and the driver's name / value pairs are in <BlockConfig>
3122 format, it may use the ConfigToBlock helper function (above) to
3125 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3127 @param[in] Configuration A null-terminated Unicode string in
3128 <ConfigString> format.
3130 @param[out] Progress A pointer to a string filled in with the
3131 offset of the most recent '&' before the
3132 first failing name / value pair (or the
3133 beginning of the string if the failure
3134 is in the first name / value pair) or
3135 the terminating NULL if all was
3138 @retval EFI_SUCCESS The results have been distributed or are
3139 awaiting distribution.
3141 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
3142 parts of the results that must be
3143 stored awaiting possible future
3146 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
3147 Results parameter would result
3148 in this type of error.
3150 @retval EFI_NOT_FOUND Target for the specified routing data
3156 IScsiFormRouteConfig (
3157 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3158 IN CONST EFI_STRING Configuration
,
3159 OUT EFI_STRING
*Progress
3163 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3164 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3166 LIST_ENTRY
*NextEntry
;
3167 ISCSI_NIC_INFO
*NicInfo
;
3169 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
3170 CHAR8
*InitiatorName
;
3181 Status
= EFI_SUCCESS
;
3183 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
3184 return EFI_INVALID_PARAMETER
;
3188 // Check routing data in <ConfigHdr>.
3189 // Note: if only one Storage is used, then this checking could be skipped.
3191 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3192 *Progress
= Configuration
;
3193 return EFI_NOT_FOUND
;
3196 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3197 if (IfrNvData
== NULL
) {
3198 return EFI_OUT_OF_RESOURCES
;
3201 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3202 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3203 if (InitiatorName
== NULL
) {
3204 Status
= EFI_OUT_OF_RESOURCES
;
3209 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
3211 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3212 Status
= gHiiConfigRouting
->ConfigToBlock (
3215 (UINT8
*) IfrNvData
,
3219 if (EFI_ERROR (Status
)) {
3223 if (IfrNvData
->InitiatorName
[0] != L
'\0') {
3224 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, InitiatorName
, ISCSI_NAME_MAX_SIZE
);
3225 BufferSize
= AsciiStrSize (InitiatorName
);
3227 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3228 if (EFI_ERROR (Status
)) {
3230 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3232 L
"Invalid iSCSI Name!",
3238 Status
= IScsiGetValue (Configuration
, L
"&OFFSET=", &OffSet
);
3239 if (EFI_ERROR (Status
)) {
3243 if (OffSet
>= ATTEMPT_MAC_ADDR_VAR_OFFSET
) {
3244 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3245 if (EFI_ERROR (Status
)) {
3247 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3249 L
"Error: please configure iSCSI initiator name first!",
3258 if (IfrNvData
->ISCSIAddAttemptList
[0] != L
'\0') {
3259 Status
=IScsiGetAttemptIndexList (IfrNvData
->ISCSIAddAttemptList
, IfrNvData
->AddAttemptList
, TRUE
);
3260 if (EFI_ERROR (Status
)) {
3262 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3264 L
"Error: The add attempt list is invalid",
3270 Status
= IScsiConfigAddAttemptsByKeywords (IfrNvData
->AddAttemptList
);
3271 if (EFI_ERROR (Status
)) {
3275 } else if (IfrNvData
->ISCSIDeleteAttemptList
[0] != L
'\0') {
3276 AttemptList
=(UINT8
*) AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM
+ 1) * sizeof (UINT8
));
3277 if (AttemptList
== NULL
) {
3278 Status
= EFI_OUT_OF_RESOURCES
;
3281 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIDeleteAttemptList
, AttemptList
, FALSE
);
3282 if (EFI_ERROR (Status
)) {
3284 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3286 L
"Error: The delete attempt list is invalid",
3293 // Mark the attempt which will be delete in the global list.
3295 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
3296 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3297 while (AttemptList
[Index
] != 0) {
3298 if (AttemptConfigData
->AttemptConfigIndex
== AttemptList
[Index
]) {
3299 IfrNvData
->DeleteAttemptList
[Index2
] = 1;
3308 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3309 if (EFI_ERROR (Status
)) {
3313 FreePool (AttemptList
);
3315 } else if (IfrNvData
->ISCSIAttemptOrder
[0] != L
'\0') {
3316 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIAttemptOrder
, IfrNvData
->DynamicOrderedList
, FALSE
);
3317 if (EFI_ERROR (Status
)) {
3319 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3321 L
"Error: The new attempt order list is invalid",
3327 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3328 if (EFI_ERROR (Status
)) {
3332 } else if (IfrNvData
->ISCSIMacAddr
[0] != L
'\0') {
3333 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
3334 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3336 &NicInfo
->PermanentAddress
,
3337 NicInfo
->HwAddressSize
,
3341 if (!StrCmp(MacString
, IfrNvData
->ISCSIMacAddr
)) {
3342 mPrivate
->CurrentNic
= NicInfo
->NicIndex
;
3347 if ((NicInfo
== NULL
) || (NicInfo
->NicIndex
== 0)) {
3348 Status
= EFI_NOT_FOUND
;
3353 Status
= IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData
, OffSet
);
3354 if (EFI_ERROR (Status
)) {
3360 IScsiConfigUpdateAttempt ();
3363 if (InitiatorName
!= NULL
) {
3364 FreePool (InitiatorName
);
3367 if (IfrNvData
!= NULL
) {
3368 FreePool (IfrNvData
);
3376 This function is called to provide results data to the driver.
3377 This data consists of a unique key that is used to identify
3378 which data is either being passed back or being asked for.
3380 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3381 @param[in] Action Specifies the type of action taken by the browser.
3382 @param[in] QuestionId A unique value which is sent to the original
3383 exporting driver so that it can identify the type
3384 of data to expect. The format of the data tends to
3385 vary based on the opcode that generated the callback.
3386 @param[in] Type The type of value for the question.
3387 @param[in, out] Value A pointer to the data being sent to the original
3389 @param[out] ActionRequest On return, points to the action requested by the
3392 @retval EFI_SUCCESS The callback successfully handled the action.
3393 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3394 variable and its data.
3395 @retval EFI_DEVICE_ERROR The variable could not be saved.
3396 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3402 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3403 IN EFI_BROWSER_ACTION Action
,
3404 IN EFI_QUESTION_ID QuestionId
,
3406 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
3407 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3410 ISCSI_FORM_CALLBACK_INFO
*Private
;
3413 CHAR8 IpString
[ISCSI_NAME_MAX_SIZE
];
3414 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
3416 EFI_IP_ADDRESS HostIp
;
3417 EFI_IP_ADDRESS SubnetMask
;
3418 EFI_IP_ADDRESS Gateway
;
3419 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3420 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
3423 ISCSI_NIC_INFO
*NicInfo
;
3427 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
3429 // Do nothing for UEFI OPEN/CLOSE Action
3434 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
3436 // All other type return unsupported.
3438 return EFI_UNSUPPORTED
;
3441 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
3442 return EFI_INVALID_PARAMETER
;
3445 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3448 // Retrieve uncommitted data from Browser
3451 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3452 IfrNvData
= AllocateZeroPool (BufferSize
);
3453 if (IfrNvData
== NULL
) {
3454 return EFI_OUT_OF_RESOURCES
;
3457 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
3458 if (IScsiName
== NULL
) {
3459 FreePool (IfrNvData
);
3460 return EFI_OUT_OF_RESOURCES
;
3463 Status
= EFI_SUCCESS
;
3465 ZeroMem (&OldIfrNvData
, BufferSize
);
3467 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
3469 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
3471 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3472 switch (QuestionId
) {
3473 case KEY_ADD_ATTEMPT
:
3475 // Check whether iSCSI initiator name is configured already.
3477 mPrivate
->InitiatorNameLength
= ISCSI_NAME_MAX_SIZE
;
3478 Status
= gIScsiInitiatorName
.Get (
3479 &gIScsiInitiatorName
,
3480 &mPrivate
->InitiatorNameLength
,
3481 mPrivate
->InitiatorName
3483 if (EFI_ERROR (Status
)) {
3485 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3487 L
"Error: please configure iSCSI initiator name first!",
3493 Status
= IScsiConfigAddAttempt ();
3496 case KEY_DELETE_ATTEMPT
:
3498 OldIfrNvData
.DeleteAttemptList
,
3499 IfrNvData
->DeleteAttemptList
,
3500 sizeof (IfrNvData
->DeleteAttemptList
)
3502 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
3505 case KEY_ORDER_ATTEMPT_CONFIG
:
3507 // Order the attempt according to user input.
3510 OldIfrNvData
.DynamicOrderedList
,
3511 IfrNvData
->DynamicOrderedList
,
3512 sizeof (IfrNvData
->DynamicOrderedList
)
3514 IScsiConfigDisplayOrderAttempts ();
3518 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
3521 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3522 switch (QuestionId
) {
3523 case KEY_INITIATOR_NAME
:
3524 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3525 BufferSize
= AsciiStrSize (IScsiName
);
3527 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
3528 if (EFI_ERROR (Status
)) {
3530 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3532 L
"Invalid iSCSI Name!",
3537 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3540 case KEY_SAVE_ATTEMPT_CONFIG
:
3541 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
3542 if (EFI_ERROR (Status
)) {
3546 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3549 case KEY_SAVE_ORDER_CHANGES
:
3551 // Sync the Attempt Order to NVR.
3553 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3554 if (EFI_ERROR (Status
)) {
3558 IScsiConfigUpdateAttempt ();
3559 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3562 case KEY_IGNORE_ORDER_CHANGES
:
3564 IfrNvData
->DynamicOrderedList
,
3565 OldIfrNvData
.DynamicOrderedList
,
3566 sizeof (IfrNvData
->DynamicOrderedList
)
3568 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3571 case KEY_SAVE_DELETE_ATTEMPT
:
3573 // Delete the Attempt Order from NVR
3575 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3576 if (EFI_ERROR (Status
)) {
3580 IScsiConfigUpdateAttempt ();
3581 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3584 case KEY_IGNORE_DELETE_ATTEMPT
:
3586 IfrNvData
->DeleteAttemptList
,
3587 OldIfrNvData
.DeleteAttemptList
,
3588 sizeof (IfrNvData
->DeleteAttemptList
)
3590 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3594 switch (Value
->u8
) {
3596 NicInfo
= IScsiGetNicInfoByIndex (Private
->Current
->NicIndex
);
3597 if(NicInfo
== NULL
) {
3601 if(!NicInfo
->Ipv6Available
) {
3603 // Current NIC doesn't Support IPv6, hence use IPv4.
3605 IfrNvData
->IpMode
= IP_MODE_IP4
;
3608 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3610 L
"Current NIC doesn't Support IPv6!",
3616 ZeroMem (IfrNvData
->LocalIp
, sizeof (IfrNvData
->LocalIp
));
3617 ZeroMem (IfrNvData
->SubnetMask
, sizeof (IfrNvData
->SubnetMask
));
3618 ZeroMem (IfrNvData
->Gateway
, sizeof (IfrNvData
->Gateway
));
3619 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
3620 Private
->Current
->AutoConfigureMode
= 0;
3621 ZeroMem (&Private
->Current
->SessionConfigData
.LocalIp
, sizeof (EFI_IP_ADDRESS
));
3622 ZeroMem (&Private
->Current
->SessionConfigData
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
3623 ZeroMem (&Private
->Current
->SessionConfigData
.Gateway
, sizeof (EFI_IP_ADDRESS
));
3624 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (EFI_IP_ADDRESS
));
3632 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
3633 if (EFI_ERROR (Status
) ||
3634 ((Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3635 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3637 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3639 L
"Invalid IP address!",
3643 Status
= EFI_INVALID_PARAMETER
;
3645 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
3650 case KEY_SUBNET_MASK
:
3651 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
3652 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
3654 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3656 L
"Invalid Subnet Mask!",
3660 Status
= EFI_INVALID_PARAMETER
;
3662 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
3668 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
3669 if (EFI_ERROR (Status
) ||
3670 ((Gateway
.Addr
[0] != 0) &&
3671 (Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3672 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3674 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3676 L
"Invalid Gateway!",
3679 Status
= EFI_INVALID_PARAMETER
;
3681 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
3687 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, IpString
, sizeof (IpString
));
3688 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
3689 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
3691 // The target is expressed in URL format or an invalid Ip address, just save.
3693 Private
->Current
->SessionConfigData
.DnsMode
= TRUE
;
3694 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (Private
->Current
->SessionConfigData
.TargetIp
));
3695 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, Private
->Current
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
3697 Private
->Current
->SessionConfigData
.DnsMode
= FALSE
;
3698 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
3703 case KEY_TARGET_NAME
:
3704 UnicodeStrToAsciiStrS (IfrNvData
->TargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3705 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
3706 if (EFI_ERROR (Status
)) {
3708 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3710 L
"Invalid iSCSI Name!",
3714 AsciiStrCpyS (Private
->Current
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
3719 case KEY_DHCP_ENABLE
:
3720 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
3721 IfrNvData
->TargetInfoFromDhcp
= 0;
3727 UnicodeStrToAsciiStrS (IfrNvData
->BootLun
, LunString
, sizeof (LunString
));
3728 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
3729 if (EFI_ERROR (Status
)) {
3731 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3733 L
"Invalid LUN string!",
3737 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
3743 switch (Value
->u8
) {
3744 case ISCSI_AUTH_TYPE_CHAP
:
3745 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
3754 UnicodeStrToAsciiStrS (
3755 IfrNvData
->CHAPName
,
3756 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
,
3757 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPName
)
3761 case KEY_CHAP_SECRET
:
3762 UnicodeStrToAsciiStrS (
3763 IfrNvData
->CHAPSecret
,
3764 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
,
3765 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
)
3769 case KEY_REVERSE_CHAP_NAME
:
3770 UnicodeStrToAsciiStrS (
3771 IfrNvData
->ReverseCHAPName
,
3772 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
,
3773 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
)
3777 case KEY_REVERSE_CHAP_SECRET
:
3778 UnicodeStrToAsciiStrS (
3779 IfrNvData
->ReverseCHAPSecret
,
3780 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
3781 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
)
3785 case KEY_CONFIG_ISID
:
3786 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3787 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3796 if (!EFI_ERROR (Status
)) {
3798 // Pass changed uncommitted data back to Form Browser.
3800 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3801 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3804 FreePool (IfrNvData
);
3805 FreePool (IScsiName
);
3812 Initialize the iSCSI configuration form.
3814 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3816 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
3817 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
3821 IScsiConfigFormInit (
3822 IN EFI_HANDLE DriverBindingHandle
3826 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
3828 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
3829 if (CallbackInfo
== NULL
) {
3830 return EFI_OUT_OF_RESOURCES
;
3833 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
3834 CallbackInfo
->Current
= NULL
;
3836 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
3837 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
3838 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
3841 // Install Device Path Protocol and Config Access protocol to driver handle.
3843 Status
= gBS
->InstallMultipleProtocolInterfaces (
3844 &CallbackInfo
->DriverHandle
,
3845 &gEfiDevicePathProtocolGuid
,
3846 &mIScsiHiiVendorDevicePath
,
3847 &gEfiHiiConfigAccessProtocolGuid
,
3848 &CallbackInfo
->ConfigAccess
,
3851 ASSERT_EFI_ERROR (Status
);
3854 // Publish our HII data.
3856 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
3858 CallbackInfo
->DriverHandle
,
3863 if (CallbackInfo
->RegisteredHandle
== NULL
) {
3864 gBS
->UninstallMultipleProtocolInterfaces (
3865 &CallbackInfo
->DriverHandle
,
3866 &gEfiDevicePathProtocolGuid
,
3867 &mIScsiHiiVendorDevicePath
,
3868 &gEfiHiiConfigAccessProtocolGuid
,
3869 &CallbackInfo
->ConfigAccess
,
3872 FreePool(CallbackInfo
);
3873 return EFI_OUT_OF_RESOURCES
;
3876 mCallbackInfo
= CallbackInfo
;
3883 Unload the iSCSI configuration form, this includes: delete all the iSCSI
3884 configuration entries, uninstall the form callback protocol, and
3885 free the resources used.
3887 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3889 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
3890 @retval Others Failed to unload the form.
3894 IScsiConfigFormUnload (
3895 IN EFI_HANDLE DriverBindingHandle
3898 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3899 ISCSI_NIC_INFO
*NicInfo
;
3903 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
3904 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
3905 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3906 FreePool (AttemptConfigData
);
3907 mPrivate
->AttemptCount
--;
3910 ASSERT (mPrivate
->AttemptCount
== 0);
3912 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
3913 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
3914 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3916 mPrivate
->NicCount
--;
3919 ASSERT (mPrivate
->NicCount
== 0);
3921 FreePool (mPrivate
);
3925 // Remove HII package list.
3927 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
3930 // Uninstall Device Path Protocol and Config Access protocol.
3932 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3933 mCallbackInfo
->DriverHandle
,
3934 &gEfiDevicePathProtocolGuid
,
3935 &mIScsiHiiVendorDevicePath
,
3936 &gEfiHiiConfigAccessProtocolGuid
,
3937 &mCallbackInfo
->ConfigAccess
,
3941 FreePool (mCallbackInfo
);