2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2016, 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 AsciiStrToUnicodeStrS (
394 SessionConfigData
->TargetName
,
395 IfrNvData
->TargetName
,
396 sizeof (IfrNvData
->TargetName
) / sizeof (IfrNvData
->TargetName
[0])
398 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
399 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
401 IfrNvData
->ConnectRetryCount
= SessionConfigData
->ConnectRetryCount
;
402 IfrNvData
->ConnectTimeout
= SessionConfigData
->ConnectTimeout
;
405 // Authentication parameters.
407 IfrNvData
->AuthenticationType
= Attempt
->AuthenticationType
;
409 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
410 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
411 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
412 AsciiStrToUnicodeStrS (
413 AuthConfigData
->CHAPName
,
415 sizeof (IfrNvData
->CHAPName
) / sizeof (IfrNvData
->CHAPName
[0])
417 AsciiStrToUnicodeStrS (
418 AuthConfigData
->CHAPSecret
,
419 IfrNvData
->CHAPSecret
,
420 sizeof (IfrNvData
->CHAPSecret
) / sizeof (IfrNvData
->CHAPSecret
[0])
422 AsciiStrToUnicodeStrS (
423 AuthConfigData
->ReverseCHAPName
,
424 IfrNvData
->ReverseCHAPName
,
425 sizeof (IfrNvData
->ReverseCHAPName
) / sizeof (IfrNvData
->ReverseCHAPName
[0])
427 AsciiStrToUnicodeStrS (
428 AuthConfigData
->ReverseCHAPSecret
,
429 IfrNvData
->ReverseCHAPSecret
,
430 sizeof (IfrNvData
->ReverseCHAPSecret
) / sizeof (IfrNvData
->ReverseCHAPSecret
[0])
437 AsciiStrToUnicodeStrS (
438 Attempt
->AttemptName
,
439 IfrNvData
->AttemptName
,
440 sizeof (IfrNvData
->AttemptName
) / sizeof (IfrNvData
->AttemptName
[0])
445 Convert the IFR data to iSCSI configuration data.
447 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
448 @param[in, out] Attempt The iSCSI attempt config data.
450 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
451 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
452 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
453 @retval EFI_ABORTED The operation is aborted.
454 @retval EFI_SUCCESS The operation is completed successfully.
458 IScsiConvertIfrNvDataToAttemptConfigData (
459 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
460 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
463 EFI_IP_ADDRESS HostIp
;
464 EFI_IP_ADDRESS SubnetMask
;
465 EFI_IP_ADDRESS Gateway
;
467 CHAR16
*AttemptName1
;
468 CHAR16
*AttemptName2
;
469 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
470 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
471 CHAR16 IScsiMode
[64];
473 ISCSI_NIC_INFO
*NicInfo
;
475 UINT8
*AttemptConfigOrder
;
476 UINTN AttemptConfigOrderSize
;
477 UINT8
*AttemptOrderTmp
;
481 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
482 return EFI_INVALID_PARAMETER
;
486 // Update those fields which don't have INTERACTIVE attribute.
488 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
489 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
490 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
492 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
493 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
494 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
496 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
497 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
500 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
503 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
505 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
506 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
510 // Only do full parameter validation if iSCSI is enabled on this device.
512 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
513 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
515 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
517 L
"Connection Establishing Timeout is less than minimum value 100ms.",
521 return EFI_INVALID_PARAMETER
;
525 // Validate the address configuration of the Initiator if DHCP isn't
528 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
529 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
530 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
531 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
533 if ((Gateway
.Addr
[0] != 0)) {
534 if (SubnetMask
.Addr
[0] == 0) {
536 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
538 L
"Gateway address is set but subnet mask is zero.",
542 return EFI_INVALID_PARAMETER
;
543 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
545 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
547 L
"Local IP and Gateway are not in the same subnet.",
551 return EFI_INVALID_PARAMETER
;
556 // Validate target configuration if DHCP isn't deployed.
558 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
559 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
561 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
563 L
"Target IP is invalid!",
566 return EFI_INVALID_PARAMETER
;
570 // Validate iSCSI target name configuration again:
571 // The format of iSCSI target name is already verified in IScsiFormCallback() when
572 // user input the name; here we only check the case user does not input the name.
574 if (Attempt
->SessionConfigData
.TargetName
[0] == '\0') {
576 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
578 L
"iSCSI target name is NULL!",
581 return EFI_INVALID_PARAMETER
;
587 // Validate the authentication info.
589 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
590 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
592 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
594 L
"CHAP Name or CHAP Secret is invalid!",
598 return EFI_INVALID_PARAMETER
;
601 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
602 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
605 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
607 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
610 return EFI_INVALID_PARAMETER
;
615 // Check whether this attempt uses NIC which is already used by existing attempt.
617 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
618 if (SameNicAttempt
!= NULL
) {
619 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
620 if (AttemptName1
== NULL
) {
621 return EFI_OUT_OF_RESOURCES
;
624 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
625 if (AttemptName2
== NULL
) {
626 FreePool (AttemptName1
);
627 return EFI_OUT_OF_RESOURCES
;
630 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_MAX_SIZE
);
631 if (StrLen (AttemptName1
) > ATTEMPT_NAME_SIZE
) {
632 CopyMem (&AttemptName1
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
635 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_MAX_SIZE
);
636 if (StrLen (AttemptName2
) > ATTEMPT_NAME_SIZE
) {
637 CopyMem (&AttemptName2
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
641 mPrivate
->PortString
,
642 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
643 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
649 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
651 mPrivate
->PortString
,
655 FreePool (AttemptName1
);
656 FreePool (AttemptName2
);
661 // Update the iSCSI Mode data and record it in attempt help info.
663 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
664 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
665 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
666 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
667 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
668 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
669 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
672 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
673 UnicodeSPrint (IpMode
, 64, L
"IP4");
674 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
675 UnicodeSPrint (IpMode
, 64, L
"IP6");
676 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
677 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
680 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
681 if (NicInfo
== NULL
) {
682 return EFI_NOT_FOUND
;
685 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
686 if (MacString
== NULL
) {
687 return EFI_OUT_OF_RESOURCES
;
690 AsciiStrToUnicodeStrS (Attempt
->MacString
, MacString
, sizeof (MacString
) / sizeof (MacString
[0]));
693 mPrivate
->PortString
,
694 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
695 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
698 NicInfo
->DeviceNumber
,
699 NicInfo
->FunctionNumber
,
704 Attempt
->AttemptTitleHelpToken
= HiiSetString (
705 mCallbackInfo
->RegisteredHandle
,
706 Attempt
->AttemptTitleHelpToken
,
707 mPrivate
->PortString
,
710 if (Attempt
->AttemptTitleHelpToken
== 0) {
711 FreePool (MacString
);
712 return EFI_OUT_OF_RESOURCES
;
716 // Check whether this attempt is an existing one.
718 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
719 if (ExistAttempt
!= NULL
) {
720 ASSERT (ExistAttempt
== Attempt
);
722 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
723 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
726 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
728 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
729 if (mPrivate
->MpioCount
< 1) {
733 if (--mPrivate
->MpioCount
== 0) {
734 mPrivate
->EnableMpio
= FALSE
;
736 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
737 if (mPrivate
->SinglePathCount
< 1) {
740 mPrivate
->SinglePathCount
--;
743 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
744 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
746 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
748 if (mPrivate
->SinglePathCount
< 1) {
752 mPrivate
->EnableMpio
= TRUE
;
753 mPrivate
->MpioCount
++;
754 mPrivate
->SinglePathCount
--;
756 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
757 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
759 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
761 if (mPrivate
->MpioCount
< 1) {
765 if (--mPrivate
->MpioCount
== 0) {
766 mPrivate
->EnableMpio
= FALSE
;
768 mPrivate
->SinglePathCount
++;
770 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
771 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
773 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
775 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
776 mPrivate
->EnableMpio
= TRUE
;
777 mPrivate
->MpioCount
++;
779 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
780 mPrivate
->SinglePathCount
++;
784 } else if (ExistAttempt
== NULL
) {
786 // When a new attempt is created, pointer of the attempt is saved to
787 // mPrivate->NewAttempt, and also saved to mCallbackInfo->Current in
788 // IScsiConfigProcessDefault. If input Attempt does not match any existing
789 // attempt, it should be a new created attempt. Save it to system now.
791 ASSERT (Attempt
== mPrivate
->NewAttempt
);
794 // Save current order number for this attempt.
796 AttemptConfigOrder
= IScsiGetVariableAndSize (
799 &AttemptConfigOrderSize
802 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
806 // Append the new created attempt order to the end.
808 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
809 if (AttemptOrderTmp
== NULL
) {
810 if (AttemptConfigOrder
!= NULL
) {
811 FreePool (AttemptConfigOrder
);
813 return EFI_OUT_OF_RESOURCES
;
816 if (AttemptConfigOrder
!= NULL
) {
817 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
818 FreePool (AttemptConfigOrder
);
821 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
822 AttemptConfigOrder
= AttemptOrderTmp
;
823 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
825 Status
= gRT
->SetVariable (
828 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
829 AttemptConfigOrderSize
,
832 FreePool (AttemptConfigOrder
);
833 if (EFI_ERROR (Status
)) {
838 // Insert new created attempt to array.
840 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
841 mPrivate
->AttemptCount
++;
843 // Reset mPrivate->NewAttempt to NULL, which indicates none attempt is created
844 // but not saved now.
846 mPrivate
->NewAttempt
= NULL
;
848 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
850 // This new Attempt is enabled for MPIO; enable the multipath mode.
852 mPrivate
->EnableMpio
= TRUE
;
853 mPrivate
->MpioCount
++;
854 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
855 mPrivate
->SinglePathCount
++;
858 IScsiConfigUpdateAttempt ();
862 // Record the user configuration information in NVR.
865 mPrivate
->PortString
,
866 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
869 (UINTN
) Attempt
->AttemptConfigIndex
872 FreePool (MacString
);
874 return gRT
->SetVariable (
875 mPrivate
->PortString
,
876 &gEfiIScsiInitiatorNameProtocolGuid
,
877 ISCSI_CONFIG_VAR_ATTR
,
878 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
884 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
887 @param[in] StartLabelNumber The number of start label.
888 @param[out] StartOpCodeHandle Points to the start opcode handle.
889 @param[out] StartLabel Points to the created start opcode.
890 @param[out] EndOpCodeHandle Points to the end opcode handle.
891 @param[out] EndLabel Points to the created end opcode.
893 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
895 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
896 @retval EFI_SUCCESS The operation is completed successfully.
901 IN UINT16 StartLabelNumber
,
902 OUT VOID
**StartOpCodeHandle
,
903 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
904 OUT VOID
**EndOpCodeHandle
,
905 OUT EFI_IFR_GUID_LABEL
**EndLabel
909 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
910 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
912 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
913 return EFI_INVALID_PARAMETER
;
916 *StartOpCodeHandle
= NULL
;
917 *EndOpCodeHandle
= NULL
;
918 Status
= EFI_OUT_OF_RESOURCES
;
921 // Initialize the container for dynamic opcodes.
923 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
924 if (*StartOpCodeHandle
== NULL
) {
928 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
929 if (*EndOpCodeHandle
== NULL
) {
934 // Create Hii Extend Label OpCode as the start opcode.
936 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
940 sizeof (EFI_IFR_GUID_LABEL
)
942 if (InternalStartLabel
== NULL
) {
946 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
947 InternalStartLabel
->Number
= StartLabelNumber
;
950 // Create Hii Extend Label OpCode as the end opcode.
952 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
956 sizeof (EFI_IFR_GUID_LABEL
)
958 if (InternalEndLabel
== NULL
) {
962 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
963 InternalEndLabel
->Number
= LABEL_END
;
965 *StartLabel
= InternalStartLabel
;
966 *EndLabel
= InternalEndLabel
;
972 if (*StartOpCodeHandle
!= NULL
) {
973 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
976 if (*EndOpCodeHandle
!= NULL
) {
977 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
984 Callback function when user presses "Add an Attempt".
986 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
988 @retval EFI_SUCCESS The operation is completed successfully.
992 IScsiConfigAddAttempt (
997 ISCSI_NIC_INFO
*NicInfo
;
998 EFI_STRING_ID PortTitleToken
;
999 EFI_STRING_ID PortTitleHelpToken
;
1000 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1002 VOID
*StartOpCodeHandle
;
1003 EFI_IFR_GUID_LABEL
*StartLabel
;
1004 VOID
*EndOpCodeHandle
;
1005 EFI_IFR_GUID_LABEL
*EndLabel
;
1007 Status
= IScsiCreateOpCode (
1014 if (EFI_ERROR (Status
)) {
1019 // Ask user to select a MAC for this attempt.
1021 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
1022 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
1024 &NicInfo
->PermanentAddress
,
1025 NicInfo
->HwAddressSize
,
1030 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
1031 PortTitleToken
= HiiSetString (
1032 mCallbackInfo
->RegisteredHandle
,
1034 mPrivate
->PortString
,
1037 if (PortTitleToken
== 0) {
1038 Status
= EFI_INVALID_PARAMETER
;
1043 mPrivate
->PortString
,
1044 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1045 L
"PFA: Bus %d | Dev %d | Func %d",
1047 NicInfo
->DeviceNumber
,
1048 NicInfo
->FunctionNumber
1050 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
1051 if (PortTitleHelpToken
== 0) {
1052 Status
= EFI_INVALID_PARAMETER
;
1056 HiiCreateGotoOpCode (
1057 StartOpCodeHandle
, // Container for dynamic created opcodes
1058 FORMID_ATTEMPT_FORM
,
1061 EFI_IFR_FLAG_CALLBACK
, // Question flag
1062 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
1066 Status
= HiiUpdateForm (
1067 mCallbackInfo
->RegisteredHandle
, // HII handle
1068 &gIScsiConfigGuid
, // Formset GUID
1069 FORMID_MAC_FORM
, // Form ID
1070 StartOpCodeHandle
, // Label for where to insert opcodes
1071 EndOpCodeHandle
// Replace data
1075 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1076 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1083 Update the MAIN form to display the configured attempts.
1087 IScsiConfigUpdateAttempt (
1091 CHAR16 AttemptName
[ATTEMPT_NAME_MAX_SIZE
];
1093 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1094 VOID
*StartOpCodeHandle
;
1095 EFI_IFR_GUID_LABEL
*StartLabel
;
1096 VOID
*EndOpCodeHandle
;
1097 EFI_IFR_GUID_LABEL
*EndLabel
;
1100 Status
= IScsiCreateOpCode (
1101 ATTEMPT_ENTRY_LABEL
,
1107 if (EFI_ERROR (Status
)) {
1111 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1112 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1114 AsciiStrToUnicodeStrS (AttemptConfigData
->AttemptName
, AttemptName
, sizeof (AttemptName
) / sizeof (AttemptName
[0]));
1115 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) 128, L
"Attempt %s", AttemptName
);
1116 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1117 mCallbackInfo
->RegisteredHandle
,
1119 mPrivate
->PortString
,
1122 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1126 HiiCreateGotoOpCode (
1127 StartOpCodeHandle
, // Container for dynamic created opcodes
1128 FORMID_ATTEMPT_FORM
, // Form ID
1129 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1130 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1131 EFI_IFR_FLAG_CALLBACK
, // Question flag
1132 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1137 mCallbackInfo
->RegisteredHandle
, // HII handle
1138 &gIScsiConfigGuid
, // Formset GUID
1139 FORMID_MAIN_FORM
, // Form ID
1140 StartOpCodeHandle
, // Label for where to insert opcodes
1141 EndOpCodeHandle
// Replace data
1144 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1145 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1150 Callback function when user presses "Commit Changes and Exit" in Delete Attempts.
1152 @param[in] IfrNvData The IFR NV data.
1154 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1155 @retval EFI_SUCCESS The operation is completed successfully.
1156 @retval EFI_ABOTRED This operation is aborted cause of error
1158 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
1163 IScsiConfigDeleteAttempts (
1164 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1170 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1171 UINT8
*AttemptConfigOrder
;
1172 UINTN AttemptConfigOrderSize
;
1173 UINT8
*AttemptNewOrder
;
1178 LIST_ENTRY
*NextEntry
;
1179 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1181 AttemptConfigOrder
= IScsiGetVariableAndSize (
1184 &AttemptConfigOrderSize
1186 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
1187 return EFI_NOT_FOUND
;
1190 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
1191 if (AttemptNewOrder
== NULL
) {
1192 Status
= EFI_OUT_OF_RESOURCES
;
1196 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1200 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
1201 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
1207 // Delete the attempt.
1210 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1211 if (AttemptConfigData
== NULL
) {
1212 Status
= EFI_NOT_FOUND
;
1217 // Remove this attempt from UI configured attempt list.
1219 RemoveEntryList (&AttemptConfigData
->Link
);
1220 mPrivate
->AttemptCount
--;
1222 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1223 if (mPrivate
->MpioCount
< 1) {
1224 Status
= EFI_ABORTED
;
1229 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
1231 if (--mPrivate
->MpioCount
== 0) {
1232 mPrivate
->EnableMpio
= FALSE
;
1234 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1235 if (mPrivate
->SinglePathCount
< 1) {
1236 Status
= EFI_ABORTED
;
1240 mPrivate
->SinglePathCount
--;
1243 AsciiStrToUnicodeStrS (AttemptConfigData
->MacString
, MacString
, sizeof (MacString
) / sizeof (MacString
[0]));
1246 mPrivate
->PortString
,
1250 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1254 mPrivate
->PortString
,
1255 &gEfiIScsiInitiatorNameProtocolGuid
,
1262 // Mark the attempt order in NVR to be deleted - 0.
1264 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
1265 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
1266 AttemptConfigOrder
[NewIndex
] = 0;
1272 FreePool (AttemptConfigData
);
1275 // Check next Attempt.
1281 // Construct AttemptNewOrder.
1283 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
1284 if (AttemptConfigOrder
[Index
] != 0) {
1285 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
1290 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
1293 // Update AttemptOrder in NVR.
1295 Status
= gRT
->SetVariable (
1299 NewTotal
* sizeof (UINT8
),
1304 if (AttemptConfigOrder
!= NULL
) {
1305 FreePool (AttemptConfigOrder
);
1308 if (AttemptNewOrder
!= NULL
) {
1309 FreePool (AttemptNewOrder
);
1317 Callback function when user presses "Delete Attempts".
1319 @param[in] IfrNvData The IFR nv data.
1321 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1322 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
1323 @retval EFI_SUCCESS The operation is completed successfully.
1327 IScsiConfigDisplayDeleteAttempts (
1328 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1332 UINT8
*AttemptConfigOrder
;
1333 UINTN AttemptConfigOrderSize
;
1335 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1337 VOID
*StartOpCodeHandle
;
1338 EFI_IFR_GUID_LABEL
*StartLabel
;
1339 VOID
*EndOpCodeHandle
;
1340 EFI_IFR_GUID_LABEL
*EndLabel
;
1343 Status
= IScsiCreateOpCode (
1350 if (EFI_ERROR (Status
)) {
1354 AttemptConfigOrder
= IScsiGetVariableAndSize (
1357 &AttemptConfigOrderSize
1359 if (AttemptConfigOrder
!= NULL
) {
1361 // Create the check box opcode to be deleted.
1365 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1366 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1367 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
1369 HiiCreateCheckBoxOpCode(
1371 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
1372 CONFIGURATION_VARSTORE_ID
,
1373 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
1374 AttemptConfigData
->AttemptTitleToken
,
1375 AttemptConfigData
->AttemptTitleHelpToken
,
1383 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
1388 FreePool (AttemptConfigOrder
);
1391 Status
= HiiUpdateForm (
1392 mCallbackInfo
->RegisteredHandle
, // HII handle
1393 &gIScsiConfigGuid
, // Formset GUID
1394 FORMID_DELETE_FORM
, // Form ID
1395 StartOpCodeHandle
, // Label for where to insert opcodes
1396 EndOpCodeHandle
// Replace data
1399 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1400 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1407 Callback function when user presses "Change Attempt Order".
1409 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1410 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1412 @retval EFI_SUCCESS The operation is completed successfully.
1416 IScsiConfigDisplayOrderAttempts (
1423 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1424 VOID
*StartOpCodeHandle
;
1425 EFI_IFR_GUID_LABEL
*StartLabel
;
1426 VOID
*EndOpCodeHandle
;
1427 EFI_IFR_GUID_LABEL
*EndLabel
;
1428 VOID
*OptionsOpCodeHandle
;
1430 Status
= IScsiCreateOpCode (
1437 if (EFI_ERROR (Status
)) {
1440 ASSERT (StartOpCodeHandle
!= NULL
);
1442 OptionsOpCodeHandle
= NULL
;
1445 // If no attempt to be ordered, update the original form and exit.
1447 if (mPrivate
->AttemptCount
== 0) {
1452 // Create Option OpCode.
1454 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
1455 if (OptionsOpCodeHandle
== NULL
) {
1456 Status
= EFI_OUT_OF_RESOURCES
;
1462 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1463 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1464 HiiCreateOneOfOptionOpCode (
1465 OptionsOpCodeHandle
,
1466 AttemptConfigData
->AttemptTitleToken
,
1468 EFI_IFR_NUMERIC_SIZE_1
,
1469 AttemptConfigData
->AttemptConfigIndex
1474 ASSERT (Index
== mPrivate
->AttemptCount
);
1476 HiiCreateOrderedListOpCode (
1477 StartOpCodeHandle
, // Container for dynamic created opcodes
1478 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
1479 CONFIGURATION_VARSTORE_ID
, // VarStore ID
1480 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
1481 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
1482 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
1484 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1485 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
1486 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
1487 OptionsOpCodeHandle
, // Option Opcode list
1488 NULL
// Default Opcode is NULL
1492 Status
= HiiUpdateForm (
1493 mCallbackInfo
->RegisteredHandle
, // HII handle
1494 &gIScsiConfigGuid
, // Formset GUID
1495 FORMID_ORDER_FORM
, // Form ID
1496 StartOpCodeHandle
, // Label for where to insert opcodes
1497 EndOpCodeHandle
// Replace data
1501 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1502 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1503 if (OptionsOpCodeHandle
!= NULL
) {
1504 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
1512 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order.
1514 @param[in] IfrNvData The IFR nv data.
1516 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1518 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1519 @retval EFI_SUCCESS The operation is completed successfully.
1523 IScsiConfigOrderAttempts (
1524 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1530 UINT8 AttemptConfigIndex
;
1531 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1532 UINT8
*AttemptConfigOrder
;
1533 UINT8
*AttemptConfigOrderTmp
;
1534 UINTN AttemptConfigOrderSize
;
1536 AttemptConfigOrder
= IScsiGetVariableAndSize (
1539 &AttemptConfigOrderSize
1541 if (AttemptConfigOrder
== NULL
) {
1542 return EFI_NOT_FOUND
;
1545 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
1546 if (AttemptConfigOrderTmp
== NULL
) {
1547 Status
= EFI_OUT_OF_RESOURCES
;
1551 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
1553 // The real content ends with 0.
1555 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
1559 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
1560 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
1561 if (AttemptConfigData
== NULL
) {
1562 Status
= EFI_NOT_FOUND
;
1567 // Reorder the Attempt List.
1569 RemoveEntryList (&AttemptConfigData
->Link
);
1570 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
1572 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
1575 // Mark it to be deleted - 0.
1577 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1578 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
1579 AttemptConfigOrder
[Indexj
] = 0;
1586 // Adjust the attempt order in NVR.
1588 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
1589 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1590 if (AttemptConfigOrder
[Indexj
] != 0) {
1591 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
1592 AttemptConfigOrder
[Indexj
] = 0;
1598 Status
= gRT
->SetVariable (
1601 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1602 AttemptConfigOrderSize
,
1603 AttemptConfigOrderTmp
1607 if (AttemptConfigOrderTmp
!= NULL
) {
1608 FreePool (AttemptConfigOrderTmp
);
1611 FreePool (AttemptConfigOrder
);
1617 Callback function when a user presses "Attempt *" or when a user selects a NIC to
1618 create the new attempt.
1620 @param[in] KeyValue A unique value which is sent to the original
1621 exporting driver so that it can identify the type
1623 @param[in] IfrNvData The IFR nv data.
1625 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1627 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1628 @retval EFI_SUCCESS The operation is completed successfully.
1632 IScsiConfigProcessDefault (
1633 IN EFI_QUESTION_ID KeyValue
,
1634 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1638 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1639 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
1640 UINT8 CurrentAttemptConfigIndex
;
1641 ISCSI_NIC_INFO
*NicInfo
;
1643 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1644 UINT8
*AttemptConfigOrder
;
1645 UINTN AttemptConfigOrderSize
;
1650 // Is User creating a new attempt?
1654 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
1655 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
1657 // User has pressed "Add an Attempt" and then selects a NIC.
1660 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
1661 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
1664 // User has pressed "Attempt *".
1669 // Don't process anything.
1675 // Free any attempt that is previously created but not saved to system.
1677 if (mPrivate
->NewAttempt
!= NULL
) {
1678 FreePool (mPrivate
->NewAttempt
);
1679 mPrivate
->NewAttempt
= NULL
;
1684 // Determine which NIC user has selected for the new created attempt.
1686 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
1687 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
1688 if (NicInfo
== NULL
) {
1689 return EFI_NOT_FOUND
;
1693 // Create new attempt.
1696 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
1697 if (AttemptConfigData
== NULL
) {
1698 return EFI_OUT_OF_RESOURCES
;
1701 ConfigData
= &AttemptConfigData
->SessionConfigData
;
1702 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1703 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1704 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
1706 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
1707 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
1710 // Get current order number for this attempt.
1712 AttemptConfigOrder
= IScsiGetVariableAndSize (
1715 &AttemptConfigOrderSize
1718 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1720 if (AttemptConfigOrder
== NULL
) {
1721 CurrentAttemptConfigIndex
= 1;
1724 // Get the max attempt config index.
1726 CurrentAttemptConfigIndex
= AttemptConfigOrder
[0];
1727 for (Index
= 1; Index
< TotalNumber
; Index
++) {
1728 if (CurrentAttemptConfigIndex
< AttemptConfigOrder
[Index
]) {
1729 CurrentAttemptConfigIndex
= AttemptConfigOrder
[Index
];
1733 CurrentAttemptConfigIndex
++;
1739 // Record the mapping between attempt order and attempt's configdata.
1741 AttemptConfigData
->AttemptConfigIndex
= CurrentAttemptConfigIndex
;
1743 if (AttemptConfigOrder
!= NULL
) {
1744 FreePool (AttemptConfigOrder
);
1748 // Record the MAC info in Config Data.
1751 &NicInfo
->PermanentAddress
,
1752 NicInfo
->HwAddressSize
,
1757 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, sizeof (AttemptConfigData
->MacString
));
1758 AttemptConfigData
->NicIndex
= NicIndex
;
1761 // Generate OUI-format ISID based on MAC address.
1763 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
1764 AttemptConfigData
->SessionConfigData
.IsId
[0] =
1765 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
1768 // Add the help info for the new attempt.
1771 mPrivate
->PortString
,
1772 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1773 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
1776 NicInfo
->DeviceNumber
,
1777 NicInfo
->FunctionNumber
1780 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
1781 mCallbackInfo
->RegisteredHandle
,
1783 mPrivate
->PortString
,
1786 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
1787 FreePool (AttemptConfigData
);
1788 return EFI_INVALID_PARAMETER
;
1792 // Set the attempt name to default.
1795 mPrivate
->PortString
,
1798 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1800 UnicodeStrToAsciiStrS (mPrivate
->PortString
, AttemptConfigData
->AttemptName
, sizeof (AttemptConfigData
->AttemptName
));
1803 // Save the created Attempt temporarily. If user does not save the attempt
1804 // by press 'KEY_SAVE_ATTEMPT_CONFIG' later, iSCSI driver would know that
1805 // and free resources.
1807 mPrivate
->NewAttempt
= (VOID
*) AttemptConfigData
;
1811 // Determine which Attempt user has selected to configure.
1812 // Get the attempt configuration data.
1814 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
1816 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
1817 if (AttemptConfigData
== NULL
) {
1818 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
1819 return EFI_NOT_FOUND
;
1824 // Clear the old IFR data to avoid sharing it with other attempts.
1826 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1827 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
1828 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
1829 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
1830 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
1833 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
1836 // Update current attempt to be a new created attempt or an existing attempt.
1838 mCallbackInfo
->Current
= AttemptConfigData
;
1846 This function allows the caller to request the current
1847 configuration for one or more named elements. The resulting
1848 string is in <ConfigAltResp> format. Also, any and all alternative
1849 configuration strings shall be appended to the end of the
1850 current configuration string. If they are, they must appear
1851 after the current configuration. They must contain the same
1852 routing (GUID, NAME, PATH) as the current configuration string.
1853 They must have an additional description indicating the type of
1854 alternative configuration the string represents,
1855 "ALTCFG=<StringToken>". That <StringToken> (when
1856 converted from Hex UNICODE to binary) is a reference to a
1857 string in the associated string pack.
1859 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1861 @param[in] Request A null-terminated Unicode string in
1862 <ConfigRequest> format. Note that this
1863 includes the routing information as well as
1864 the configurable name / value pairs. It is
1865 invalid for this string to be in
1866 <MultiConfigRequest> format.
1868 @param[out] Progress On return, points to a character in the
1869 Request string. Points to the string's null
1870 terminator if request was successful. Points
1871 to the most recent "&" before the first
1872 failing name / value pair (or the beginning
1873 of the string if the failure is in the first
1874 name / value pair) if the request was not successful.
1876 @param[out] Results A null-terminated Unicode string in
1877 <ConfigAltResp> format which has all values
1878 filled in for the names in the Request string.
1879 String to be allocated by the called function.
1881 @retval EFI_SUCCESS The Results string is filled with the
1882 values corresponding to all requested
1885 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1886 parts of the results that must be
1887 stored awaiting possible future
1890 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
1891 for the Request parameter
1892 would result in this type of
1893 error. In this case, the
1894 Progress parameter would be
1897 @retval EFI_NOT_FOUND Routing data doesn't match any
1898 known driver. Progress set to the
1899 first character in the routing header.
1900 Note: There is no requirement that the
1901 driver validate the routing data. It
1902 must skip the <ConfigHdr> in order to
1905 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
1906 to most recent "&" before the
1907 error or the beginning of the
1910 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
1911 to the & before the name in
1917 IScsiFormExtractConfig (
1918 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1919 IN CONST EFI_STRING Request
,
1920 OUT EFI_STRING
*Progress
,
1921 OUT EFI_STRING
*Results
1925 CHAR8
*InitiatorName
;
1927 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
1928 ISCSI_FORM_CALLBACK_INFO
*Private
;
1929 EFI_STRING ConfigRequestHdr
;
1930 EFI_STRING ConfigRequest
;
1931 BOOLEAN AllocatedRequest
;
1934 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
1935 return EFI_INVALID_PARAMETER
;
1938 *Progress
= Request
;
1939 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
1940 return EFI_NOT_FOUND
;
1943 ConfigRequestHdr
= NULL
;
1944 ConfigRequest
= NULL
;
1945 AllocatedRequest
= FALSE
;
1948 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
1949 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
1950 if (IfrNvData
== NULL
) {
1951 return EFI_OUT_OF_RESOURCES
;
1954 if (Private
->Current
!= NULL
) {
1955 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
1958 BufferSize
= ISCSI_NAME_MAX_SIZE
;
1959 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
1960 if (InitiatorName
== NULL
) {
1961 FreePool (IfrNvData
);
1962 return EFI_OUT_OF_RESOURCES
;
1965 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
1966 if (EFI_ERROR (Status
)) {
1967 IfrNvData
->InitiatorName
[0] = L
'\0';
1969 AsciiStrToUnicodeStrS (
1971 IfrNvData
->InitiatorName
,
1972 sizeof (IfrNvData
->InitiatorName
) / sizeof (IfrNvData
->InitiatorName
[0])
1977 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
1979 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
1980 ConfigRequest
= Request
;
1981 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
1983 // Request has no request element, construct full request string.
1984 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1985 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
1987 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
1988 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
1989 ConfigRequest
= AllocateZeroPool (Size
);
1990 if (ConfigRequest
== NULL
) {
1991 FreePool (IfrNvData
);
1992 FreePool (InitiatorName
);
1993 return EFI_OUT_OF_RESOURCES
;
1995 AllocatedRequest
= TRUE
;
1996 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
1997 FreePool (ConfigRequestHdr
);
2000 Status
= gHiiConfigRouting
->BlockToConfig (
2003 (UINT8
*) IfrNvData
,
2008 FreePool (IfrNvData
);
2009 FreePool (InitiatorName
);
2012 // Free the allocated config request string.
2014 if (AllocatedRequest
) {
2015 FreePool (ConfigRequest
);
2016 ConfigRequest
= NULL
;
2019 // Set Progress string to the original request string.
2021 if (Request
== NULL
) {
2023 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
2024 *Progress
= Request
+ StrLen (Request
);
2033 This function applies changes in a driver's configuration.
2034 Input is a Configuration, which has the routing data for this
2035 driver followed by name / value configuration pairs. The driver
2036 must apply those pairs to its configurable storage. If the
2037 driver's configuration is stored in a linear block of data
2038 and the driver's name / value pairs are in <BlockConfig>
2039 format, it may use the ConfigToBlock helper function (above) to
2042 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2044 @param[in] Configuration A null-terminated Unicode string in
2045 <ConfigString> format.
2047 @param[out] Progress A pointer to a string filled in with the
2048 offset of the most recent '&' before the
2049 first failing name / value pair (or the
2050 beginning of the string if the failure
2051 is in the first name / value pair) or
2052 the terminating NULL if all was
2055 @retval EFI_SUCCESS The results have been distributed or are
2056 awaiting distribution.
2058 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2059 parts of the results that must be
2060 stored awaiting possible future
2063 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
2064 Results parameter would result
2065 in this type of error.
2067 @retval EFI_NOT_FOUND Target for the specified routing data
2073 IScsiFormRouteConfig (
2074 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2075 IN CONST EFI_STRING Configuration
,
2076 OUT EFI_STRING
*Progress
2079 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
2080 return EFI_INVALID_PARAMETER
;
2084 // Check routing data in <ConfigHdr>.
2085 // Note: if only one Storage is used, then this checking could be skipped.
2087 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
2088 *Progress
= Configuration
;
2089 return EFI_NOT_FOUND
;
2092 *Progress
= Configuration
+ StrLen (Configuration
);
2099 This function is called to provide results data to the driver.
2100 This data consists of a unique key that is used to identify
2101 which data is either being passed back or being asked for.
2103 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2104 @param[in] Action Specifies the type of action taken by the browser.
2105 @param[in] QuestionId A unique value which is sent to the original
2106 exporting driver so that it can identify the type
2107 of data to expect. The format of the data tends to
2108 vary based on the opcode that generated the callback.
2109 @param[in] Type The type of value for the question.
2110 @param[in, out] Value A pointer to the data being sent to the original
2112 @param[out] ActionRequest On return, points to the action requested by the
2115 @retval EFI_SUCCESS The callback successfully handled the action.
2116 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2117 variable and its data.
2118 @retval EFI_DEVICE_ERROR The variable could not be saved.
2119 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2125 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2126 IN EFI_BROWSER_ACTION Action
,
2127 IN EFI_QUESTION_ID QuestionId
,
2129 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
2130 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2133 ISCSI_FORM_CALLBACK_INFO
*Private
;
2136 CHAR8 IpString
[IP_STR_MAX_SIZE
];
2137 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
2139 EFI_IP_ADDRESS HostIp
;
2140 EFI_IP_ADDRESS SubnetMask
;
2141 EFI_IP_ADDRESS Gateway
;
2142 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
2143 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
2145 CHAR16 AttemptName
[ATTEMPT_NAME_SIZE
+ 4];
2148 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
2150 // Do nothing for UEFI OPEN/CLOSE Action
2155 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
2157 // All other type return unsupported.
2159 return EFI_UNSUPPORTED
;
2162 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
2163 return EFI_INVALID_PARAMETER
;
2166 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
2169 // Retrieve uncommitted data from Browser
2172 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2173 IfrNvData
= AllocateZeroPool (BufferSize
);
2174 if (IfrNvData
== NULL
) {
2175 return EFI_OUT_OF_RESOURCES
;
2178 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
2179 if (IScsiName
== NULL
) {
2180 FreePool (IfrNvData
);
2181 return EFI_OUT_OF_RESOURCES
;
2184 Status
= EFI_SUCCESS
;
2186 ZeroMem (&OldIfrNvData
, BufferSize
);
2188 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2190 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
2192 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2193 switch (QuestionId
) {
2194 case KEY_ADD_ATTEMPT
:
2196 // Check whether iSCSI initiator name is configured already.
2198 mPrivate
->InitiatorNameLength
= ISCSI_NAME_MAX_SIZE
;
2199 Status
= gIScsiInitiatorName
.Get (
2200 &gIScsiInitiatorName
,
2201 &mPrivate
->InitiatorNameLength
,
2202 mPrivate
->InitiatorName
2204 if (EFI_ERROR (Status
)) {
2206 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2208 L
"Error: please configure iSCSI initiator name first!",
2214 Status
= IScsiConfigAddAttempt ();
2217 case KEY_DELETE_ATTEMPT
:
2219 OldIfrNvData
.DeleteAttemptList
,
2220 IfrNvData
->DeleteAttemptList
,
2221 sizeof (IfrNvData
->DeleteAttemptList
)
2223 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
2226 case KEY_ORDER_ATTEMPT_CONFIG
:
2228 // Order the attempt according to user input.
2231 OldIfrNvData
.DynamicOrderedList
,
2232 IfrNvData
->DynamicOrderedList
,
2233 sizeof (IfrNvData
->DynamicOrderedList
)
2235 IScsiConfigDisplayOrderAttempts ();
2239 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
2242 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2243 switch (QuestionId
) {
2244 case KEY_INITIATOR_NAME
:
2245 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
2246 BufferSize
= AsciiStrSize (IScsiName
);
2248 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
2249 if (EFI_ERROR (Status
)) {
2251 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2253 L
"Invalid iSCSI Name!",
2258 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2260 case KEY_ATTEMPT_NAME
:
2261 if (StrLen (IfrNvData
->AttemptName
) > ATTEMPT_NAME_SIZE
) {
2262 CopyMem (AttemptName
, IfrNvData
->AttemptName
, ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
2263 CopyMem (&AttemptName
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
2267 IfrNvData
->AttemptName
,
2268 (StrLen (IfrNvData
->AttemptName
) + 1) * sizeof (CHAR16
)
2272 UnicodeStrToAsciiStrS (IfrNvData
->AttemptName
, Private
->Current
->AttemptName
, sizeof (Private
->Current
->AttemptName
));
2274 IScsiConfigUpdateAttempt ();
2276 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2279 case KEY_SAVE_ATTEMPT_CONFIG
:
2280 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
2281 if (EFI_ERROR (Status
)) {
2285 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2288 case KEY_SAVE_ORDER_CHANGES
:
2290 // Sync the Attempt Order to NVR.
2292 Status
= IScsiConfigOrderAttempts (IfrNvData
);
2293 if (EFI_ERROR (Status
)) {
2297 IScsiConfigUpdateAttempt ();
2298 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
2301 case KEY_IGNORE_ORDER_CHANGES
:
2303 IfrNvData
->DynamicOrderedList
,
2304 OldIfrNvData
.DynamicOrderedList
,
2305 sizeof (IfrNvData
->DynamicOrderedList
)
2307 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
2310 case KEY_SAVE_DELETE_ATTEMPT
:
2312 // Delete the Attempt Order from NVR
2314 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
2315 if (EFI_ERROR (Status
)) {
2319 IScsiConfigUpdateAttempt ();
2320 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
2323 case KEY_IGNORE_DELETE_ATTEMPT
:
2325 IfrNvData
->DeleteAttemptList
,
2326 OldIfrNvData
.DeleteAttemptList
,
2327 sizeof (IfrNvData
->DeleteAttemptList
)
2329 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
2333 switch (Value
->u8
) {
2335 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2336 IScsiIpToStr (&Private
->Current
->SessionConfigData
.TargetIp
, TRUE
, IfrNvData
->TargetIp
);
2337 Private
->Current
->AutoConfigureMode
= 0;
2341 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2342 IScsiIpToStr (&Private
->Current
->SessionConfigData
.TargetIp
, FALSE
, IfrNvData
->TargetIp
);
2343 Private
->Current
->AutoConfigureMode
= 0;
2351 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
2352 if (EFI_ERROR (Status
) || !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
2354 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2356 L
"Invalid IP address!",
2360 Status
= EFI_INVALID_PARAMETER
;
2362 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
2367 case KEY_SUBNET_MASK
:
2368 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
2369 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
2371 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2373 L
"Invalid Subnet Mask!",
2377 Status
= EFI_INVALID_PARAMETER
;
2379 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
2385 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
2386 if (EFI_ERROR (Status
) || ((Gateway
.Addr
[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), 0))) {
2388 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2390 L
"Invalid Gateway!",
2393 Status
= EFI_INVALID_PARAMETER
;
2395 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
2401 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, IpString
, sizeof (IpString
));
2402 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
2403 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
2405 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2407 L
"Invalid IP address!",
2410 Status
= EFI_INVALID_PARAMETER
;
2412 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
2417 case KEY_TARGET_NAME
:
2418 UnicodeStrToAsciiStrS (IfrNvData
->TargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
2419 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
2420 if (EFI_ERROR (Status
)) {
2422 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2424 L
"Invalid iSCSI Name!",
2428 AsciiStrCpyS (Private
->Current
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
2433 case KEY_DHCP_ENABLE
:
2434 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
2435 IfrNvData
->TargetInfoFromDhcp
= 0;
2441 UnicodeStrToAsciiStrS (IfrNvData
->BootLun
, LunString
, sizeof (LunString
));
2442 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
2443 if (EFI_ERROR (Status
)) {
2445 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2447 L
"Invalid LUN string!",
2451 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
2457 switch (Value
->u8
) {
2458 case ISCSI_AUTH_TYPE_CHAP
:
2459 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
2468 UnicodeStrToAsciiStrS (
2469 IfrNvData
->CHAPName
,
2470 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
,
2471 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPName
)
2475 case KEY_CHAP_SECRET
:
2476 UnicodeStrToAsciiStrS (
2477 IfrNvData
->CHAPSecret
,
2478 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
,
2479 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
)
2483 case KEY_REVERSE_CHAP_NAME
:
2484 UnicodeStrToAsciiStrS (
2485 IfrNvData
->ReverseCHAPName
,
2486 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
,
2487 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
)
2491 case KEY_REVERSE_CHAP_SECRET
:
2492 UnicodeStrToAsciiStrS (
2493 IfrNvData
->ReverseCHAPSecret
,
2494 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
2495 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
)
2499 case KEY_CONFIG_ISID
:
2500 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2501 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2510 if (!EFI_ERROR (Status
)) {
2512 // Pass changed uncommitted data back to Form Browser.
2514 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2515 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2518 FreePool (IfrNvData
);
2519 FreePool (IScsiName
);
2526 Initialize the iSCSI configuration form.
2528 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2530 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
2531 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2535 IScsiConfigFormInit (
2536 IN EFI_HANDLE DriverBindingHandle
2540 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
2542 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
2543 if (CallbackInfo
== NULL
) {
2544 return EFI_OUT_OF_RESOURCES
;
2547 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
2548 CallbackInfo
->Current
= NULL
;
2550 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
2551 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
2552 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
2555 // Install Device Path Protocol and Config Access protocol to driver handle.
2557 Status
= gBS
->InstallMultipleProtocolInterfaces (
2558 &CallbackInfo
->DriverHandle
,
2559 &gEfiDevicePathProtocolGuid
,
2560 &mIScsiHiiVendorDevicePath
,
2561 &gEfiHiiConfigAccessProtocolGuid
,
2562 &CallbackInfo
->ConfigAccess
,
2565 ASSERT_EFI_ERROR (Status
);
2568 // Publish our HII data.
2570 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
2572 CallbackInfo
->DriverHandle
,
2577 if (CallbackInfo
->RegisteredHandle
== NULL
) {
2578 gBS
->UninstallMultipleProtocolInterfaces (
2579 &CallbackInfo
->DriverHandle
,
2580 &gEfiDevicePathProtocolGuid
,
2581 &mIScsiHiiVendorDevicePath
,
2582 &gEfiHiiConfigAccessProtocolGuid
,
2583 &CallbackInfo
->ConfigAccess
,
2586 FreePool(CallbackInfo
);
2587 return EFI_OUT_OF_RESOURCES
;
2590 mCallbackInfo
= CallbackInfo
;
2597 Unload the iSCSI configuration form, this includes: delete all the iSCSI
2598 configuration entries, uninstall the form callback protocol, and
2599 free the resources used.
2601 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2603 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
2604 @retval Others Failed to unload the form.
2608 IScsiConfigFormUnload (
2609 IN EFI_HANDLE DriverBindingHandle
2612 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2613 ISCSI_NIC_INFO
*NicInfo
;
2617 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
2618 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
2619 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2620 FreePool (AttemptConfigData
);
2621 mPrivate
->AttemptCount
--;
2624 ASSERT (mPrivate
->AttemptCount
== 0);
2626 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
2627 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
2628 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
2630 mPrivate
->NicCount
--;
2633 ASSERT (mPrivate
->NicCount
== 0);
2636 // Free attempt is created but not saved to system.
2638 if (mPrivate
->NewAttempt
!= NULL
) {
2639 FreePool (mPrivate
->NewAttempt
);
2642 FreePool (mPrivate
);
2646 // Remove HII package list.
2648 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
2651 // Uninstall Device Path Protocol and Config Access protocol.
2653 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2654 mCallbackInfo
->DriverHandle
,
2655 &gEfiDevicePathProtocolGuid
,
2656 &mIScsiHiiVendorDevicePath
,
2657 &gEfiHiiConfigAccessProtocolGuid
,
2658 &mCallbackInfo
->ConfigAccess
,
2662 FreePool (mCallbackInfo
);