2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "IScsiImpl.h"
17 CHAR16 mVendorStorageName
[] = L
"ISCSI_CONFIG_IFR_NVDATA";
18 BOOLEAN mIScsiDeviceListUpdated
= FALSE
;
19 UINTN mNumberOfIScsiDevices
= 0;
20 ISCSI_FORM_CALLBACK_INFO
*mCallbackInfo
= NULL
;
22 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath
= {
28 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
29 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
36 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
38 (UINT8
) (END_DEVICE_PATH_LENGTH
),
39 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
46 Convert the IP address into a dotted string.
48 @param[in] Ip The IP address.
49 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.
50 @param[out] Str The formatted IP string.
55 IN EFI_IP_ADDRESS
*Ip
,
60 EFI_IPv4_ADDRESS
*Ip4
;
61 EFI_IPv6_ADDRESS
*Ip6
;
65 CHAR16 FormatString
[8];
72 (UINTN
) 2 * IP4_STR_MAX_SIZE
,
86 for (Index
= 0; Index
< 15; Index
= Index
+ 2) {
89 Ip6
->Addr
[Index
] == 0 &&
90 Ip6
->Addr
[Index
+ 1] == 0
93 // Deal with the case of ::.
104 while ((Index
< 15) && (Ip6
->Addr
[Index
] == 0) && (Ip6
->Addr
[Index
+ 1] == 0)) {
112 // :: is at the end of the address.
121 if (Ip6
->Addr
[Index
] == 0) {
122 Number
= UnicodeSPrint (Str
, 2 * IP_STR_MAX_SIZE
, L
"%x:", (UINTN
) Ip6
->Addr
[Index
+ 1]);
124 if (Ip6
->Addr
[Index
+ 1] < 0x10) {
125 CopyMem (FormatString
, L
"%x0%x:", StrSize (L
"%x0%x:"));
127 CopyMem (FormatString
, L
"%x%x:", StrSize (L
"%x%x:"));
130 Number
= UnicodeSPrint (
133 (CONST CHAR16
*) FormatString
,
134 (UINTN
) Ip6
->Addr
[Index
],
135 (UINTN
) Ip6
->Addr
[Index
+ 1]
141 if (Index
+ 2 == 16) {
143 if (*(Str
- 1) == L
':') {
151 Check whether the input IP address is valid.
153 @param[in] Ip The IP address.
154 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.
156 @retval TRUE The input IP address is valid.
157 @retval FALSE Otherwise
162 IN EFI_IP_ADDRESS
*Ip
,
166 if (IpMode
== IP_MODE_IP4
) {
167 if (IP4_IS_UNSPECIFIED (NTOHL (Ip
->Addr
[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip
->Addr
[0]))) {
171 } else if (IpMode
== IP_MODE_IP6
) {
172 return NetIp6IsValidUnicast (&Ip
->v6
);
174 DEBUG ((DEBUG_ERROR
, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode
));
180 Parse IsId in string format and convert it to binary.
182 @param[in] String The buffer of the string to be parsed.
183 @param[in, out] IsId The buffer to store IsId.
185 @retval EFI_SUCCESS The operation finished successfully.
186 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
190 IScsiParseIsIdFromString (
191 IN CONST CHAR16
*String
,
199 CHAR16 PortString
[ISCSI_NAME_IFR_MAX_SIZE
];
202 if ((String
== NULL
) || (IsId
== NULL
)) {
203 return EFI_INVALID_PARAMETER
;
206 IsIdStr
= (CHAR16
*) String
;
208 if (StrLen (IsIdStr
) != 6) {
211 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
212 L
"Error! Input is incorrect, please input 6 hex numbers!\n"
216 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
222 return EFI_INVALID_PARAMETER
;
225 for (Index
= 3; Index
< 6; Index
++) {
226 CopyMem (TempStr
, IsIdStr
, sizeof (TempStr
));
230 // Convert the string to IsId. StrHexToUintn stops at the first character
231 // that is not a valid hex character, '\0' here.
233 NodeVal
= StrHexToUintn (TempStr
);
235 IsId
[Index
] = (UINT8
) NodeVal
;
237 IsIdStr
= IsIdStr
+ 2;
244 Convert IsId from binary to string format.
246 @param[out] String The buffer to store the converted string.
247 @param[in] IsId The buffer to store IsId.
249 @retval EFI_SUCCESS The string converted successfully.
250 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
254 IScsiConvertIsIdToString (
262 if ((String
== NULL
) || (IsId
== NULL
)) {
263 return EFI_INVALID_PARAMETER
;
266 for (Index
= 0; Index
< 6; Index
++) {
267 if (IsId
[Index
] <= 0xF) {
268 Number
= UnicodeSPrint (
270 2 * ISID_CONFIGURABLE_STORAGE
,
275 Number
= UnicodeSPrint (
277 2 * ISID_CONFIGURABLE_STORAGE
,
284 String
= String
+ Number
;
293 Get the Offset value specified by the input String.
295 @param[in] Configuration A null-terminated Unicode string in
296 <ConfigString> format.
297 @param[in] String The string is "&OFFSET=".
298 @param[out] Value The Offset value.
300 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
302 @retval EFI_SUCCESS Value of <Number> is outputted in Number
308 IN CONST EFI_STRING Configuration
,
328 StringPtr
= StrStr (Configuration
, String
);
329 ASSERT(StringPtr
!= NULL
);
330 StringPtr
+= StrLen (String
);
333 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
336 Length
= StringPtr
- TmpPtr
;
339 Str
= AllocateZeroPool (Len
* sizeof (CHAR16
));
341 Status
= EFI_OUT_OF_RESOURCES
;
345 CopyMem (Str
, TmpPtr
, Len
* sizeof (CHAR16
));
346 *(Str
+ Length
) = L
'\0';
349 Buf
= (UINT8
*) AllocateZeroPool (Len
);
351 Status
= EFI_OUT_OF_RESOURCES
;
355 ZeroMem (TmpStr
, sizeof (TmpStr
));
356 for (Index
= 0; Index
< Length
; Index
++) {
357 TmpStr
[0] = Str
[Length
- Index
- 1];
358 DigitUint8
= (UINT8
) StrHexToUint64 (TmpStr
);
359 if ((Index
& 1) == 0) {
360 Buf
[Index
/2] = DigitUint8
;
362 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
370 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
374 Status
= EFI_SUCCESS
;
385 Get the attempt config data from global structure by the ConfigIndex.
387 @param[in] AttemptConfigIndex The unique index indicates the attempt.
389 @return Pointer to the attempt config data.
390 @retval NULL The attempt configuration data cannot be found.
393 ISCSI_ATTEMPT_CONFIG_NVDATA
*
394 IScsiConfigGetAttemptByConfigIndex (
395 IN UINT8 AttemptConfigIndex
399 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
401 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
402 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
403 if (Attempt
->AttemptConfigIndex
== AttemptConfigIndex
) {
413 Get the existing attempt config data from global structure by the NicIndex.
415 @param[in] NewAttempt The created new attempt
416 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
419 @return Pointer to the existing attempt config data which
420 has the same NICIndex as the new created attempt.
421 @retval NULL The attempt with NicIndex does not exist.
424 ISCSI_ATTEMPT_CONFIG_NVDATA
*
425 IScsiConfigGetAttemptByNic (
426 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*NewAttempt
,
431 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
433 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
434 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
435 if (Attempt
!= NewAttempt
&& Attempt
->NicIndex
== NewAttempt
->NicIndex
&&
436 Attempt
->SessionConfigData
.Enabled
== IScsiMode
) {
445 Extract the Index of the attempt list.
447 @param[in] AttemptNameList The Name list of the Attempts.
448 @param[out] AttemptIndexList The Index list of the Attempts.
449 @param[in] IsAddAttempts If TRUE, Indicates add one or more attempts.
450 If FALSE, Indicates delete attempts or change attempt order.
452 @retval EFI_SUCCESS The Attempt list is valid.
453 @retval EFI_INVALID_PARAMETERS The Attempt List is invalid.
457 IScsiGetAttemptIndexList (
458 IN CHAR16
*AttemptNameList
,
459 OUT UINT8
*AttemptIndexList
,
460 IN BOOLEAN IsAddAttempts
463 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
471 if ((AttemptNameList
== NULL
) || (*AttemptNameList
== L
'\0')) {
472 return EFI_INVALID_PARAMETER
;
475 AttemptStr
= AttemptNameList
;
476 Len
= StrLen (L
"attempt:");
478 while (*AttemptStr
!= L
'\0') {
479 AttemptStr
= StrStr (AttemptStr
, L
"attempt:");
480 if (AttemptStr
== NULL
) {
481 return EFI_INVALID_PARAMETER
;
484 AttemptIndex
= (UINT8
)(*AttemptStr
- L
'0');
485 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
487 if ((AttemptConfigData
!= NULL
) || ((AttemptIndex
) > PcdGet8 (PcdMaxIScsiAttemptNumber
))) {
488 return EFI_INVALID_PARAMETER
;
491 if (AttemptConfigData
== NULL
) {
492 return EFI_INVALID_PARAMETER
;
496 AttemptIndexList
[Index
] = AttemptIndex
;
504 Convert the iSCSI configuration data into the IFR data.
506 @param[in] Attempt The iSCSI attempt config data.
507 @param[in, out] IfrNvData The IFR nv data.
511 IScsiConvertAttemptConfigDataToIfrNvData (
512 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
,
513 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
516 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
517 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
522 // Normal session configuration parameters.
524 SessionConfigData
= &Attempt
->SessionConfigData
;
525 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
526 IfrNvData
->IpMode
= SessionConfigData
->IpMode
;
527 DnsMode
= SessionConfigData
->DnsMode
;
529 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
530 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
531 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
533 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
534 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
535 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->LocalIp
);
536 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
537 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->SubnetMask
);
538 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
539 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Gateway
);
540 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
541 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
542 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->TargetIp
);
545 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
546 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
547 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
548 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
549 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->TargetIp
);
553 AsciiStrToUnicodeStrS (
554 SessionConfigData
->TargetName
,
555 IfrNvData
->TargetName
,
556 sizeof (IfrNvData
->TargetName
) / sizeof (IfrNvData
->TargetName
[0])
560 AsciiStrToUnicodeStrS (
561 SessionConfigData
->TargetUrl
,
563 sizeof (IfrNvData
->TargetIp
) / sizeof (IfrNvData
->TargetIp
[0])
567 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
568 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
570 IfrNvData
->ConnectRetryCount
= SessionConfigData
->ConnectRetryCount
;
571 IfrNvData
->ConnectTimeout
= SessionConfigData
->ConnectTimeout
;
574 // Authentication parameters.
576 IfrNvData
->AuthenticationType
= Attempt
->AuthenticationType
;
578 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
579 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
580 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
581 AsciiStrToUnicodeStrS (
582 AuthConfigData
->CHAPName
,
584 sizeof (IfrNvData
->CHAPName
) / sizeof (IfrNvData
->CHAPName
[0])
586 AsciiStrToUnicodeStrS (
587 AuthConfigData
->CHAPSecret
,
588 IfrNvData
->CHAPSecret
,
589 sizeof (IfrNvData
->CHAPSecret
) / sizeof (IfrNvData
->CHAPSecret
[0])
591 AsciiStrToUnicodeStrS (
592 AuthConfigData
->ReverseCHAPName
,
593 IfrNvData
->ReverseCHAPName
,
594 sizeof (IfrNvData
->ReverseCHAPName
) / sizeof (IfrNvData
->ReverseCHAPName
[0])
596 AsciiStrToUnicodeStrS (
597 AuthConfigData
->ReverseCHAPSecret
,
598 IfrNvData
->ReverseCHAPSecret
,
599 sizeof (IfrNvData
->ReverseCHAPSecret
) / sizeof (IfrNvData
->ReverseCHAPSecret
[0])
606 AsciiStrToUnicodeStrS (
607 Attempt
->AttemptName
,
608 IfrNvData
->AttemptName
,
609 sizeof (IfrNvData
->AttemptName
) / sizeof (IfrNvData
->AttemptName
[0])
614 Convert the iSCSI configuration data into the IFR data Which will be used
615 to extract the iSCSI Keyword configuration in <ConfigAltResp> format.
617 @param[in, out] IfrNvData The IFR nv data.
622 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (
623 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
627 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
628 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
629 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
630 CHAR16 AttemptNameList
[ATTEMPT_NAME_LIST_SIZE
];
635 ZeroMem (AttemptNameList
, sizeof (AttemptNameList
));
637 if ((mPrivate
!= NULL
) && (mPrivate
->AttemptCount
!= 0)) {
638 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
639 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
641 // Normal session configuration parameters.
643 SessionConfigData
= &Attempt
->SessionConfigData
;
645 ASSERT ((Attempt
->AttemptConfigIndex
> 0) && (Attempt
->AttemptConfigIndex
<= FixedPcdGet8 (PcdMaxIScsiAttemptNumber
)));
646 Index
= Attempt
->AttemptConfigIndex
- 1;
649 // Save the attempt to AttemptNameList as Attempt:1 Attempt:2
651 AsciiStrToUnicodeStrS (
652 Attempt
->AttemptName
,
653 AttemptNameList
+ StrLen (AttemptNameList
),
654 ATTEMPT_NAME_LIST_SIZE
- StrLen (AttemptNameList
)
657 StringLen
= StrLen (AttemptNameList
);
658 ASSERT (StringLen
> 2);
659 *(AttemptNameList
+ StringLen
- 2) = L
':';
660 *(AttemptNameList
+ StringLen
) = L
' ';
662 AsciiStrToUnicodeStrS (
663 Attempt
->AttemptName
,
664 IfrNvData
->ISCSIAttemptName
+ ATTEMPT_NAME_SIZE
* Index
,
665 ATTEMPT_NAME_LIST_SIZE
- ATTEMPT_NAME_SIZE
* Index
668 IfrNvData
->ISCSIBootEnableList
[Index
] = SessionConfigData
->Enabled
;
669 IfrNvData
->ISCSIIpAddressTypeList
[Index
] = SessionConfigData
->IpMode
;
671 IfrNvData
->ISCSIInitiatorInfoViaDHCP
[Index
] = SessionConfigData
->InitiatorInfoFromDhcp
;
672 IfrNvData
->ISCSITargetInfoViaDHCP
[Index
] = SessionConfigData
->TargetInfoFromDhcp
;
673 IfrNvData
->ISCSIConnectRetry
[Index
] = SessionConfigData
->ConnectRetryCount
;
674 IfrNvData
->ISCSIConnectTimeout
[Index
] = SessionConfigData
->ConnectTimeout
;
675 IfrNvData
->ISCSITargetTcpPort
[Index
] = SessionConfigData
->TargetPort
;
677 if (SessionConfigData
->IpMode
== IP_MODE_IP4
) {
678 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
679 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
);
680 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
681 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
);
682 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
683 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
);
684 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
685 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
686 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
);
688 } else if (SessionConfigData
->IpMode
== IP_MODE_IP6
) {
689 ZeroMem (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, sizeof (IfrNvData
->TargetIp
));
690 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
691 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
692 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
);
696 AsciiStrToUnicodeStrS (
697 SessionConfigData
->TargetName
,
698 IfrNvData
->Keyword
[Index
].ISCSITargetName
,
702 if (SessionConfigData
->DnsMode
) {
703 AsciiStrToUnicodeStrS (
704 SessionConfigData
->TargetUrl
,
706 sizeof (IfrNvData
->TargetIp
) / sizeof (IfrNvData
->TargetIp
[0])
710 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->Keyword
[Index
].ISCSILun
);
711 IScsiConvertIsIdToString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, SessionConfigData
->IsId
);
713 IfrNvData
->ISCSIAuthenticationMethod
[Index
] = Attempt
->AuthenticationType
;
715 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
716 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
717 IfrNvData
->ISCSIChapType
[Index
] = AuthConfigData
->CHAPType
;
718 AsciiStrToUnicodeStrS (
719 AuthConfigData
->CHAPName
,
720 IfrNvData
->Keyword
[Index
].ISCSIChapUsername
,
721 ISCSI_CHAP_NAME_STORAGE
724 AsciiStrToUnicodeStrS (
725 AuthConfigData
->CHAPSecret
,
726 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
727 ISCSI_CHAP_SECRET_STORAGE
730 AsciiStrToUnicodeStrS (
731 AuthConfigData
->ReverseCHAPName
,
732 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
733 ISCSI_CHAP_NAME_STORAGE
736 AsciiStrToUnicodeStrS (
737 AuthConfigData
->ReverseCHAPSecret
,
738 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
739 ISCSI_CHAP_SECRET_STORAGE
744 CopyMem(IfrNvData
->ISCSIDisplayAttemptList
, AttemptNameList
, ATTEMPT_NAME_LIST_SIZE
);
749 Convert the IFR data to iSCSI configuration data.
751 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
752 @param[in, out] Attempt The iSCSI attempt config data.
754 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
755 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
756 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
757 @retval EFI_ABORTED The operation is aborted.
758 @retval EFI_SUCCESS The operation is completed successfully.
762 IScsiConvertIfrNvDataToAttemptConfigData (
763 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
764 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
767 EFI_IP_ADDRESS HostIp
;
768 EFI_IP_ADDRESS SubnetMask
;
769 EFI_IP_ADDRESS Gateway
;
771 CHAR16
*AttemptName1
;
772 CHAR16
*AttemptName2
;
773 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
774 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
775 CHAR16 IScsiMode
[64];
777 ISCSI_NIC_INFO
*NicInfo
;
779 UINT8
*AttemptConfigOrder
;
780 UINTN AttemptConfigOrderSize
;
781 UINT8
*AttemptOrderTmp
;
785 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
786 return EFI_INVALID_PARAMETER
;
790 // Update those fields which don't have INTERACTIVE attribute.
792 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
793 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
794 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
796 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
797 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
798 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
800 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
801 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
804 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
807 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
809 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
810 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
814 // Only do full parameter validation if iSCSI is enabled on this device.
816 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
817 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
819 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
821 L
"Connection Establishing Timeout is less than minimum value 100ms.",
825 return EFI_INVALID_PARAMETER
;
829 // Validate the address configuration of the Initiator if DHCP isn't
832 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
833 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
834 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
835 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
837 if ((Gateway
.Addr
[0] != 0)) {
838 if (SubnetMask
.Addr
[0] == 0) {
840 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
842 L
"Gateway address is set but subnet mask is zero.",
846 return EFI_INVALID_PARAMETER
;
847 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
849 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
851 L
"Local IP and Gateway are not in the same subnet.",
855 return EFI_INVALID_PARAMETER
;
860 // Validate target configuration if DHCP isn't deployed.
862 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
863 if (!Attempt
->SessionConfigData
.DnsMode
) {
864 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
866 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
868 L
"Target IP is invalid!",
871 return EFI_INVALID_PARAMETER
;
874 if (Attempt
->SessionConfigData
.TargetUrl
[0] == '\0') {
876 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
878 L
"iSCSI target Url should not be NULL!",
881 return EFI_INVALID_PARAMETER
;
886 // Validate iSCSI target name configuration again:
887 // The format of iSCSI target name is already verified in IScsiFormCallback() when
888 // user input the name; here we only check the case user does not input the name.
890 if (Attempt
->SessionConfigData
.TargetName
[0] == '\0') {
892 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
894 L
"iSCSI target name is NULL!",
897 return EFI_INVALID_PARAMETER
;
902 // Validate the authentication info.
904 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
905 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
907 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
909 L
"CHAP Name or CHAP Secret is invalid!",
913 return EFI_INVALID_PARAMETER
;
916 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
917 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
920 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
922 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
925 return EFI_INVALID_PARAMETER
;
930 // Check whether this attempt uses NIC which is already used by existing attempt.
932 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
933 if (SameNicAttempt
!= NULL
) {
934 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
935 if (AttemptName1
== NULL
) {
936 return EFI_OUT_OF_RESOURCES
;
939 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
940 if (AttemptName2
== NULL
) {
941 FreePool (AttemptName1
);
942 return EFI_OUT_OF_RESOURCES
;
945 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
946 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
949 mPrivate
->PortString
,
950 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
951 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
957 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
959 mPrivate
->PortString
,
963 FreePool (AttemptName1
);
964 FreePool (AttemptName2
);
969 // Update the iSCSI Mode data and record it in attempt help info.
971 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
972 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
973 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
974 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
975 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
976 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
979 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
980 UnicodeSPrint (IpMode
, 64, L
"IP4");
981 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
982 UnicodeSPrint (IpMode
, 64, L
"IP6");
983 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
984 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
987 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
988 if (NicInfo
== NULL
) {
989 return EFI_NOT_FOUND
;
992 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
993 if (MacString
== NULL
) {
994 return EFI_OUT_OF_RESOURCES
;
997 AsciiStrToUnicodeStrS (Attempt
->MacString
, MacString
, ISCSI_MAX_MAC_STRING_LEN
);
1000 mPrivate
->PortString
,
1001 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1002 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
1005 NicInfo
->DeviceNumber
,
1006 NicInfo
->FunctionNumber
,
1011 Attempt
->AttemptTitleHelpToken
= HiiSetString (
1012 mCallbackInfo
->RegisteredHandle
,
1013 Attempt
->AttemptTitleHelpToken
,
1014 mPrivate
->PortString
,
1017 if (Attempt
->AttemptTitleHelpToken
== 0) {
1018 FreePool (MacString
);
1019 return EFI_OUT_OF_RESOURCES
;
1023 // Check whether this attempt is an existing one.
1025 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
1026 if (ExistAttempt
!= NULL
) {
1027 ASSERT (ExistAttempt
== Attempt
);
1029 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
1030 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1033 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1035 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1036 if (mPrivate
->MpioCount
< 1) {
1040 if (--mPrivate
->MpioCount
== 0) {
1041 mPrivate
->EnableMpio
= FALSE
;
1043 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1044 if (mPrivate
->SinglePathCount
< 1) {
1047 mPrivate
->SinglePathCount
--;
1050 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
1051 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1053 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1055 if (mPrivate
->SinglePathCount
< 1) {
1059 mPrivate
->EnableMpio
= TRUE
;
1060 mPrivate
->MpioCount
++;
1061 mPrivate
->SinglePathCount
--;
1063 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
1064 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1066 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1068 if (mPrivate
->MpioCount
< 1) {
1072 if (--mPrivate
->MpioCount
== 0) {
1073 mPrivate
->EnableMpio
= FALSE
;
1075 mPrivate
->SinglePathCount
++;
1077 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
1078 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
1080 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1082 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1083 mPrivate
->EnableMpio
= TRUE
;
1084 mPrivate
->MpioCount
++;
1086 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1087 mPrivate
->SinglePathCount
++;
1091 } else if (ExistAttempt
== NULL
) {
1093 // When a new attempt is created, pointer of the attempt is saved to
1094 // mCallbackInfo->Current in IScsiConfigProcessDefault. If input Attempt
1095 // does not match any existing attempt, it should be a new created attempt.
1096 // Save it to system now.
1100 // Save current order number for this attempt.
1102 AttemptConfigOrder
= IScsiGetVariableAndSize (
1105 &AttemptConfigOrderSize
1108 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1112 // Append the new created attempt order to the end.
1114 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
1115 if (AttemptOrderTmp
== NULL
) {
1116 if (AttemptConfigOrder
!= NULL
) {
1117 FreePool (AttemptConfigOrder
);
1119 return EFI_OUT_OF_RESOURCES
;
1122 if (AttemptConfigOrder
!= NULL
) {
1123 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
1124 FreePool (AttemptConfigOrder
);
1127 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
1128 AttemptConfigOrder
= AttemptOrderTmp
;
1129 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
1131 Status
= gRT
->SetVariable (
1134 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1135 AttemptConfigOrderSize
,
1138 FreePool (AttemptConfigOrder
);
1139 if (EFI_ERROR (Status
)) {
1144 // Insert new created attempt to array.
1146 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
1147 mPrivate
->AttemptCount
++;
1149 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1151 // This new Attempt is enabled for MPIO; enable the multipath mode.
1153 mPrivate
->EnableMpio
= TRUE
;
1154 mPrivate
->MpioCount
++;
1155 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1156 mPrivate
->SinglePathCount
++;
1159 IScsiConfigUpdateAttempt ();
1161 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1164 // Record the user configuration information in NVR.
1166 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1168 FreePool (MacString
);
1170 return gRT
->SetVariable (
1171 mPrivate
->PortString
,
1172 &gEfiIScsiInitiatorNameProtocolGuid
,
1173 ISCSI_CONFIG_VAR_ATTR
,
1174 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1180 Convert the IFR data configured by keyword to iSCSI configuration data.
1182 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
1183 @param[in] OffSet The offset of the variable to the configuration structure.
1185 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
1186 @retval EFI_SUCCESS The operation is completed successfully.
1190 IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (
1191 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
1195 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
1198 CHAR16
*AttemptName1
;
1199 CHAR16
*AttemptName2
;
1200 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
1201 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
1202 CHAR8 IScsiName
[ISCSI_NAME_MAX_SIZE
];
1203 CHAR8 IpString
[IP_STR_MAX_SIZE
];
1204 EFI_IP_ADDRESS HostIp
;
1205 EFI_IP_ADDRESS SubnetMask
;
1206 EFI_IP_ADDRESS Gateway
;
1212 ZeroMem (IScsiName
, sizeof (IScsiName
));
1214 if (OffSet
< ATTEMPT_BOOTENABLE_VAR_OFFSET
) {
1217 } else if ((OffSet
>= ATTEMPT_BOOTENABLE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
)) {
1218 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_BOOTENABLE_VAR_OFFSET
) + 1);
1219 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1220 if (Attempt
== NULL
) {
1221 return EFI_INVALID_PARAMETER
;
1223 IfrNvData
->Enabled
= IfrNvData
->ISCSIBootEnableList
[AttemptIndex
- 1];
1225 // Validate the configuration of attempt.
1227 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
1229 // Check whether this attempt uses NIC which is already used by existing attempt.
1231 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
1232 if (SameNicAttempt
!= NULL
) {
1233 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
1234 if (AttemptName1
== NULL
) {
1235 return EFI_OUT_OF_RESOURCES
;
1238 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
1239 if (AttemptName2
== NULL
) {
1240 FreePool (AttemptName1
);
1241 return EFI_OUT_OF_RESOURCES
;
1244 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
1245 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
1248 mPrivate
->PortString
,
1249 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1250 L
"Warning! \"%s\" uses same NIC as Attempt \"%s\".",
1256 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1258 mPrivate
->PortString
,
1262 FreePool (AttemptName1
);
1263 FreePool (AttemptName2
);
1267 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
1268 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1271 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1273 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1274 if (mPrivate
->MpioCount
< 1) {
1278 if (--mPrivate
->MpioCount
== 0) {
1279 mPrivate
->EnableMpio
= FALSE
;
1281 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1282 if (mPrivate
->SinglePathCount
< 1) {
1285 mPrivate
->SinglePathCount
--;
1288 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
1289 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1291 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1293 if (mPrivate
->SinglePathCount
< 1) {
1297 mPrivate
->EnableMpio
= TRUE
;
1298 mPrivate
->MpioCount
++;
1299 mPrivate
->SinglePathCount
--;
1301 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
1302 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1304 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1306 if (mPrivate
->MpioCount
< 1) {
1310 if (--mPrivate
->MpioCount
== 0) {
1311 mPrivate
->EnableMpio
= FALSE
;
1313 mPrivate
->SinglePathCount
++;
1315 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
1316 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
1318 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1320 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1321 mPrivate
->EnableMpio
= TRUE
;
1322 mPrivate
->MpioCount
++;
1324 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1325 mPrivate
->SinglePathCount
++;
1328 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1330 } else if ((OffSet
>= ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_RETRY_VAR_OFFSET
)) {
1331 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) + 1);
1332 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1333 if (Attempt
== NULL
) {
1334 return EFI_INVALID_PARAMETER
;
1336 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->ISCSIIpAddressTypeList
[AttemptIndex
- 1];
1337 if (Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
1338 Attempt
->AutoConfigureMode
= 0;
1341 } else if ((OffSet
>= ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
)) {
1342 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) + 1);
1343 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1344 if (Attempt
== NULL
) {
1345 return EFI_INVALID_PARAMETER
;
1347 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1];
1348 if (Attempt
->SessionConfigData
.ConnectRetryCount
== 0) {
1349 Attempt
->SessionConfigData
.ConnectRetryCount
= CONNECT_MIN_RETRY
;
1352 } else if ((OffSet
>= ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
)) {
1353 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) / 2 + 1);
1354 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1355 if (Attempt
== NULL
) {
1356 return EFI_INVALID_PARAMETER
;
1358 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1];
1359 if (Attempt
->SessionConfigData
.ConnectTimeout
== 0) {
1360 Attempt
->SessionConfigData
.ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1363 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1364 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
1366 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1368 L
"Connection Establishing Timeout is less than minimum value 100ms.",
1371 return EFI_INVALID_PARAMETER
;
1375 } else if ((OffSet
>= ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
)) {
1376 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) + 1);
1377 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1378 if (Attempt
== NULL
) {
1379 return EFI_INVALID_PARAMETER
;
1381 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->ISCSIInitiatorInfoViaDHCP
[AttemptIndex
- 1];
1383 } else if ((OffSet
>= ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
)) {
1384 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) + 1);
1385 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1386 if (Attempt
== NULL
) {
1387 return EFI_INVALID_PARAMETER
;
1390 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1391 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->ISCSITargetInfoViaDHCP
[AttemptIndex
- 1];
1394 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1396 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1399 return EFI_INVALID_PARAMETER
;
1402 } else if ((OffSet
>= ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
) && (OffSet
< ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
)) {
1403 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
) / 2 + 1);
1404 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1405 if (Attempt
== NULL
) {
1406 return EFI_INVALID_PARAMETER
;
1408 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1409 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->ISCSITargetTcpPort
[AttemptIndex
- 1];
1410 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
1411 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1415 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1417 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1420 return EFI_INVALID_PARAMETER
;
1423 } else if ((OffSet
>= ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHARTYPE_VAR_OFFSET
)) {
1424 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
) + 1);
1425 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1426 if (Attempt
== NULL
) {
1427 return EFI_INVALID_PARAMETER
;
1430 Attempt
->AuthenticationType
= IfrNvData
->ISCSIAuthenticationMethod
[AttemptIndex
- 1];
1432 } else if ((OffSet
>= ATTEMPT_CHARTYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ISID_VAR_OFFSET
)) {
1433 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CHARTYPE_VAR_OFFSET
) + 1);
1434 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1435 if (Attempt
== NULL
) {
1436 return EFI_INVALID_PARAMETER
;
1438 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1439 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->ISCSIChapType
[AttemptIndex
- 1];
1442 } else if (OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) {
1443 Index
= (UINT8
) ((OffSet
- ATTEMPT_ISID_VAR_OFFSET
) / sizeof (KEYWORD_STR
));
1444 AttemptIndex
= Index
+ 1;
1445 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1446 if (Attempt
== NULL
) {
1447 return EFI_INVALID_PARAMETER
;
1450 OffSet
= OffSet
- Index
* sizeof (KEYWORD_STR
);
1452 if ((OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
)) {
1453 IScsiParseIsIdFromString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, Attempt
->SessionConfigData
.IsId
);
1455 } else if ((OffSet
>= ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
)) {
1456 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1460 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
, &HostIp
.v4
);
1461 if (EFI_ERROR (Status
) || ((Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1462 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
)))) {
1464 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1466 L
"Invalid IP address!",
1469 return EFI_INVALID_PARAMETER
;
1471 CopyMem (&Attempt
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
1475 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1477 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1480 return EFI_INVALID_PARAMETER
;
1483 } else if ((OffSet
>= ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
)) {
1484 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1485 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
, &SubnetMask
.v4
);
1486 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
1488 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1490 L
"Invalid Subnet Mask!",
1493 return EFI_INVALID_PARAMETER
;
1495 CopyMem (&Attempt
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
1499 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1501 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1504 return EFI_INVALID_PARAMETER
;
1507 } else if ((OffSet
>= ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_NAME_VAR_OFFSET
)) {
1508 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1509 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
, &Gateway
.v4
);
1510 if (EFI_ERROR (Status
) ||
1511 ((Gateway
.Addr
[0] != 0) && (Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1512 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
)))) {
1514 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1516 L
"Invalid Gateway!",
1519 return EFI_INVALID_PARAMETER
;
1521 CopyMem (&Attempt
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
1525 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1527 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1530 return EFI_INVALID_PARAMETER
;
1533 } else if ((OffSet
>= ATTEMPT_TARGET_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
)) {
1534 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1535 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
1536 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
1537 if (EFI_ERROR (Status
)) {
1539 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1541 L
"Invalid iSCSI Name!",
1545 AsciiStrCpyS (Attempt
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
1547 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1548 if (Attempt
->SessionConfigData
.TargetName
[0] == L
'\0') {
1550 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1552 L
"iSCSI target name is NULL!",
1555 return EFI_INVALID_PARAMETER
;
1560 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1562 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1565 return EFI_INVALID_PARAMETER
;
1568 } else if ((OffSet
>= ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_LUN_VAR_OFFSET
)) {
1569 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1570 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, IpString
, sizeof (IpString
));
1571 Status
= IScsiAsciiStrToIp (IpString
, Attempt
->SessionConfigData
.IpMode
, &HostIp
);
1572 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, Attempt
->SessionConfigData
.IpMode
)) {
1573 Attempt
->SessionConfigData
.DnsMode
= TRUE
;
1574 ZeroMem (&Attempt
->SessionConfigData
.TargetIp
, sizeof (Attempt
->SessionConfigData
.TargetIp
));
1575 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, Attempt
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
1577 Attempt
->SessionConfigData
.DnsMode
= FALSE
;
1578 CopyMem (&Attempt
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
1582 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1584 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1587 return EFI_INVALID_PARAMETER
;
1590 } else if ((OffSet
>= ATTEMPT_LUN_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
)) {
1591 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.TargetInfoFromDhcp
== 0)) {
1595 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSILun
, LunString
, ISCSI_LUN_STR_MAX_LEN
);
1596 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
1597 if (EFI_ERROR (Status
)) {
1599 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1601 L
"Invalid LUN string, Examples are: 4752-3A4F-6b7e-2F99, 6734-9-156f-127, 4186-9!",
1605 CopyMem (&Attempt
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
1609 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1611 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1614 return EFI_INVALID_PARAMETER
;
1617 } else if ((OffSet
>= ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_SECRET_VAR_OFFSET
)) {
1618 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1619 UnicodeStrToAsciiStrS (
1620 IfrNvData
->Keyword
[Index
].ISCSIChapUsername
,
1621 Attempt
->AuthConfigData
.CHAP
.CHAPName
,
1622 ISCSI_CHAP_NAME_STORAGE
1625 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1626 if (IfrNvData
->CHAPName
[0] == L
'\0') {
1628 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1630 L
"CHAP Name is invalid!",
1633 return EFI_INVALID_PARAMETER
;
1638 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1640 L
"Invalid Configuration, Check value of AuthenticationType!",
1643 return EFI_INVALID_PARAMETER
;
1646 } else if ((OffSet
>= ATTEMPT_CHAR_SECRET_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
)) {
1647 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1648 UnicodeStrToAsciiStrS (
1649 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
1650 Attempt
->AuthConfigData
.CHAP
.CHAPSecret
,
1651 ISCSI_CHAP_SECRET_STORAGE
1654 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1655 if (IfrNvData
->CHAPSecret
[0] == L
'\0') {
1657 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1659 L
"CHAP Secret is invalid!",
1662 return EFI_INVALID_PARAMETER
;
1667 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1669 L
"Invalid Configuration, Check value of AuthenticationType!",
1672 return EFI_INVALID_PARAMETER
;
1675 } else if ((OffSet
>= ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
)) {
1676 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1677 UnicodeStrToAsciiStrS (
1678 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
1679 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPName
,
1680 ISCSI_CHAP_NAME_STORAGE
1682 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1683 if (IfrNvData
->ReverseCHAPName
[0] == L
'\0') {
1685 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1687 L
"Reverse CHAP Name is invalid!",
1690 return EFI_INVALID_PARAMETER
;
1695 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1697 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1700 return EFI_INVALID_PARAMETER
;
1703 } else if (OffSet
>= ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
) {
1704 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1705 UnicodeStrToAsciiStrS (
1706 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
1707 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
1708 ISCSI_CHAP_SECRET_STORAGE
1711 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1712 if (IfrNvData
->ReverseCHAPSecret
[0] == L
'\0') {
1714 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1716 L
"Reverse CHAP Secret is invalid!",
1719 return EFI_INVALID_PARAMETER
;
1724 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1726 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1729 return EFI_INVALID_PARAMETER
;
1737 // Record the user configuration information in NVR.
1739 ASSERT (Attempt
!= NULL
);
1740 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1741 return gRT
->SetVariable (
1742 mPrivate
->PortString
,
1743 &gEfiIScsiInitiatorNameProtocolGuid
,
1744 ISCSI_CONFIG_VAR_ATTR
,
1745 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1752 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
1755 @param[in] StartLabelNumber The number of start label.
1756 @param[out] StartOpCodeHandle Points to the start opcode handle.
1757 @param[out] StartLabel Points to the created start opcode.
1758 @param[out] EndOpCodeHandle Points to the end opcode handle.
1759 @param[out] EndLabel Points to the created end opcode.
1761 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
1763 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1764 @retval EFI_SUCCESS The operation is completed successfully.
1769 IN UINT16 StartLabelNumber
,
1770 OUT VOID
**StartOpCodeHandle
,
1771 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
1772 OUT VOID
**EndOpCodeHandle
,
1773 OUT EFI_IFR_GUID_LABEL
**EndLabel
1777 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
1778 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
1780 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
1781 return EFI_INVALID_PARAMETER
;
1784 *StartOpCodeHandle
= NULL
;
1785 *EndOpCodeHandle
= NULL
;
1786 Status
= EFI_OUT_OF_RESOURCES
;
1789 // Initialize the container for dynamic opcodes.
1791 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1792 if (*StartOpCodeHandle
== NULL
) {
1796 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1797 if (*EndOpCodeHandle
== NULL
) {
1802 // Create Hii Extend Label OpCode as the start opcode.
1804 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1808 sizeof (EFI_IFR_GUID_LABEL
)
1810 if (InternalStartLabel
== NULL
) {
1814 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1815 InternalStartLabel
->Number
= StartLabelNumber
;
1818 // Create Hii Extend Label OpCode as the end opcode.
1820 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1824 sizeof (EFI_IFR_GUID_LABEL
)
1826 if (InternalEndLabel
== NULL
) {
1830 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1831 InternalEndLabel
->Number
= LABEL_END
;
1833 *StartLabel
= InternalStartLabel
;
1834 *EndLabel
= InternalEndLabel
;
1840 if (*StartOpCodeHandle
!= NULL
) {
1841 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
1844 if (*EndOpCodeHandle
!= NULL
) {
1845 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
1851 Update the MAIN form to display the configured attempts.
1855 IScsiConfigUpdateAttempt (
1860 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1861 VOID
*StartOpCodeHandle
;
1862 EFI_IFR_GUID_LABEL
*StartLabel
;
1863 VOID
*EndOpCodeHandle
;
1864 EFI_IFR_GUID_LABEL
*EndLabel
;
1867 Status
= IScsiCreateOpCode (
1868 ATTEMPT_ENTRY_LABEL
,
1874 if (EFI_ERROR (Status
)) {
1878 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1879 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1880 if (AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
1882 // Update Attempt Help Info.
1884 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", (UINTN
) AttemptConfigData
->AttemptConfigIndex
);
1885 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1886 mCallbackInfo
->RegisteredHandle
,
1888 mPrivate
->PortString
,
1891 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1895 HiiCreateGotoOpCode (
1896 StartOpCodeHandle
, // Container for dynamic created opcodes
1897 FORMID_ATTEMPT_FORM
, // Form ID
1898 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1899 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1900 EFI_IFR_FLAG_CALLBACK
, // Question flag
1901 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1907 mCallbackInfo
->RegisteredHandle
, // HII handle
1908 &gIScsiConfigGuid
, // Formset GUID
1909 FORMID_MAIN_FORM
, // Form ID
1910 StartOpCodeHandle
, // Label for where to insert opcodes
1911 EndOpCodeHandle
// Replace data
1914 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1915 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1919 Callback function when user presses "Add an Attempt".
1921 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1923 @retval EFI_SUCCESS The operation is completed successfully.
1927 IScsiConfigAddAttempt (
1932 ISCSI_NIC_INFO
*NicInfo
;
1933 EFI_STRING_ID PortTitleToken
;
1934 EFI_STRING_ID PortTitleHelpToken
;
1935 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1937 VOID
*StartOpCodeHandle
;
1938 EFI_IFR_GUID_LABEL
*StartLabel
;
1939 VOID
*EndOpCodeHandle
;
1940 EFI_IFR_GUID_LABEL
*EndLabel
;
1942 Status
= IScsiCreateOpCode (
1949 if (EFI_ERROR (Status
)) {
1954 // Ask user to select a MAC for this attempt.
1956 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
1957 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
1959 &NicInfo
->PermanentAddress
,
1960 NicInfo
->HwAddressSize
,
1965 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
1966 PortTitleToken
= HiiSetString (
1967 mCallbackInfo
->RegisteredHandle
,
1969 mPrivate
->PortString
,
1972 if (PortTitleToken
== 0) {
1973 Status
= EFI_INVALID_PARAMETER
;
1978 mPrivate
->PortString
,
1979 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1980 L
"PFA: Bus %d | Dev %d | Func %d",
1982 NicInfo
->DeviceNumber
,
1983 NicInfo
->FunctionNumber
1985 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
1986 if (PortTitleHelpToken
== 0) {
1987 Status
= EFI_INVALID_PARAMETER
;
1991 HiiCreateGotoOpCode (
1992 StartOpCodeHandle
, // Container for dynamic created opcodes
1993 FORMID_ATTEMPT_FORM
,
1996 EFI_IFR_FLAG_CALLBACK
, // Question flag
1997 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
2001 Status
= HiiUpdateForm (
2002 mCallbackInfo
->RegisteredHandle
, // HII handle
2003 &gIScsiConfigGuid
, // Formset GUID
2004 FORMID_MAC_FORM
, // Form ID
2005 StartOpCodeHandle
, // Label for where to insert opcodes
2006 EndOpCodeHandle
// Replace data
2010 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2011 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2017 Add the attempts by keyword 'iSCSIAddAttempts', you can use this keyword with
2018 value 'attempt:1 attempt:2' etc to add one or more attempts once. This is different
2019 with IScsiConfigAddAttempt function which is used to add attempt by UI configuration.
2021 @param[in] AttemptList The new attempt List will be added.
2023 @retval EFI_SUCCESS The operation to add attempt list successfully.
2024 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2025 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2026 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2031 IScsiConfigAddAttemptsByKeywords (
2032 IN UINT8
*AttemptList
2039 UINT8
*AttemptConfigOrder
;
2040 UINTN AttemptConfigOrderSize
;
2041 UINT8
*AttemptConfigOrderTmp
;
2042 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2043 ISCSI_NIC_INFO
*NicInfo
;
2044 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2045 CHAR16 IScsiMode
[64];
2049 Nic
= mPrivate
->CurrentNic
;
2050 NicInfo
= IScsiGetNicInfoByIndex (Nic
);
2051 if (NicInfo
== NULL
) {
2052 return EFI_NOT_FOUND
;
2056 // The MAC info will be recorded in Config Data.
2059 &NicInfo
->PermanentAddress
,
2060 NicInfo
->HwAddressSize
,
2065 for (Index
= 0; Index
< PcdGet8 (PcdMaxIScsiAttemptNumber
); Index
++) {
2066 if (AttemptList
[Index
] == 0) {
2073 Number
= AttemptList
[Index
];
2076 mPrivate
->PortString
,
2077 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2083 mPrivate
->PortString
,
2084 &gEfiIScsiInitiatorNameProtocolGuid
,
2085 (VOID
**)&AttemptConfigData
,
2088 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2089 return EFI_INVALID_PARAMETER
;
2092 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2093 AttemptConfigData
->NicIndex
= NicInfo
->NicIndex
;
2094 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, ISCSI_MAX_MAC_STRING_LEN
);
2097 // Generate OUI-format ISID based on MAC address.
2099 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2100 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2101 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2104 // Configure the iSCSI Mode and IpMode to default.
2105 // Add Attempt Help Info.
2107 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
2108 UnicodeSPrint (IpMode
, 64, L
"IP4");
2110 mPrivate
->PortString
,
2111 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2112 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
2115 NicInfo
->DeviceNumber
,
2116 NicInfo
->FunctionNumber
,
2121 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2122 mCallbackInfo
->RegisteredHandle
,
2124 mPrivate
->PortString
,
2127 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2128 return EFI_OUT_OF_RESOURCES
;
2132 // Get current Attempt order and number.
2134 AttemptConfigOrder
= IScsiGetVariableAndSize (
2137 &AttemptConfigOrderSize
2139 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2143 // Append the new created attempt order to the end.
2145 AttemptConfigOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
2146 if (AttemptConfigOrderTmp
== NULL
) {
2147 if (AttemptConfigOrder
!= NULL
) {
2148 FreePool (AttemptConfigOrder
);
2150 return EFI_OUT_OF_RESOURCES
;
2152 if (AttemptConfigOrder
!= NULL
) {
2153 CopyMem (AttemptConfigOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
2154 FreePool (AttemptConfigOrder
);
2157 AttemptConfigOrderTmp
[TotalNumber
- 1] = Number
;
2158 AttemptConfigOrder
= AttemptConfigOrderTmp
;
2159 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
2161 Status
= gRT
->SetVariable (
2164 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2165 AttemptConfigOrderSize
,
2168 FreePool (AttemptConfigOrder
);
2169 if (EFI_ERROR (Status
)) {
2174 // Record the attempt in global link list.
2176 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2177 mPrivate
->AttemptCount
++;
2178 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", AttemptConfigData
->AttemptConfigIndex
);
2180 mPrivate
->PortString
,
2181 &gEfiIScsiInitiatorNameProtocolGuid
,
2182 ISCSI_CONFIG_VAR_ATTR
,
2183 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2193 Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword.
2195 @param[in] IfrNvData The IFR NV data.
2197 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2198 @retval EFI_SUCCESS The operation is completed successfully.
2199 @retval EFI_ABOTRED This operation is aborted cause of error
2201 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2206 IScsiConfigDeleteAttempts (
2207 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2213 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2214 UINT8
*AttemptConfigOrder
;
2215 UINTN AttemptConfigOrderSize
;
2216 UINT8
*AttemptNewOrder
;
2217 UINT8 AttemptConfigIndex
;
2222 LIST_ENTRY
*NextEntry
;
2223 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
2227 AttemptConfigOrder
= IScsiGetVariableAndSize (
2230 &AttemptConfigOrderSize
2232 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
2233 return EFI_NOT_FOUND
;
2236 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
2237 if (AttemptNewOrder
== NULL
) {
2238 Status
= EFI_OUT_OF_RESOURCES
;
2242 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2245 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
2246 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
2252 // Delete the attempt.
2255 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2256 if (AttemptConfigData
== NULL
) {
2257 Status
= EFI_NOT_FOUND
;
2262 // Remove this attempt from UI configured attempt list.
2264 RemoveEntryList (&AttemptConfigData
->Link
);
2265 mPrivate
->AttemptCount
--;
2267 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
2268 if (mPrivate
->MpioCount
< 1) {
2269 Status
= EFI_ABORTED
;
2274 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
2276 if (--mPrivate
->MpioCount
== 0) {
2277 mPrivate
->EnableMpio
= FALSE
;
2279 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
2280 if (mPrivate
->SinglePathCount
< 1) {
2281 Status
= EFI_ABORTED
;
2285 mPrivate
->SinglePathCount
--;
2288 AttemptConfigIndex
= AttemptConfigData
->AttemptConfigIndex
;
2289 FreePool (AttemptConfigData
);
2292 // Create a new Attempt
2294 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
2295 if (AttemptConfigData
== NULL
) {
2296 return EFI_OUT_OF_RESOURCES
;
2298 ConfigData
= &AttemptConfigData
->SessionConfigData
;
2299 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
2300 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
2301 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
2303 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
2304 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
2306 // Configure the Attempt index and set variable.
2308 AttemptConfigData
->AttemptConfigIndex
= AttemptConfigIndex
;
2311 // Set the attempt name to default.
2314 mPrivate
->PortString
,
2315 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2317 (UINTN
) AttemptConfigData
->AttemptConfigIndex
2319 UnicodeStrToAsciiStrS (mPrivate
->PortString
, AttemptConfigData
->AttemptName
, ATTEMPT_NAME_SIZE
);
2321 mPrivate
->PortString
,
2322 &gEfiIScsiInitiatorNameProtocolGuid
,
2323 ISCSI_CONFIG_VAR_ATTR
,
2324 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2329 // Mark the attempt order in NVR to be deleted - 0.
2331 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
2332 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
2333 AttemptConfigOrder
[NewIndex
] = 0;
2339 if (mCallbackInfo
->Current
== AttemptConfigData
) {
2340 mCallbackInfo
->Current
= NULL
;
2342 FreePool (AttemptConfigData
);
2345 // Check next Attempt.
2351 // Construct AttemptNewOrder.
2353 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
2354 if (AttemptConfigOrder
[Index
] != 0) {
2355 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
2360 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
2363 // Update AttemptOrder in NVR.
2365 Status
= gRT
->SetVariable (
2369 NewTotal
* sizeof (UINT8
),
2374 if (AttemptConfigOrder
!= NULL
) {
2375 FreePool (AttemptConfigOrder
);
2378 if (AttemptNewOrder
!= NULL
) {
2379 FreePool (AttemptNewOrder
);
2387 Callback function when user presses "Delete Attempts".
2389 @param[in] IfrNvData The IFR nv data.
2391 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2392 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
2393 @retval EFI_SUCCESS The operation is completed successfully.
2397 IScsiConfigDisplayDeleteAttempts (
2398 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2402 UINT8
*AttemptConfigOrder
;
2403 UINTN AttemptConfigOrderSize
;
2405 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2407 VOID
*StartOpCodeHandle
;
2408 EFI_IFR_GUID_LABEL
*StartLabel
;
2409 VOID
*EndOpCodeHandle
;
2410 EFI_IFR_GUID_LABEL
*EndLabel
;
2413 Status
= IScsiCreateOpCode (
2420 if (EFI_ERROR (Status
)) {
2424 AttemptConfigOrder
= IScsiGetVariableAndSize (
2427 &AttemptConfigOrderSize
2429 if (AttemptConfigOrder
!= NULL
) {
2431 // Create the check box opcode to be deleted.
2435 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2436 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2437 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
2439 HiiCreateCheckBoxOpCode(
2441 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
2442 CONFIGURATION_VARSTORE_ID
,
2443 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
2444 AttemptConfigData
->AttemptTitleToken
,
2445 AttemptConfigData
->AttemptTitleHelpToken
,
2453 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
2458 FreePool (AttemptConfigOrder
);
2461 Status
= HiiUpdateForm (
2462 mCallbackInfo
->RegisteredHandle
, // HII handle
2463 &gIScsiConfigGuid
, // Formset GUID
2464 FORMID_DELETE_FORM
, // Form ID
2465 StartOpCodeHandle
, // Label for where to insert opcodes
2466 EndOpCodeHandle
// Replace data
2469 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2470 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2477 Callback function when user presses "Change Attempt Order".
2479 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2480 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2482 @retval EFI_SUCCESS The operation is completed successfully.
2486 IScsiConfigDisplayOrderAttempts (
2493 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2494 VOID
*StartOpCodeHandle
;
2495 EFI_IFR_GUID_LABEL
*StartLabel
;
2496 VOID
*EndOpCodeHandle
;
2497 EFI_IFR_GUID_LABEL
*EndLabel
;
2498 VOID
*OptionsOpCodeHandle
;
2500 Status
= IScsiCreateOpCode (
2507 if (EFI_ERROR (Status
)) {
2510 ASSERT (StartOpCodeHandle
!= NULL
);
2512 OptionsOpCodeHandle
= NULL
;
2515 // If no attempt to be ordered, update the original form and exit.
2517 if (mPrivate
->AttemptCount
== 0) {
2522 // Create Option OpCode.
2524 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
2525 if (OptionsOpCodeHandle
== NULL
) {
2526 Status
= EFI_OUT_OF_RESOURCES
;
2532 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2533 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2534 HiiCreateOneOfOptionOpCode (
2535 OptionsOpCodeHandle
,
2536 AttemptConfigData
->AttemptTitleToken
,
2538 EFI_IFR_NUMERIC_SIZE_1
,
2539 AttemptConfigData
->AttemptConfigIndex
2544 ASSERT (Index
== mPrivate
->AttemptCount
);
2546 HiiCreateOrderedListOpCode (
2547 StartOpCodeHandle
, // Container for dynamic created opcodes
2548 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
2549 CONFIGURATION_VARSTORE_ID
, // VarStore ID
2550 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
2551 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
2552 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
2554 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
2555 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
2556 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
2557 OptionsOpCodeHandle
, // Option Opcode list
2558 NULL
// Default Opcode is NULL
2562 Status
= HiiUpdateForm (
2563 mCallbackInfo
->RegisteredHandle
, // HII handle
2564 &gIScsiConfigGuid
, // Formset GUID
2565 FORMID_ORDER_FORM
, // Form ID
2566 StartOpCodeHandle
, // Label for where to insert opcodes
2567 EndOpCodeHandle
// Replace data
2571 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2572 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2573 if (OptionsOpCodeHandle
!= NULL
) {
2574 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
2581 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.
2583 @param[in] IfrNvData The IFR nv data.
2585 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2587 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2588 @retval EFI_SUCCESS The operation is completed successfully.
2592 IScsiConfigOrderAttempts (
2593 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2599 UINT8 AttemptConfigIndex
;
2600 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2601 UINT8
*AttemptConfigOrder
;
2602 UINT8
*AttemptConfigOrderTmp
;
2603 UINTN AttemptConfigOrderSize
;
2605 AttemptConfigOrder
= IScsiGetVariableAndSize (
2608 &AttemptConfigOrderSize
2610 if (AttemptConfigOrder
== NULL
) {
2611 return EFI_NOT_FOUND
;
2614 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
2615 if (AttemptConfigOrderTmp
== NULL
) {
2616 Status
= EFI_OUT_OF_RESOURCES
;
2620 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
2622 // The real content ends with 0.
2624 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
2628 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
2629 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
2630 if (AttemptConfigData
== NULL
) {
2631 Status
= EFI_NOT_FOUND
;
2636 // Reorder the Attempt List.
2638 RemoveEntryList (&AttemptConfigData
->Link
);
2639 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2641 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
2644 // Mark it to be deleted - 0.
2646 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2647 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
2648 AttemptConfigOrder
[Indexj
] = 0;
2655 // Adjust the attempt order in NVR.
2657 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2658 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2659 if (AttemptConfigOrder
[Indexj
] != 0) {
2660 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
2661 AttemptConfigOrder
[Indexj
] = 0;
2667 Status
= gRT
->SetVariable (
2670 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2671 AttemptConfigOrderSize
,
2672 AttemptConfigOrderTmp
2676 if (AttemptConfigOrderTmp
!= NULL
) {
2677 FreePool (AttemptConfigOrderTmp
);
2680 FreePool (AttemptConfigOrder
);
2686 Callback function when a user presses "Attempt *" or when a user selects a NIC to
2687 create the new attempt.
2689 @param[in] KeyValue A unique value which is sent to the original
2690 exporting driver so that it can identify the type
2692 @param[in] IfrNvData The IFR nv data.
2694 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2696 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2697 @retval EFI_UNSUPPORTED Can not create more attempts.
2698 @retval EFI_SUCCESS The operation is completed successfully.
2702 IScsiConfigProcessDefault (
2703 IN EFI_QUESTION_ID KeyValue
,
2704 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2708 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2709 UINT8 CurrentAttemptConfigIndex
;
2710 ISCSI_NIC_INFO
*NicInfo
;
2712 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2713 UINT8
*AttemptConfigOrder
;
2714 UINTN AttemptConfigOrderSize
;
2718 AttemptConfigData
= NULL
;
2720 // Is User creating a new attempt?
2724 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
2725 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
2727 // User has pressed "Add an Attempt" and then selects a NIC.
2730 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
2731 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
2734 // User has pressed "Attempt *".
2739 // Don't process anything.
2746 // Determine which NIC user has selected for the new created attempt.
2748 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
2749 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
2750 if (NicInfo
== NULL
) {
2751 return EFI_NOT_FOUND
;
2755 // Create an attempt following the initialized attempt order.
2757 AttemptConfigOrder
= IScsiGetVariableAndSize (
2758 L
"InitialAttemptOrder",
2760 &AttemptConfigOrderSize
2763 if (AttemptConfigOrder
== NULL
) {
2764 return EFI_NOT_FOUND
;
2767 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2769 mPrivate
->PortString
,
2770 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2772 (UINTN
) AttemptConfigOrder
[Index
]
2775 mPrivate
->PortString
,
2776 &gEfiIScsiInitiatorNameProtocolGuid
,
2777 (VOID
**)&AttemptConfigData
,
2780 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2787 if (Index
> PcdGet8 (PcdMaxIScsiAttemptNumber
)) {
2789 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2791 L
"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",
2794 return EFI_UNSUPPORTED
;
2797 if (AttemptConfigOrder
!= NULL
) {
2798 FreePool (AttemptConfigOrder
);
2802 // Record the MAC info in Config Data.
2805 &NicInfo
->PermanentAddress
,
2806 NicInfo
->HwAddressSize
,
2811 ASSERT (AttemptConfigData
!= NULL
);
2812 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, sizeof (AttemptConfigData
->MacString
));
2813 AttemptConfigData
->NicIndex
= NicIndex
;
2814 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2817 // Generate OUI-format ISID based on MAC address.
2819 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2820 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2821 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2824 // Add the help info for the new attempt.
2827 mPrivate
->PortString
,
2828 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2829 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
2832 NicInfo
->DeviceNumber
,
2833 NicInfo
->FunctionNumber
2836 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2837 mCallbackInfo
->RegisteredHandle
,
2839 mPrivate
->PortString
,
2842 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2843 FreePool (AttemptConfigData
);
2844 return EFI_OUT_OF_RESOURCES
;
2849 // Determine which Attempt user has selected to configure.
2850 // Get the attempt configuration data.
2852 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
2854 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
2855 if (AttemptConfigData
== NULL
) {
2856 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
2857 return EFI_NOT_FOUND
;
2862 // Clear the old IFR data to avoid sharing it with other attempts.
2864 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
2865 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
2866 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
2867 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
2868 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
2871 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
2874 // Update current attempt to be a new created attempt or an existing attempt.
2876 mCallbackInfo
->Current
= AttemptConfigData
;
2884 This function allows the caller to request the current
2885 configuration for one or more named elements. The resulting
2886 string is in <ConfigAltResp> format. Also, any and all alternative
2887 configuration strings shall be appended to the end of the
2888 current configuration string. If they are, they must appear
2889 after the current configuration. They must contain the same
2890 routing (GUID, NAME, PATH) as the current configuration string.
2891 They must have an additional description indicating the type of
2892 alternative configuration the string represents,
2893 "ALTCFG=<StringToken>". That <StringToken> (when
2894 converted from Hex UNICODE to binary) is a reference to a
2895 string in the associated string pack.
2897 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2899 @param[in] Request A null-terminated Unicode string in
2900 <ConfigRequest> format. Note that this
2901 includes the routing information as well as
2902 the configurable name / value pairs. It is
2903 invalid for this string to be in
2904 <MultiConfigRequest> format.
2906 @param[out] Progress On return, points to a character in the
2907 Request string. Points to the string's null
2908 terminator if request was successful. Points
2909 to the most recent "&" before the first
2910 failing name / value pair (or the beginning
2911 of the string if the failure is in the first
2912 name / value pair) if the request was not successful.
2914 @param[out] Results A null-terminated Unicode string in
2915 <ConfigAltResp> format which has all values
2916 filled in for the names in the Request string.
2917 String to be allocated by the called function.
2919 @retval EFI_SUCCESS The Results string is filled with the
2920 values corresponding to all requested
2923 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2924 parts of the results that must be
2925 stored awaiting possible future
2928 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
2929 for the Request parameter
2930 would result in this type of
2931 error. In this case, the
2932 Progress parameter would be
2935 @retval EFI_NOT_FOUND Routing data doesn't match any
2936 known driver. Progress set to the
2937 first character in the routing header.
2938 Note: There is no requirement that the
2939 driver validate the routing data. It
2940 must skip the <ConfigHdr> in order to
2943 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
2944 to most recent "&" before the
2945 error or the beginning of the
2948 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
2949 to the & before the name in
2955 IScsiFormExtractConfig (
2956 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2957 IN CONST EFI_STRING Request
,
2958 OUT EFI_STRING
*Progress
,
2959 OUT EFI_STRING
*Results
2963 CHAR8
*InitiatorName
;
2965 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
2966 ISCSI_FORM_CALLBACK_INFO
*Private
;
2967 EFI_STRING ConfigRequestHdr
;
2968 EFI_STRING ConfigRequest
;
2969 BOOLEAN AllocatedRequest
;
2972 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
2973 return EFI_INVALID_PARAMETER
;
2976 *Progress
= Request
;
2977 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
2978 return EFI_NOT_FOUND
;
2981 ConfigRequestHdr
= NULL
;
2982 ConfigRequest
= NULL
;
2983 AllocatedRequest
= FALSE
;
2986 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
2987 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
2988 if (IfrNvData
== NULL
) {
2989 return EFI_OUT_OF_RESOURCES
;
2993 if (Private
->Current
!= NULL
) {
2994 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
2998 // Extract all AttemptConfigData to Keyword stroage of IfrNvData.
3000 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData
);
3002 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3003 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3004 if (InitiatorName
== NULL
) {
3005 FreePool (IfrNvData
);
3006 return EFI_OUT_OF_RESOURCES
;
3009 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3010 if (EFI_ERROR (Status
)) {
3011 IfrNvData
->InitiatorName
[0] = L
'\0';
3013 AsciiStrToUnicodeStrS (
3015 IfrNvData
->InitiatorName
,
3016 sizeof (IfrNvData
->InitiatorName
) / sizeof (IfrNvData
->InitiatorName
[0])
3021 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
3023 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3024 ConfigRequest
= Request
;
3025 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3027 // Request has no request element, construct full request string.
3028 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3029 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3031 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
3032 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3033 ConfigRequest
= AllocateZeroPool (Size
);
3034 if (ConfigRequest
== NULL
) {
3035 FreePool (IfrNvData
);
3036 FreePool (InitiatorName
);
3037 return EFI_OUT_OF_RESOURCES
;
3039 AllocatedRequest
= TRUE
;
3040 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3041 FreePool (ConfigRequestHdr
);
3044 Status
= gHiiConfigRouting
->BlockToConfig (
3047 (UINT8
*) IfrNvData
,
3052 FreePool (IfrNvData
);
3053 FreePool (InitiatorName
);
3056 // Free the allocated config request string.
3058 if (AllocatedRequest
) {
3059 FreePool (ConfigRequest
);
3060 ConfigRequest
= NULL
;
3063 // Set Progress string to the original request string.
3065 if (Request
== NULL
) {
3067 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3068 *Progress
= Request
+ StrLen (Request
);
3077 This function applies changes in a driver's configuration.
3078 Input is a Configuration, which has the routing data for this
3079 driver followed by name / value configuration pairs. The driver
3080 must apply those pairs to its configurable storage. If the
3081 driver's configuration is stored in a linear block of data
3082 and the driver's name / value pairs are in <BlockConfig>
3083 format, it may use the ConfigToBlock helper function (above) to
3086 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3088 @param[in] Configuration A null-terminated Unicode string in
3089 <ConfigString> format.
3091 @param[out] Progress A pointer to a string filled in with the
3092 offset of the most recent '&' before the
3093 first failing name / value pair (or the
3094 beginning of the string if the failure
3095 is in the first name / value pair) or
3096 the terminating NULL if all was
3099 @retval EFI_SUCCESS The results have been distributed or are
3100 awaiting distribution.
3102 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
3103 parts of the results that must be
3104 stored awaiting possible future
3107 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
3108 Results parameter would result
3109 in this type of error.
3111 @retval EFI_NOT_FOUND Target for the specified routing data
3117 IScsiFormRouteConfig (
3118 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3119 IN CONST EFI_STRING Configuration
,
3120 OUT EFI_STRING
*Progress
3124 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3125 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3127 LIST_ENTRY
*NextEntry
;
3128 ISCSI_NIC_INFO
*NicInfo
;
3130 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
3131 CHAR8
*InitiatorName
;
3142 Status
= EFI_SUCCESS
;
3144 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
3145 return EFI_INVALID_PARAMETER
;
3149 // Check routing data in <ConfigHdr>.
3150 // Note: if only one Storage is used, then this checking could be skipped.
3152 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3153 *Progress
= Configuration
;
3154 return EFI_NOT_FOUND
;
3157 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3158 if (IfrNvData
== NULL
) {
3159 return EFI_OUT_OF_RESOURCES
;
3162 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3163 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3164 if (InitiatorName
== NULL
) {
3165 Status
= EFI_OUT_OF_RESOURCES
;
3170 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
3172 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3173 Status
= gHiiConfigRouting
->ConfigToBlock (
3176 (UINT8
*) IfrNvData
,
3180 if (EFI_ERROR (Status
)) {
3184 if (IfrNvData
->InitiatorName
[0] != L
'\0') {
3185 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, InitiatorName
, ISCSI_NAME_MAX_SIZE
);
3186 BufferSize
= AsciiStrSize (InitiatorName
);
3188 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3189 if (EFI_ERROR (Status
)) {
3191 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3193 L
"Invalid iSCSI Name!",
3199 Status
= IScsiGetValue (Configuration
, L
"&OFFSET=", &OffSet
);
3200 if (EFI_ERROR (Status
)) {
3204 if (OffSet
>= ATTEMPT_MAC_ADDR_VAR_OFFSET
) {
3205 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3206 if (EFI_ERROR (Status
)) {
3208 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3210 L
"Error: please configure iSCSI initiator name first!",
3219 if (IfrNvData
->ISCSIAddAttemptList
[0] != L
'\0') {
3220 Status
=IScsiGetAttemptIndexList (IfrNvData
->ISCSIAddAttemptList
, IfrNvData
->AddAttemptList
, TRUE
);
3221 if (EFI_ERROR (Status
)) {
3223 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3225 L
"Error: The add attempt list is invalid",
3231 Status
= IScsiConfigAddAttemptsByKeywords (IfrNvData
->AddAttemptList
);
3232 if (EFI_ERROR (Status
)) {
3236 } else if (IfrNvData
->ISCSIDeleteAttemptList
[0] != L
'\0') {
3237 AttemptList
=(UINT8
*) AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM
+ 1) * sizeof (UINT8
));
3238 if (AttemptList
== NULL
) {
3239 Status
= EFI_OUT_OF_RESOURCES
;
3242 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIDeleteAttemptList
, AttemptList
, FALSE
);
3243 if (EFI_ERROR (Status
)) {
3245 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3247 L
"Error: The delete attempt list is invalid",
3254 // Mark the attempt which will be delete in the global list.
3256 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
3257 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3258 while (AttemptList
[Index
] != 0) {
3259 if (AttemptConfigData
->AttemptConfigIndex
== AttemptList
[Index
]) {
3260 IfrNvData
->DeleteAttemptList
[Index2
] = 1;
3269 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3270 if (EFI_ERROR (Status
)) {
3274 FreePool (AttemptList
);
3276 } else if (IfrNvData
->ISCSIAttemptOrder
[0] != L
'\0') {
3277 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIAttemptOrder
, IfrNvData
->DynamicOrderedList
, FALSE
);
3278 if (EFI_ERROR (Status
)) {
3280 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3282 L
"Error: The new attempt order list is invalid",
3288 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3289 if (EFI_ERROR (Status
)) {
3293 } else if (IfrNvData
->ISCSIMacAddr
[0] != L
'\0') {
3294 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
3295 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3297 &NicInfo
->PermanentAddress
,
3298 NicInfo
->HwAddressSize
,
3302 if (!StrCmp(MacString
, IfrNvData
->ISCSIMacAddr
)) {
3303 mPrivate
->CurrentNic
= NicInfo
->NicIndex
;
3308 if ((NicInfo
== NULL
) || (NicInfo
->NicIndex
== 0)) {
3309 Status
= EFI_NOT_FOUND
;
3314 Status
= IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData
, OffSet
);
3315 if (EFI_ERROR (Status
)) {
3321 IScsiConfigUpdateAttempt ();
3324 if (InitiatorName
!= NULL
) {
3325 FreePool (InitiatorName
);
3328 if (IfrNvData
!= NULL
) {
3329 FreePool (IfrNvData
);
3337 This function is called to provide results data to the driver.
3338 This data consists of a unique key that is used to identify
3339 which data is either being passed back or being asked for.
3341 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3342 @param[in] Action Specifies the type of action taken by the browser.
3343 @param[in] QuestionId A unique value which is sent to the original
3344 exporting driver so that it can identify the type
3345 of data to expect. The format of the data tends to
3346 vary based on the opcode that generated the callback.
3347 @param[in] Type The type of value for the question.
3348 @param[in, out] Value A pointer to the data being sent to the original
3350 @param[out] ActionRequest On return, points to the action requested by the
3353 @retval EFI_SUCCESS The callback successfully handled the action.
3354 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3355 variable and its data.
3356 @retval EFI_DEVICE_ERROR The variable could not be saved.
3357 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3363 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3364 IN EFI_BROWSER_ACTION Action
,
3365 IN EFI_QUESTION_ID QuestionId
,
3367 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
3368 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3371 ISCSI_FORM_CALLBACK_INFO
*Private
;
3374 CHAR8 IpString
[ISCSI_NAME_MAX_SIZE
];
3375 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
3377 EFI_IP_ADDRESS HostIp
;
3378 EFI_IP_ADDRESS SubnetMask
;
3379 EFI_IP_ADDRESS Gateway
;
3380 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3381 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
3385 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
3387 // Do nothing for UEFI OPEN/CLOSE Action
3392 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
3394 // All other type return unsupported.
3396 return EFI_UNSUPPORTED
;
3399 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
3400 return EFI_INVALID_PARAMETER
;
3403 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3406 // Retrieve uncommitted data from Browser
3409 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3410 IfrNvData
= AllocateZeroPool (BufferSize
);
3411 if (IfrNvData
== NULL
) {
3412 return EFI_OUT_OF_RESOURCES
;
3415 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
3416 if (IScsiName
== NULL
) {
3417 FreePool (IfrNvData
);
3418 return EFI_OUT_OF_RESOURCES
;
3421 Status
= EFI_SUCCESS
;
3423 ZeroMem (&OldIfrNvData
, BufferSize
);
3425 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
3427 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
3429 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3430 switch (QuestionId
) {
3431 case KEY_ADD_ATTEMPT
:
3433 // Check whether iSCSI initiator name is configured already.
3435 mPrivate
->InitiatorNameLength
= ISCSI_NAME_MAX_SIZE
;
3436 Status
= gIScsiInitiatorName
.Get (
3437 &gIScsiInitiatorName
,
3438 &mPrivate
->InitiatorNameLength
,
3439 mPrivate
->InitiatorName
3441 if (EFI_ERROR (Status
)) {
3443 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3445 L
"Error: please configure iSCSI initiator name first!",
3451 Status
= IScsiConfigAddAttempt ();
3454 case KEY_DELETE_ATTEMPT
:
3456 OldIfrNvData
.DeleteAttemptList
,
3457 IfrNvData
->DeleteAttemptList
,
3458 sizeof (IfrNvData
->DeleteAttemptList
)
3460 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
3463 case KEY_ORDER_ATTEMPT_CONFIG
:
3465 // Order the attempt according to user input.
3468 OldIfrNvData
.DynamicOrderedList
,
3469 IfrNvData
->DynamicOrderedList
,
3470 sizeof (IfrNvData
->DynamicOrderedList
)
3472 IScsiConfigDisplayOrderAttempts ();
3476 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
3479 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3480 switch (QuestionId
) {
3481 case KEY_INITIATOR_NAME
:
3482 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3483 BufferSize
= AsciiStrSize (IScsiName
);
3485 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
3486 if (EFI_ERROR (Status
)) {
3488 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3490 L
"Invalid iSCSI Name!",
3495 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3498 case KEY_SAVE_ATTEMPT_CONFIG
:
3499 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
3500 if (EFI_ERROR (Status
)) {
3504 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3507 case KEY_SAVE_ORDER_CHANGES
:
3509 // Sync the Attempt Order to NVR.
3511 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3512 if (EFI_ERROR (Status
)) {
3516 IScsiConfigUpdateAttempt ();
3517 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3520 case KEY_IGNORE_ORDER_CHANGES
:
3522 IfrNvData
->DynamicOrderedList
,
3523 OldIfrNvData
.DynamicOrderedList
,
3524 sizeof (IfrNvData
->DynamicOrderedList
)
3526 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3529 case KEY_SAVE_DELETE_ATTEMPT
:
3531 // Delete the Attempt Order from NVR
3533 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3534 if (EFI_ERROR (Status
)) {
3538 IScsiConfigUpdateAttempt ();
3539 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3542 case KEY_IGNORE_DELETE_ATTEMPT
:
3544 IfrNvData
->DeleteAttemptList
,
3545 OldIfrNvData
.DeleteAttemptList
,
3546 sizeof (IfrNvData
->DeleteAttemptList
)
3548 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3552 switch (Value
->u8
) {
3555 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
3556 Private
->Current
->AutoConfigureMode
= 0;
3564 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
3565 if (EFI_ERROR (Status
) ||
3566 ((Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3567 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3569 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3571 L
"Invalid IP address!",
3575 Status
= EFI_INVALID_PARAMETER
;
3577 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
3582 case KEY_SUBNET_MASK
:
3583 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
3584 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
3586 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3588 L
"Invalid Subnet Mask!",
3592 Status
= EFI_INVALID_PARAMETER
;
3594 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
3600 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
3601 if (EFI_ERROR (Status
) ||
3602 ((Gateway
.Addr
[0] != 0) &&
3603 (Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3604 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3606 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3608 L
"Invalid Gateway!",
3611 Status
= EFI_INVALID_PARAMETER
;
3613 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
3619 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, IpString
, sizeof (IpString
));
3620 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
3621 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
3623 // The target is expressed in URL format or an invalid Ip address, just save.
3625 Private
->Current
->SessionConfigData
.DnsMode
= TRUE
;
3626 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (Private
->Current
->SessionConfigData
.TargetIp
));
3627 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, Private
->Current
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
3629 Private
->Current
->SessionConfigData
.DnsMode
= FALSE
;
3630 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
3635 case KEY_TARGET_NAME
:
3636 UnicodeStrToAsciiStrS (IfrNvData
->TargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3637 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
3638 if (EFI_ERROR (Status
)) {
3640 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3642 L
"Invalid iSCSI Name!",
3646 AsciiStrCpyS (Private
->Current
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
3651 case KEY_DHCP_ENABLE
:
3652 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
3653 IfrNvData
->TargetInfoFromDhcp
= 0;
3659 UnicodeStrToAsciiStrS (IfrNvData
->BootLun
, LunString
, sizeof (LunString
));
3660 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
3661 if (EFI_ERROR (Status
)) {
3663 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3665 L
"Invalid LUN string!",
3669 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
3675 switch (Value
->u8
) {
3676 case ISCSI_AUTH_TYPE_CHAP
:
3677 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
3686 UnicodeStrToAsciiStrS (
3687 IfrNvData
->CHAPName
,
3688 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
,
3689 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPName
)
3693 case KEY_CHAP_SECRET
:
3694 UnicodeStrToAsciiStrS (
3695 IfrNvData
->CHAPSecret
,
3696 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
,
3697 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
)
3701 case KEY_REVERSE_CHAP_NAME
:
3702 UnicodeStrToAsciiStrS (
3703 IfrNvData
->ReverseCHAPName
,
3704 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
,
3705 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
)
3709 case KEY_REVERSE_CHAP_SECRET
:
3710 UnicodeStrToAsciiStrS (
3711 IfrNvData
->ReverseCHAPSecret
,
3712 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
3713 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
)
3717 case KEY_CONFIG_ISID
:
3718 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3719 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3728 if (!EFI_ERROR (Status
)) {
3730 // Pass changed uncommitted data back to Form Browser.
3732 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3733 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3736 FreePool (IfrNvData
);
3737 FreePool (IScsiName
);
3744 Initialize the iSCSI configuration form.
3746 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3748 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
3749 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
3753 IScsiConfigFormInit (
3754 IN EFI_HANDLE DriverBindingHandle
3758 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
3760 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
3761 if (CallbackInfo
== NULL
) {
3762 return EFI_OUT_OF_RESOURCES
;
3765 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
3766 CallbackInfo
->Current
= NULL
;
3768 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
3769 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
3770 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
3773 // Install Device Path Protocol and Config Access protocol to driver handle.
3775 Status
= gBS
->InstallMultipleProtocolInterfaces (
3776 &CallbackInfo
->DriverHandle
,
3777 &gEfiDevicePathProtocolGuid
,
3778 &mIScsiHiiVendorDevicePath
,
3779 &gEfiHiiConfigAccessProtocolGuid
,
3780 &CallbackInfo
->ConfigAccess
,
3783 ASSERT_EFI_ERROR (Status
);
3786 // Publish our HII data.
3788 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
3790 CallbackInfo
->DriverHandle
,
3795 if (CallbackInfo
->RegisteredHandle
== NULL
) {
3796 gBS
->UninstallMultipleProtocolInterfaces (
3797 &CallbackInfo
->DriverHandle
,
3798 &gEfiDevicePathProtocolGuid
,
3799 &mIScsiHiiVendorDevicePath
,
3800 &gEfiHiiConfigAccessProtocolGuid
,
3801 &CallbackInfo
->ConfigAccess
,
3804 FreePool(CallbackInfo
);
3805 return EFI_OUT_OF_RESOURCES
;
3808 mCallbackInfo
= CallbackInfo
;
3815 Unload the iSCSI configuration form, this includes: delete all the iSCSI
3816 configuration entries, uninstall the form callback protocol, and
3817 free the resources used.
3819 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3821 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
3822 @retval Others Failed to unload the form.
3826 IScsiConfigFormUnload (
3827 IN EFI_HANDLE DriverBindingHandle
3830 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3831 ISCSI_NIC_INFO
*NicInfo
;
3835 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
3836 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
3837 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3838 FreePool (AttemptConfigData
);
3839 mPrivate
->AttemptCount
--;
3842 ASSERT (mPrivate
->AttemptCount
== 0);
3844 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
3845 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
3846 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3848 mPrivate
->NicCount
--;
3851 ASSERT (mPrivate
->NicCount
== 0);
3853 FreePool (mPrivate
);
3857 // Remove HII package list.
3859 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
3862 // Uninstall Device Path Protocol and Config Access protocol.
3864 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3865 mCallbackInfo
->DriverHandle
,
3866 &gEfiDevicePathProtocolGuid
,
3867 &mIScsiHiiVendorDevicePath
,
3868 &gEfiHiiConfigAccessProtocolGuid
,
3869 &mCallbackInfo
->ConfigAccess
,
3873 FreePool (mCallbackInfo
);