2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2014, 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 return NetIp4IsUnicast (NTOHL (Ip
->Addr
[0]), 0);
168 } else if (IpMode
== IP_MODE_IP6
) {
169 return NetIp6IsValidUnicast (&Ip
->v6
);
171 DEBUG ((DEBUG_ERROR
, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode
));
177 Parse IsId in string format and convert it to binary.
179 @param[in] String The buffer of the string to be parsed.
180 @param[in, out] IsId The buffer to store IsId.
182 @retval EFI_SUCCESS The operation finished successfully.
183 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
187 IScsiParseIsIdFromString (
188 IN CONST CHAR16
*String
,
196 CHAR16 PortString
[ISCSI_NAME_IFR_MAX_SIZE
];
199 if ((String
== NULL
) || (IsId
== NULL
)) {
200 return EFI_INVALID_PARAMETER
;
203 IsIdStr
= (CHAR16
*) String
;
205 if (StrLen (IsIdStr
) != 6) {
208 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
209 L
"Error! Input is incorrect, please input 6 hex numbers!\n"
213 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
219 return EFI_INVALID_PARAMETER
;
222 for (Index
= 3; Index
< 6; Index
++) {
223 CopyMem (TempStr
, IsIdStr
, sizeof (TempStr
));
227 // Convert the string to IsId. StrHexToUintn stops at the first character
228 // that is not a valid hex character, '\0' here.
230 NodeVal
= StrHexToUintn (TempStr
);
232 IsId
[Index
] = (UINT8
) NodeVal
;
234 IsIdStr
= IsIdStr
+ 2;
241 Convert IsId from binary to string format.
243 @param[out] String The buffer to store the converted string.
244 @param[in] IsId The buffer to store IsId.
246 @retval EFI_SUCCESS The string converted successfully.
247 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
251 IScsiConvertIsIdToString (
259 if ((String
== NULL
) || (IsId
== NULL
)) {
260 return EFI_INVALID_PARAMETER
;
263 for (Index
= 0; Index
< 6; Index
++) {
264 if (IsId
[Index
] <= 0xF) {
265 Number
= UnicodeSPrint (
267 2 * ISID_CONFIGURABLE_STORAGE
,
272 Number
= UnicodeSPrint (
274 2 * ISID_CONFIGURABLE_STORAGE
,
281 String
= String
+ Number
;
290 Get the attempt config data from global structure by the ConfigIndex.
292 @param[in] AttemptConfigIndex The unique index indicates the attempt.
294 @return Pointer to the attempt config data.
295 @retval NULL The attempt configuration data cannot be found.
298 ISCSI_ATTEMPT_CONFIG_NVDATA
*
299 IScsiConfigGetAttemptByConfigIndex (
300 IN UINT8 AttemptConfigIndex
304 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
306 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
307 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
308 if (Attempt
->AttemptConfigIndex
== AttemptConfigIndex
) {
318 Get the existing attempt config data from global structure by the NicIndex.
320 @param[in] NewAttempt The created new attempt
321 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
324 @return Pointer to the existing attempt config data which
325 has the same NICIndex as the new created attempt.
326 @retval NULL The attempt with NicIndex does not exist.
329 ISCSI_ATTEMPT_CONFIG_NVDATA
*
330 IScsiConfigGetAttemptByNic (
331 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*NewAttempt
,
336 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
338 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
339 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
340 if (Attempt
!= NewAttempt
&& Attempt
->NicIndex
== NewAttempt
->NicIndex
&&
341 Attempt
->SessionConfigData
.Enabled
== IScsiMode
) {
351 Convert the iSCSI configuration data into the IFR data.
353 @param[in] Attempt The iSCSI attempt config data.
354 @param[in, out] IfrNvData The IFR nv data.
358 IScsiConvertAttemptConfigDataToIfrNvData (
359 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
,
360 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
363 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
364 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
368 // Normal session configuration parameters.
370 SessionConfigData
= &Attempt
->SessionConfigData
;
371 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
372 IfrNvData
->IpMode
= SessionConfigData
->IpMode
;
374 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
375 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
376 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
378 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
379 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
380 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->LocalIp
);
381 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
382 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->SubnetMask
);
383 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
384 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Gateway
);
385 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
386 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->TargetIp
);
387 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
388 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
389 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
390 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->TargetIp
);
393 AsciiStrToUnicodeStr (SessionConfigData
->TargetName
, IfrNvData
->TargetName
);
394 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
395 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
397 IfrNvData
->ConnectRetryCount
= SessionConfigData
->ConnectRetryCount
;
398 IfrNvData
->ConnectTimeout
= SessionConfigData
->ConnectTimeout
;
401 // Authentication parameters.
403 IfrNvData
->AuthenticationType
= Attempt
->AuthenticationType
;
405 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
406 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
407 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
408 AsciiStrToUnicodeStr (AuthConfigData
->CHAPName
, IfrNvData
->CHAPName
);
409 AsciiStrToUnicodeStr (AuthConfigData
->CHAPSecret
, IfrNvData
->CHAPSecret
);
410 AsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPName
, IfrNvData
->ReverseCHAPName
);
411 AsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPSecret
, IfrNvData
->ReverseCHAPSecret
);
417 AsciiStrToUnicodeStr (Attempt
->AttemptName
, IfrNvData
->AttemptName
);
421 Convert the IFR data to iSCSI configuration data.
423 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
424 @param[in, out] Attempt The iSCSI attempt config data.
426 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
427 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
428 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
429 @retval EFI_ABORTED The operation is aborted.
430 @retval EFI_SUCCESS The operation is completed successfully.
434 IScsiConvertIfrNvDataToAttemptConfigData (
435 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
436 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
439 EFI_IP_ADDRESS HostIp
;
440 EFI_IP_ADDRESS SubnetMask
;
441 EFI_IP_ADDRESS Gateway
;
443 CHAR16
*AttemptName1
;
444 CHAR16
*AttemptName2
;
445 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
446 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
447 CHAR16 IScsiMode
[64];
449 ISCSI_NIC_INFO
*NicInfo
;
451 UINT8
*AttemptConfigOrder
;
452 UINTN AttemptConfigOrderSize
;
453 UINT8
*AttemptOrderTmp
;
457 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
458 return EFI_INVALID_PARAMETER
;
462 // Update those fields which don't have INTERACTIVE attribute.
464 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
465 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
466 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
468 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
469 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
470 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
472 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
473 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
476 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
479 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
481 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
482 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
486 // Only do full parameter validation if iSCSI is enabled on this device.
488 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
489 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
491 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
493 L
"Connection Establishing Timeout is less than minimum value 100ms.",
497 return EFI_INVALID_PARAMETER
;
501 // Validate the address configuration of the Initiator if DHCP isn't
504 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
505 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
506 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
507 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
509 if ((Gateway
.Addr
[0] != 0)) {
510 if (SubnetMask
.Addr
[0] == 0) {
512 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
514 L
"Gateway address is set but subnet mask is zero.",
518 return EFI_INVALID_PARAMETER
;
519 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
521 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
523 L
"Local IP and Gateway are not in the same subnet.",
527 return EFI_INVALID_PARAMETER
;
532 // Validate target configuration if DHCP isn't deployed.
534 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
535 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
537 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
539 L
"Target IP is invalid!",
542 return EFI_INVALID_PARAMETER
;
546 // Validate iSCSI target name configuration again:
547 // The format of iSCSI target name is already verified in IScsiFormCallback() when
548 // user input the name; here we only check the case user does not input the name.
550 if (Attempt
->SessionConfigData
.TargetName
[0] == '\0') {
552 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
554 L
"iSCSI target name is NULL!",
557 return EFI_INVALID_PARAMETER
;
563 // Validate the authentication info.
565 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
566 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
568 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
570 L
"CHAP Name or CHAP Secret is invalid!",
574 return EFI_INVALID_PARAMETER
;
577 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
578 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
581 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
583 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
586 return EFI_INVALID_PARAMETER
;
591 // Check whether this attempt uses NIC which is already used by existing attempt.
593 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
594 if (SameNicAttempt
!= NULL
) {
595 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
596 if (AttemptName1
== NULL
) {
597 return EFI_OUT_OF_RESOURCES
;
600 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
601 if (AttemptName2
== NULL
) {
602 FreePool (AttemptName1
);
603 return EFI_OUT_OF_RESOURCES
;
606 AsciiStrToUnicodeStr (Attempt
->AttemptName
, AttemptName1
);
607 if (StrLen (AttemptName1
) > ATTEMPT_NAME_SIZE
) {
608 CopyMem (&AttemptName1
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
611 AsciiStrToUnicodeStr (SameNicAttempt
->AttemptName
, AttemptName2
);
612 if (StrLen (AttemptName2
) > ATTEMPT_NAME_SIZE
) {
613 CopyMem (&AttemptName2
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
617 mPrivate
->PortString
,
618 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
619 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
625 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
627 mPrivate
->PortString
,
631 FreePool (AttemptName1
);
632 FreePool (AttemptName2
);
637 // Update the iSCSI Mode data and record it in attempt help info.
639 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
640 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
641 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
642 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
643 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
644 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
645 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
648 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
649 UnicodeSPrint (IpMode
, 64, L
"IP4");
650 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
651 UnicodeSPrint (IpMode
, 64, L
"IP6");
652 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
653 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
656 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
657 if (NicInfo
== NULL
) {
658 return EFI_NOT_FOUND
;
661 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
662 if (MacString
== NULL
) {
663 return EFI_OUT_OF_RESOURCES
;
666 AsciiStrToUnicodeStr (Attempt
->MacString
, MacString
);
669 mPrivate
->PortString
,
670 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
671 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
674 NicInfo
->DeviceNumber
,
675 NicInfo
->FunctionNumber
,
680 Attempt
->AttemptTitleHelpToken
= HiiSetString (
681 mCallbackInfo
->RegisteredHandle
,
682 Attempt
->AttemptTitleHelpToken
,
683 mPrivate
->PortString
,
686 if (Attempt
->AttemptTitleHelpToken
== 0) {
687 FreePool (MacString
);
688 return EFI_OUT_OF_RESOURCES
;
692 // Check whether this attempt is an existing one.
694 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
695 if (ExistAttempt
!= NULL
) {
696 ASSERT (ExistAttempt
== Attempt
);
698 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
699 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
702 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
704 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
705 if (mPrivate
->MpioCount
< 1) {
709 if (--mPrivate
->MpioCount
== 0) {
710 mPrivate
->EnableMpio
= FALSE
;
712 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
713 if (mPrivate
->SinglePathCount
< 1) {
716 mPrivate
->SinglePathCount
--;
719 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
720 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
722 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
724 if (mPrivate
->SinglePathCount
< 1) {
728 mPrivate
->EnableMpio
= TRUE
;
729 mPrivate
->MpioCount
++;
730 mPrivate
->SinglePathCount
--;
732 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
733 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
735 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
737 if (mPrivate
->MpioCount
< 1) {
741 if (--mPrivate
->MpioCount
== 0) {
742 mPrivate
->EnableMpio
= FALSE
;
744 mPrivate
->SinglePathCount
++;
746 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
747 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
749 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
751 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
752 mPrivate
->EnableMpio
= TRUE
;
753 mPrivate
->MpioCount
++;
755 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
756 mPrivate
->SinglePathCount
++;
760 } else if (ExistAttempt
== NULL
) {
762 // When a new attempt is created, pointer of the attempt is saved to
763 // mPrivate->NewAttempt, and also saved to mCallbackInfo->Current in
764 // IScsiConfigProcessDefault. If input Attempt does not match any existing
765 // attempt, it should be a new created attempt. Save it to system now.
767 ASSERT (Attempt
== mPrivate
->NewAttempt
);
770 // Save current order number for this attempt.
772 AttemptConfigOrder
= IScsiGetVariableAndSize (
775 &AttemptConfigOrderSize
778 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
782 // Append the new created attempt order to the end.
784 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
785 if (AttemptOrderTmp
== NULL
) {
786 if (AttemptConfigOrder
!= NULL
) {
787 FreePool (AttemptConfigOrder
);
789 return EFI_OUT_OF_RESOURCES
;
792 if (AttemptConfigOrder
!= NULL
) {
793 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
794 FreePool (AttemptConfigOrder
);
797 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
798 AttemptConfigOrder
= AttemptOrderTmp
;
799 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
801 Status
= gRT
->SetVariable (
804 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
805 AttemptConfigOrderSize
,
808 FreePool (AttemptConfigOrder
);
809 if (EFI_ERROR (Status
)) {
814 // Insert new created attempt to array.
816 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
817 mPrivate
->AttemptCount
++;
819 // Reset mPrivate->NewAttempt to NULL, which indicates none attempt is created
820 // but not saved now.
822 mPrivate
->NewAttempt
= NULL
;
824 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
826 // This new Attempt is enabled for MPIO; enable the multipath mode.
828 mPrivate
->EnableMpio
= TRUE
;
829 mPrivate
->MpioCount
++;
830 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
831 mPrivate
->SinglePathCount
++;
834 IScsiConfigUpdateAttempt ();
838 // Record the user configuration information in NVR.
841 mPrivate
->PortString
,
842 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
845 (UINTN
) Attempt
->AttemptConfigIndex
848 FreePool (MacString
);
850 return gRT
->SetVariable (
851 mPrivate
->PortString
,
852 &gEfiIScsiInitiatorNameProtocolGuid
,
853 ISCSI_CONFIG_VAR_ATTR
,
854 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
860 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
863 @param[in] StartLabelNumber The number of start label.
864 @param[out] StartOpCodeHandle Points to the start opcode handle.
865 @param[out] StartLabel Points to the created start opcode.
866 @param[out] EndOpCodeHandle Points to the end opcode handle.
867 @param[out] EndLabel Points to the created end opcode.
869 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
871 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
872 @retval EFI_SUCCESS The operation is completed successfully.
877 IN UINT16 StartLabelNumber
,
878 OUT VOID
**StartOpCodeHandle
,
879 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
880 OUT VOID
**EndOpCodeHandle
,
881 OUT EFI_IFR_GUID_LABEL
**EndLabel
885 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
886 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
888 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
889 return EFI_INVALID_PARAMETER
;
892 *StartOpCodeHandle
= NULL
;
893 *EndOpCodeHandle
= NULL
;
894 Status
= EFI_OUT_OF_RESOURCES
;
897 // Initialize the container for dynamic opcodes.
899 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
900 if (*StartOpCodeHandle
== NULL
) {
904 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
905 if (*EndOpCodeHandle
== NULL
) {
910 // Create Hii Extend Label OpCode as the start opcode.
912 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
916 sizeof (EFI_IFR_GUID_LABEL
)
918 if (InternalStartLabel
== NULL
) {
922 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
923 InternalStartLabel
->Number
= StartLabelNumber
;
926 // Create Hii Extend Label OpCode as the end opcode.
928 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
932 sizeof (EFI_IFR_GUID_LABEL
)
934 if (InternalEndLabel
== NULL
) {
938 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
939 InternalEndLabel
->Number
= LABEL_END
;
941 *StartLabel
= InternalStartLabel
;
942 *EndLabel
= InternalEndLabel
;
948 if (*StartOpCodeHandle
!= NULL
) {
949 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
952 if (*EndOpCodeHandle
!= NULL
) {
953 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
960 Callback function when user presses "Add an Attempt".
962 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
964 @retval EFI_SUCCESS The operation is completed successfully.
968 IScsiConfigAddAttempt (
973 ISCSI_NIC_INFO
*NicInfo
;
974 EFI_STRING_ID PortTitleToken
;
975 EFI_STRING_ID PortTitleHelpToken
;
976 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
978 VOID
*StartOpCodeHandle
;
979 EFI_IFR_GUID_LABEL
*StartLabel
;
980 VOID
*EndOpCodeHandle
;
981 EFI_IFR_GUID_LABEL
*EndLabel
;
983 Status
= IScsiCreateOpCode (
990 if (EFI_ERROR (Status
)) {
995 // Ask user to select a MAC for this attempt.
997 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
998 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
1000 &NicInfo
->PermanentAddress
,
1001 NicInfo
->HwAddressSize
,
1006 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
1007 PortTitleToken
= HiiSetString (
1008 mCallbackInfo
->RegisteredHandle
,
1010 mPrivate
->PortString
,
1013 if (PortTitleToken
== 0) {
1014 Status
= EFI_INVALID_PARAMETER
;
1019 mPrivate
->PortString
,
1020 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1021 L
"PFA: Bus %d | Dev %d | Func %d",
1023 NicInfo
->DeviceNumber
,
1024 NicInfo
->FunctionNumber
1026 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
1027 if (PortTitleHelpToken
== 0) {
1028 Status
= EFI_INVALID_PARAMETER
;
1032 HiiCreateGotoOpCode (
1033 StartOpCodeHandle
, // Container for dynamic created opcodes
1034 FORMID_ATTEMPT_FORM
,
1037 EFI_IFR_FLAG_CALLBACK
, // Question flag
1038 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
1042 Status
= HiiUpdateForm (
1043 mCallbackInfo
->RegisteredHandle
, // HII handle
1044 &gIScsiConfigGuid
, // Formset GUID
1045 FORMID_MAC_FORM
, // Form ID
1046 StartOpCodeHandle
, // Label for where to insert opcodes
1047 EndOpCodeHandle
// Replace data
1051 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1052 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1059 Update the MAIN form to display the configured attempts.
1063 IScsiConfigUpdateAttempt (
1067 CHAR16 AttemptName
[ATTEMPT_NAME_MAX_SIZE
];
1069 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1070 VOID
*StartOpCodeHandle
;
1071 EFI_IFR_GUID_LABEL
*StartLabel
;
1072 VOID
*EndOpCodeHandle
;
1073 EFI_IFR_GUID_LABEL
*EndLabel
;
1076 Status
= IScsiCreateOpCode (
1077 ATTEMPT_ENTRY_LABEL
,
1083 if (EFI_ERROR (Status
)) {
1087 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1088 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1090 AsciiStrToUnicodeStr (AttemptConfigData
->AttemptName
, AttemptName
);
1091 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) 128, L
"Attempt %s", AttemptName
);
1092 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1093 mCallbackInfo
->RegisteredHandle
,
1095 mPrivate
->PortString
,
1098 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1102 HiiCreateGotoOpCode (
1103 StartOpCodeHandle
, // Container for dynamic created opcodes
1104 FORMID_ATTEMPT_FORM
, // Form ID
1105 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1106 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1107 EFI_IFR_FLAG_CALLBACK
, // Question flag
1108 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1113 mCallbackInfo
->RegisteredHandle
, // HII handle
1114 &gIScsiConfigGuid
, // Formset GUID
1115 FORMID_MAIN_FORM
, // Form ID
1116 StartOpCodeHandle
, // Label for where to insert opcodes
1117 EndOpCodeHandle
// Replace data
1120 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1121 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1126 Callback function when user presses "Commit Changes and Exit" in Delete Attempts.
1128 @param[in] IfrNvData The IFR NV data.
1130 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1131 @retval EFI_SUCCESS The operation is completed successfully.
1132 @retval EFI_ABOTRED This operation is aborted cause of error
1134 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
1139 IScsiConfigDeleteAttempts (
1140 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1146 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1147 UINT8
*AttemptConfigOrder
;
1148 UINTN AttemptConfigOrderSize
;
1149 UINT8
*AttemptNewOrder
;
1154 LIST_ENTRY
*NextEntry
;
1155 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1157 AttemptConfigOrder
= IScsiGetVariableAndSize (
1160 &AttemptConfigOrderSize
1162 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
1163 return EFI_NOT_FOUND
;
1166 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
1167 if (AttemptNewOrder
== NULL
) {
1168 Status
= EFI_OUT_OF_RESOURCES
;
1172 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1176 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
1177 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
1183 // Delete the attempt.
1186 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1187 if (AttemptConfigData
== NULL
) {
1188 Status
= EFI_NOT_FOUND
;
1193 // Remove this attempt from UI configured attempt list.
1195 RemoveEntryList (&AttemptConfigData
->Link
);
1196 mPrivate
->AttemptCount
--;
1198 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1199 if (mPrivate
->MpioCount
< 1) {
1200 Status
= EFI_ABORTED
;
1205 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
1207 if (--mPrivate
->MpioCount
== 0) {
1208 mPrivate
->EnableMpio
= FALSE
;
1210 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1211 if (mPrivate
->SinglePathCount
< 1) {
1212 Status
= EFI_ABORTED
;
1216 mPrivate
->SinglePathCount
--;
1219 AsciiStrToUnicodeStr (AttemptConfigData
->MacString
, MacString
);
1222 mPrivate
->PortString
,
1226 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1230 mPrivate
->PortString
,
1231 &gEfiIScsiInitiatorNameProtocolGuid
,
1238 // Mark the attempt order in NVR to be deleted - 0.
1240 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
1241 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
1242 AttemptConfigOrder
[NewIndex
] = 0;
1248 FreePool (AttemptConfigData
);
1251 // Check next Attempt.
1257 // Construct AttemptNewOrder.
1259 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
1260 if (AttemptConfigOrder
[Index
] != 0) {
1261 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
1266 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
1269 // Update AttemptOrder in NVR.
1271 Status
= gRT
->SetVariable (
1275 NewTotal
* sizeof (UINT8
),
1280 if (AttemptConfigOrder
!= NULL
) {
1281 FreePool (AttemptConfigOrder
);
1284 if (AttemptNewOrder
!= NULL
) {
1285 FreePool (AttemptNewOrder
);
1293 Callback function when user presses "Delete Attempts".
1295 @param[in] IfrNvData The IFR nv data.
1297 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1298 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
1299 @retval EFI_SUCCESS The operation is completed successfully.
1303 IScsiConfigDisplayDeleteAttempts (
1304 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1308 UINT8
*AttemptConfigOrder
;
1309 UINTN AttemptConfigOrderSize
;
1311 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1313 VOID
*StartOpCodeHandle
;
1314 EFI_IFR_GUID_LABEL
*StartLabel
;
1315 VOID
*EndOpCodeHandle
;
1316 EFI_IFR_GUID_LABEL
*EndLabel
;
1319 Status
= IScsiCreateOpCode (
1326 if (EFI_ERROR (Status
)) {
1330 AttemptConfigOrder
= IScsiGetVariableAndSize (
1333 &AttemptConfigOrderSize
1335 if (AttemptConfigOrder
!= NULL
) {
1337 // Create the check box opcode to be deleted.
1341 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1342 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1343 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
1345 HiiCreateCheckBoxOpCode(
1347 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
1348 CONFIGURATION_VARSTORE_ID
,
1349 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
1350 AttemptConfigData
->AttemptTitleToken
,
1351 AttemptConfigData
->AttemptTitleHelpToken
,
1359 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
1364 FreePool (AttemptConfigOrder
);
1367 Status
= HiiUpdateForm (
1368 mCallbackInfo
->RegisteredHandle
, // HII handle
1369 &gIScsiConfigGuid
, // Formset GUID
1370 FORMID_DELETE_FORM
, // Form ID
1371 StartOpCodeHandle
, // Label for where to insert opcodes
1372 EndOpCodeHandle
// Replace data
1375 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1376 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1383 Callback function when user presses "Change Attempt Order".
1385 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1386 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1388 @retval EFI_SUCCESS The operation is completed successfully.
1392 IScsiConfigDisplayOrderAttempts (
1399 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1400 VOID
*StartOpCodeHandle
;
1401 EFI_IFR_GUID_LABEL
*StartLabel
;
1402 VOID
*EndOpCodeHandle
;
1403 EFI_IFR_GUID_LABEL
*EndLabel
;
1404 VOID
*OptionsOpCodeHandle
;
1406 Status
= IScsiCreateOpCode (
1413 if (EFI_ERROR (Status
)) {
1416 ASSERT (StartOpCodeHandle
!= NULL
);
1418 OptionsOpCodeHandle
= NULL
;
1421 // If no attempt to be ordered, update the original form and exit.
1423 if (mPrivate
->AttemptCount
== 0) {
1428 // Create Option OpCode.
1430 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
1431 if (OptionsOpCodeHandle
== NULL
) {
1432 Status
= EFI_OUT_OF_RESOURCES
;
1438 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1439 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1440 HiiCreateOneOfOptionOpCode (
1441 OptionsOpCodeHandle
,
1442 AttemptConfigData
->AttemptTitleToken
,
1444 EFI_IFR_NUMERIC_SIZE_1
,
1445 AttemptConfigData
->AttemptConfigIndex
1450 ASSERT (Index
== mPrivate
->AttemptCount
);
1452 HiiCreateOrderedListOpCode (
1453 StartOpCodeHandle
, // Container for dynamic created opcodes
1454 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
1455 CONFIGURATION_VARSTORE_ID
, // VarStore ID
1456 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
1457 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
1458 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
1460 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1461 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
1462 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
1463 OptionsOpCodeHandle
, // Option Opcode list
1464 NULL
// Default Opcode is NULL
1468 Status
= HiiUpdateForm (
1469 mCallbackInfo
->RegisteredHandle
, // HII handle
1470 &gIScsiConfigGuid
, // Formset GUID
1471 FORMID_ORDER_FORM
, // Form ID
1472 StartOpCodeHandle
, // Label for where to insert opcodes
1473 EndOpCodeHandle
// Replace data
1477 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1478 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1479 if (OptionsOpCodeHandle
!= NULL
) {
1480 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
1488 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order.
1490 @param[in] IfrNvData The IFR nv data.
1492 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1494 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1495 @retval EFI_SUCCESS The operation is completed successfully.
1499 IScsiConfigOrderAttempts (
1500 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1506 UINT8 AttemptConfigIndex
;
1507 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1508 UINT8
*AttemptConfigOrder
;
1509 UINT8
*AttemptConfigOrderTmp
;
1510 UINTN AttemptConfigOrderSize
;
1512 AttemptConfigOrder
= IScsiGetVariableAndSize (
1515 &AttemptConfigOrderSize
1517 if (AttemptConfigOrder
== NULL
) {
1518 return EFI_NOT_FOUND
;
1521 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
1522 if (AttemptConfigOrderTmp
== NULL
) {
1523 Status
= EFI_OUT_OF_RESOURCES
;
1527 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
1529 // The real content ends with 0.
1531 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
1535 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
1536 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
1537 if (AttemptConfigData
== NULL
) {
1538 Status
= EFI_NOT_FOUND
;
1543 // Reorder the Attempt List.
1545 RemoveEntryList (&AttemptConfigData
->Link
);
1546 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
1548 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
1551 // Mark it to be deleted - 0.
1553 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1554 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
1555 AttemptConfigOrder
[Indexj
] = 0;
1562 // Adjust the attempt order in NVR.
1564 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
1565 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1566 if (AttemptConfigOrder
[Indexj
] != 0) {
1567 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
1568 AttemptConfigOrder
[Indexj
] = 0;
1574 Status
= gRT
->SetVariable (
1577 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1578 AttemptConfigOrderSize
,
1579 AttemptConfigOrderTmp
1583 if (AttemptConfigOrderTmp
!= NULL
) {
1584 FreePool (AttemptConfigOrderTmp
);
1587 FreePool (AttemptConfigOrder
);
1593 Callback function when a user presses "Attempt *" or when a user selects a NIC to
1594 create the new attempt.
1596 @param[in] KeyValue A unique value which is sent to the original
1597 exporting driver so that it can identify the type
1599 @param[in] IfrNvData The IFR nv data.
1601 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1603 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1604 @retval EFI_SUCCESS The operation is completed successfully.
1608 IScsiConfigProcessDefault (
1609 IN EFI_QUESTION_ID KeyValue
,
1610 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1614 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1615 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
1616 UINT8 CurrentAttemptConfigIndex
;
1617 ISCSI_NIC_INFO
*NicInfo
;
1619 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1620 UINT8
*AttemptConfigOrder
;
1621 UINTN AttemptConfigOrderSize
;
1626 // Is User creating a new attempt?
1630 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
1631 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
1633 // User has pressed "Add an Attempt" and then selects a NIC.
1636 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
1637 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
1640 // User has pressed "Attempt *".
1645 // Don't process anything.
1651 // Free any attempt that is previously created but not saved to system.
1653 if (mPrivate
->NewAttempt
!= NULL
) {
1654 FreePool (mPrivate
->NewAttempt
);
1655 mPrivate
->NewAttempt
= NULL
;
1660 // Determine which NIC user has selected for the new created attempt.
1662 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
1663 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
1664 if (NicInfo
== NULL
) {
1665 return EFI_NOT_FOUND
;
1669 // Create new attempt.
1672 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
1673 if (AttemptConfigData
== NULL
) {
1674 return EFI_OUT_OF_RESOURCES
;
1677 ConfigData
= &AttemptConfigData
->SessionConfigData
;
1678 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1679 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1680 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
1682 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
1683 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
1686 // Get current order number for this attempt.
1688 AttemptConfigOrder
= IScsiGetVariableAndSize (
1691 &AttemptConfigOrderSize
1694 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1696 if (AttemptConfigOrder
== NULL
) {
1697 CurrentAttemptConfigIndex
= 1;
1700 // Get the max attempt config index.
1702 CurrentAttemptConfigIndex
= AttemptConfigOrder
[0];
1703 for (Index
= 1; Index
< TotalNumber
; Index
++) {
1704 if (CurrentAttemptConfigIndex
< AttemptConfigOrder
[Index
]) {
1705 CurrentAttemptConfigIndex
= AttemptConfigOrder
[Index
];
1709 CurrentAttemptConfigIndex
++;
1715 // Record the mapping between attempt order and attempt's configdata.
1717 AttemptConfigData
->AttemptConfigIndex
= CurrentAttemptConfigIndex
;
1719 if (AttemptConfigOrder
!= NULL
) {
1720 FreePool (AttemptConfigOrder
);
1724 // Record the MAC info in Config Data.
1727 &NicInfo
->PermanentAddress
,
1728 NicInfo
->HwAddressSize
,
1733 UnicodeStrToAsciiStr (MacString
, AttemptConfigData
->MacString
);
1734 AttemptConfigData
->NicIndex
= NicIndex
;
1737 // Generate OUI-format ISID based on MAC address.
1739 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
1740 AttemptConfigData
->SessionConfigData
.IsId
[0] =
1741 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
1744 // Add the help info for the new attempt.
1747 mPrivate
->PortString
,
1748 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1749 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
1752 NicInfo
->DeviceNumber
,
1753 NicInfo
->FunctionNumber
1756 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
1757 mCallbackInfo
->RegisteredHandle
,
1759 mPrivate
->PortString
,
1762 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
1763 FreePool (AttemptConfigData
);
1764 return EFI_INVALID_PARAMETER
;
1768 // Set the attempt name to default.
1771 mPrivate
->PortString
,
1774 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1776 UnicodeStrToAsciiStr (mPrivate
->PortString
, AttemptConfigData
->AttemptName
);
1779 // Save the created Attempt temporarily. If user does not save the attempt
1780 // by press 'KEY_SAVE_ATTEMPT_CONFIG' later, iSCSI driver would know that
1781 // and free resources.
1783 mPrivate
->NewAttempt
= (VOID
*) AttemptConfigData
;
1787 // Determine which Attempt user has selected to configure.
1788 // Get the attempt configuration data.
1790 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
1792 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
1793 if (AttemptConfigData
== NULL
) {
1794 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
1795 return EFI_NOT_FOUND
;
1800 // Clear the old IFR data to avoid sharing it with other attempts.
1802 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1803 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
1804 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
1805 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
1806 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
1809 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
1812 // Update current attempt to be a new created attempt or an existing attempt.
1814 mCallbackInfo
->Current
= AttemptConfigData
;
1822 This function allows the caller to request the current
1823 configuration for one or more named elements. The resulting
1824 string is in <ConfigAltResp> format. Also, any and all alternative
1825 configuration strings shall be appended to the end of the
1826 current configuration string. If they are, they must appear
1827 after the current configuration. They must contain the same
1828 routing (GUID, NAME, PATH) as the current configuration string.
1829 They must have an additional description indicating the type of
1830 alternative configuration the string represents,
1831 "ALTCFG=<StringToken>". That <StringToken> (when
1832 converted from Hex UNICODE to binary) is a reference to a
1833 string in the associated string pack.
1835 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1837 @param[in] Request A null-terminated Unicode string in
1838 <ConfigRequest> format. Note that this
1839 includes the routing information as well as
1840 the configurable name / value pairs. It is
1841 invalid for this string to be in
1842 <MultiConfigRequest> format.
1844 @param[out] Progress On return, points to a character in the
1845 Request string. Points to the string's null
1846 terminator if request was successful. Points
1847 to the most recent "&" before the first
1848 failing name / value pair (or the beginning
1849 of the string if the failure is in the first
1850 name / value pair) if the request was not successful.
1852 @param[out] Results A null-terminated Unicode string in
1853 <ConfigAltResp> format which has all values
1854 filled in for the names in the Request string.
1855 String to be allocated by the called function.
1857 @retval EFI_SUCCESS The Results string is filled with the
1858 values corresponding to all requested
1861 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1862 parts of the results that must be
1863 stored awaiting possible future
1866 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
1867 for the Request parameter
1868 would result in this type of
1869 error. In this case, the
1870 Progress parameter would be
1873 @retval EFI_NOT_FOUND Routing data doesn't match any
1874 known driver. Progress set to the
1875 first character in the routing header.
1876 Note: There is no requirement that the
1877 driver validate the routing data. It
1878 must skip the <ConfigHdr> in order to
1881 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
1882 to most recent "&" before the
1883 error or the beginning of the
1886 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
1887 to the & before the name in
1893 IScsiFormExtractConfig (
1894 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1895 IN CONST EFI_STRING Request
,
1896 OUT EFI_STRING
*Progress
,
1897 OUT EFI_STRING
*Results
1901 CHAR8
*InitiatorName
;
1903 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
1904 ISCSI_FORM_CALLBACK_INFO
*Private
;
1905 EFI_STRING ConfigRequestHdr
;
1906 EFI_STRING ConfigRequest
;
1907 BOOLEAN AllocatedRequest
;
1910 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
1911 return EFI_INVALID_PARAMETER
;
1914 *Progress
= Request
;
1915 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
1916 return EFI_NOT_FOUND
;
1919 ConfigRequestHdr
= NULL
;
1920 ConfigRequest
= NULL
;
1921 AllocatedRequest
= FALSE
;
1924 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
1925 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
1926 if (IfrNvData
== NULL
) {
1927 return EFI_OUT_OF_RESOURCES
;
1930 if (Private
->Current
!= NULL
) {
1931 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
1934 BufferSize
= ISCSI_NAME_MAX_SIZE
;
1935 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
1936 if (InitiatorName
== NULL
) {
1937 FreePool (IfrNvData
);
1938 return EFI_OUT_OF_RESOURCES
;
1941 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
1942 if (EFI_ERROR (Status
)) {
1943 IfrNvData
->InitiatorName
[0] = L
'\0';
1945 AsciiStrToUnicodeStr (InitiatorName
, IfrNvData
->InitiatorName
);
1949 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
1951 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
1952 ConfigRequest
= Request
;
1953 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
1955 // Request has no request element, construct full request string.
1956 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1957 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
1959 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
1960 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
1961 ConfigRequest
= AllocateZeroPool (Size
);
1962 ASSERT (ConfigRequest
!= NULL
);
1963 AllocatedRequest
= TRUE
;
1964 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
1965 FreePool (ConfigRequestHdr
);
1968 Status
= gHiiConfigRouting
->BlockToConfig (
1971 (UINT8
*) IfrNvData
,
1976 FreePool (IfrNvData
);
1977 FreePool (InitiatorName
);
1980 // Free the allocated config request string.
1982 if (AllocatedRequest
) {
1983 FreePool (ConfigRequest
);
1984 ConfigRequest
= NULL
;
1987 // Set Progress string to the original request string.
1989 if (Request
== NULL
) {
1991 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
1992 *Progress
= Request
+ StrLen (Request
);
2001 This function applies changes in a driver's configuration.
2002 Input is a Configuration, which has the routing data for this
2003 driver followed by name / value configuration pairs. The driver
2004 must apply those pairs to its configurable storage. If the
2005 driver's configuration is stored in a linear block of data
2006 and the driver's name / value pairs are in <BlockConfig>
2007 format, it may use the ConfigToBlock helper function (above) to
2010 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2012 @param[in] Configuration A null-terminated Unicode string in
2013 <ConfigString> format.
2015 @param[out] Progress A pointer to a string filled in with the
2016 offset of the most recent '&' before the
2017 first failing name / value pair (or the
2018 beginning of the string if the failure
2019 is in the first name / value pair) or
2020 the terminating NULL if all was
2023 @retval EFI_SUCCESS The results have been distributed or are
2024 awaiting distribution.
2026 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2027 parts of the results that must be
2028 stored awaiting possible future
2031 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
2032 Results parameter would result
2033 in this type of error.
2035 @retval EFI_NOT_FOUND Target for the specified routing data
2041 IScsiFormRouteConfig (
2042 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2043 IN CONST EFI_STRING Configuration
,
2044 OUT EFI_STRING
*Progress
2047 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
2048 return EFI_INVALID_PARAMETER
;
2052 // Check routing data in <ConfigHdr>.
2053 // Note: if only one Storage is used, then this checking could be skipped.
2055 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
2056 *Progress
= Configuration
;
2057 return EFI_NOT_FOUND
;
2060 *Progress
= Configuration
+ StrLen (Configuration
);
2067 This function is called to provide results data to the driver.
2068 This data consists of a unique key that is used to identify
2069 which data is either being passed back or being asked for.
2071 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2072 @param[in] Action Specifies the type of action taken by the browser.
2073 @param[in] QuestionId A unique value which is sent to the original
2074 exporting driver so that it can identify the type
2075 of data to expect. The format of the data tends to
2076 vary based on the opcode that generated the callback.
2077 @param[in] Type The type of value for the question.
2078 @param[in, out] Value A pointer to the data being sent to the original
2080 @param[out] ActionRequest On return, points to the action requested by the
2083 @retval EFI_SUCCESS The callback successfully handled the action.
2084 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2085 variable and its data.
2086 @retval EFI_DEVICE_ERROR The variable could not be saved.
2087 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2093 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2094 IN EFI_BROWSER_ACTION Action
,
2095 IN EFI_QUESTION_ID QuestionId
,
2097 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
2098 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2101 ISCSI_FORM_CALLBACK_INFO
*Private
;
2104 CHAR8 IpString
[IP_STR_MAX_SIZE
];
2105 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
2107 EFI_IP_ADDRESS HostIp
;
2108 EFI_IP_ADDRESS SubnetMask
;
2109 EFI_IP_ADDRESS Gateway
;
2110 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
2111 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
2113 CHAR16 AttemptName
[ATTEMPT_NAME_SIZE
+ 4];
2116 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
2118 // Do nothing for UEFI OPEN/CLOSE Action
2123 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
2125 // All other type return unsupported.
2127 return EFI_UNSUPPORTED
;
2130 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
2131 return EFI_INVALID_PARAMETER
;
2134 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
2137 // Retrieve uncommitted data from Browser
2140 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2141 IfrNvData
= AllocateZeroPool (BufferSize
);
2142 if (IfrNvData
== NULL
) {
2143 return EFI_OUT_OF_RESOURCES
;
2146 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
2147 if (IScsiName
== NULL
) {
2148 FreePool (IfrNvData
);
2149 return EFI_OUT_OF_RESOURCES
;
2152 Status
= EFI_SUCCESS
;
2154 ZeroMem (&OldIfrNvData
, BufferSize
);
2156 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2158 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
2160 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2161 switch (QuestionId
) {
2162 case KEY_ADD_ATTEMPT
:
2163 Status
= IScsiConfigAddAttempt ();
2166 case KEY_DELETE_ATTEMPT
:
2168 OldIfrNvData
.DeleteAttemptList
,
2169 IfrNvData
->DeleteAttemptList
,
2170 sizeof (IfrNvData
->DeleteAttemptList
)
2172 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
2175 case KEY_ORDER_ATTEMPT_CONFIG
:
2177 // Order the attempt according to user input.
2180 OldIfrNvData
.DynamicOrderedList
,
2181 IfrNvData
->DynamicOrderedList
,
2182 sizeof (IfrNvData
->DynamicOrderedList
)
2184 IScsiConfigDisplayOrderAttempts ();
2188 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
2191 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2192 switch (QuestionId
) {
2193 case KEY_INITIATOR_NAME
:
2194 UnicodeStrToAsciiStr (IfrNvData
->InitiatorName
, IScsiName
);
2195 BufferSize
= AsciiStrSize (IScsiName
);
2197 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
2198 if (EFI_ERROR (Status
)) {
2200 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2202 L
"Invalid iSCSI Name!",
2207 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2209 case KEY_ATTEMPT_NAME
:
2210 if (StrLen (IfrNvData
->AttemptName
) > ATTEMPT_NAME_SIZE
) {
2211 CopyMem (AttemptName
, IfrNvData
->AttemptName
, ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
2212 CopyMem (&AttemptName
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
2216 IfrNvData
->AttemptName
,
2217 (StrLen (IfrNvData
->AttemptName
) + 1) * sizeof (CHAR16
)
2221 UnicodeStrToAsciiStr (IfrNvData
->AttemptName
, Private
->Current
->AttemptName
);
2223 IScsiConfigUpdateAttempt ();
2225 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2228 case KEY_SAVE_ATTEMPT_CONFIG
:
2229 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
2230 if (EFI_ERROR (Status
)) {
2234 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2237 case KEY_SAVE_ORDER_CHANGES
:
2239 // Sync the Attempt Order to NVR.
2241 Status
= IScsiConfigOrderAttempts (IfrNvData
);
2242 if (EFI_ERROR (Status
)) {
2246 IScsiConfigUpdateAttempt ();
2247 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
2250 case KEY_IGNORE_ORDER_CHANGES
:
2252 IfrNvData
->DynamicOrderedList
,
2253 OldIfrNvData
.DynamicOrderedList
,
2254 sizeof (IfrNvData
->DynamicOrderedList
)
2256 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
2259 case KEY_SAVE_DELETE_ATTEMPT
:
2261 // Delete the Attempt Order from NVR
2263 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
2264 if (EFI_ERROR (Status
)) {
2268 IScsiConfigUpdateAttempt ();
2269 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
2272 case KEY_IGNORE_DELETE_ATTEMPT
:
2274 IfrNvData
->DeleteAttemptList
,
2275 OldIfrNvData
.DeleteAttemptList
,
2276 sizeof (IfrNvData
->DeleteAttemptList
)
2278 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
2282 switch (Value
->u8
) {
2284 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2285 IScsiIpToStr (&Private
->Current
->SessionConfigData
.TargetIp
, TRUE
, IfrNvData
->TargetIp
);
2286 Private
->Current
->AutoConfigureMode
= 0;
2290 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2291 IScsiIpToStr (&Private
->Current
->SessionConfigData
.TargetIp
, FALSE
, IfrNvData
->TargetIp
);
2292 Private
->Current
->AutoConfigureMode
= 0;
2300 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
2301 if (EFI_ERROR (Status
) || !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
2303 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2305 L
"Invalid IP address!",
2309 Status
= EFI_INVALID_PARAMETER
;
2311 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
2316 case KEY_SUBNET_MASK
:
2317 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
2318 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
2320 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2322 L
"Invalid Subnet Mask!",
2326 Status
= EFI_INVALID_PARAMETER
;
2328 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
2334 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
2335 if (EFI_ERROR (Status
) || ((Gateway
.Addr
[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), 0))) {
2337 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2339 L
"Invalid Gateway!",
2342 Status
= EFI_INVALID_PARAMETER
;
2344 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
2350 UnicodeStrToAsciiStr (IfrNvData
->TargetIp
, IpString
);
2351 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
2352 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
2354 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2356 L
"Invalid IP address!",
2359 Status
= EFI_INVALID_PARAMETER
;
2361 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
2366 case KEY_TARGET_NAME
:
2367 UnicodeStrToAsciiStr (IfrNvData
->TargetName
, IScsiName
);
2368 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
2369 if (EFI_ERROR (Status
)) {
2371 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2373 L
"Invalid iSCSI Name!",
2377 AsciiStrCpy (Private
->Current
->SessionConfigData
.TargetName
, IScsiName
);
2382 case KEY_DHCP_ENABLE
:
2383 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
2384 IfrNvData
->TargetInfoFromDhcp
= 0;
2390 UnicodeStrToAsciiStr (IfrNvData
->BootLun
, LunString
);
2391 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
2392 if (EFI_ERROR (Status
)) {
2394 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2396 L
"Invalid LUN string!",
2400 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
2406 switch (Value
->u8
) {
2407 case ISCSI_AUTH_TYPE_CHAP
:
2408 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
2417 UnicodeStrToAsciiStr (
2418 IfrNvData
->CHAPName
,
2419 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
2423 case KEY_CHAP_SECRET
:
2424 UnicodeStrToAsciiStr (
2425 IfrNvData
->CHAPSecret
,
2426 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
2430 case KEY_REVERSE_CHAP_NAME
:
2431 UnicodeStrToAsciiStr (
2432 IfrNvData
->ReverseCHAPName
,
2433 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
2437 case KEY_REVERSE_CHAP_SECRET
:
2438 UnicodeStrToAsciiStr (
2439 IfrNvData
->ReverseCHAPSecret
,
2440 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
2444 case KEY_CONFIG_ISID
:
2445 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2446 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2455 if (!EFI_ERROR (Status
)) {
2457 // Pass changed uncommitted data back to Form Browser.
2459 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2460 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2463 FreePool (IfrNvData
);
2464 FreePool (IScsiName
);
2471 Initialize the iSCSI configuration form.
2473 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2475 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
2476 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2480 IScsiConfigFormInit (
2481 IN EFI_HANDLE DriverBindingHandle
2485 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
2487 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
2488 if (CallbackInfo
== NULL
) {
2489 return EFI_OUT_OF_RESOURCES
;
2492 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
2493 CallbackInfo
->Current
= NULL
;
2495 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
2496 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
2497 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
2500 // Install Device Path Protocol and Config Access protocol to driver handle.
2502 Status
= gBS
->InstallMultipleProtocolInterfaces (
2503 &CallbackInfo
->DriverHandle
,
2504 &gEfiDevicePathProtocolGuid
,
2505 &mIScsiHiiVendorDevicePath
,
2506 &gEfiHiiConfigAccessProtocolGuid
,
2507 &CallbackInfo
->ConfigAccess
,
2510 ASSERT_EFI_ERROR (Status
);
2513 // Publish our HII data.
2515 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
2517 CallbackInfo
->DriverHandle
,
2522 if (CallbackInfo
->RegisteredHandle
== NULL
) {
2523 gBS
->UninstallMultipleProtocolInterfaces (
2524 &CallbackInfo
->DriverHandle
,
2525 &gEfiDevicePathProtocolGuid
,
2526 &mIScsiHiiVendorDevicePath
,
2527 &gEfiHiiConfigAccessProtocolGuid
,
2528 &CallbackInfo
->ConfigAccess
,
2531 FreePool(CallbackInfo
);
2532 return EFI_OUT_OF_RESOURCES
;
2535 mCallbackInfo
= CallbackInfo
;
2542 Unload the iSCSI configuration form, this includes: delete all the iSCSI
2543 configuration entries, uninstall the form callback protocol, and
2544 free the resources used.
2546 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2548 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
2549 @retval Others Failed to unload the form.
2553 IScsiConfigFormUnload (
2554 IN EFI_HANDLE DriverBindingHandle
2557 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2558 ISCSI_NIC_INFO
*NicInfo
;
2562 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
2563 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
2564 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2565 FreePool (AttemptConfigData
);
2566 mPrivate
->AttemptCount
--;
2569 ASSERT (mPrivate
->AttemptCount
== 0);
2571 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
2572 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
2573 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
2575 mPrivate
->NicCount
--;
2578 ASSERT (mPrivate
->NicCount
== 0);
2581 // Free attempt is created but not saved to system.
2583 if (mPrivate
->NewAttempt
!= NULL
) {
2584 FreePool (mPrivate
->NewAttempt
);
2587 FreePool (mPrivate
);
2591 // Remove HII package list.
2593 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
2596 // Uninstall Device Path Protocol and Config Access protocol.
2598 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2599 mCallbackInfo
->DriverHandle
,
2600 &gEfiDevicePathProtocolGuid
,
2601 &mIScsiHiiVendorDevicePath
,
2602 &gEfiHiiConfigAccessProtocolGuid
,
2603 &mCallbackInfo
->ConfigAccess
,
2607 FreePool (mCallbackInfo
);