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 if (IP4_IS_UNSPECIFIED (NTOHL (Ip
->Addr
[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip
->Addr
[0]))) {
171 } else if (IpMode
== IP_MODE_IP6
) {
172 return NetIp6IsValidUnicast (&Ip
->v6
);
174 DEBUG ((DEBUG_ERROR
, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode
));
180 Parse IsId in string format and convert it to binary.
182 @param[in] String The buffer of the string to be parsed.
183 @param[in, out] IsId The buffer to store IsId.
185 @retval EFI_SUCCESS The operation finished successfully.
186 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
190 IScsiParseIsIdFromString (
191 IN CONST CHAR16
*String
,
199 CHAR16 PortString
[ISCSI_NAME_IFR_MAX_SIZE
];
202 if ((String
== NULL
) || (IsId
== NULL
)) {
203 return EFI_INVALID_PARAMETER
;
206 IsIdStr
= (CHAR16
*) String
;
208 if (StrLen (IsIdStr
) != 6) {
211 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
212 L
"Error! Input is incorrect, please input 6 hex numbers!\n"
216 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
222 return EFI_INVALID_PARAMETER
;
225 for (Index
= 3; Index
< 6; Index
++) {
226 CopyMem (TempStr
, IsIdStr
, sizeof (TempStr
));
230 // Convert the string to IsId. StrHexToUintn stops at the first character
231 // that is not a valid hex character, '\0' here.
233 NodeVal
= StrHexToUintn (TempStr
);
235 IsId
[Index
] = (UINT8
) NodeVal
;
237 IsIdStr
= IsIdStr
+ 2;
244 Convert IsId from binary to string format.
246 @param[out] String The buffer to store the converted string.
247 @param[in] IsId The buffer to store IsId.
249 @retval EFI_SUCCESS The string converted successfully.
250 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
254 IScsiConvertIsIdToString (
262 if ((String
== NULL
) || (IsId
== NULL
)) {
263 return EFI_INVALID_PARAMETER
;
266 for (Index
= 0; Index
< 6; Index
++) {
267 if (IsId
[Index
] <= 0xF) {
268 Number
= UnicodeSPrint (
270 2 * ISID_CONFIGURABLE_STORAGE
,
275 Number
= UnicodeSPrint (
277 2 * ISID_CONFIGURABLE_STORAGE
,
284 String
= String
+ Number
;
293 Get the attempt config data from global structure by the ConfigIndex.
295 @param[in] AttemptConfigIndex The unique index indicates the attempt.
297 @return Pointer to the attempt config data.
298 @retval NULL The attempt configuration data cannot be found.
301 ISCSI_ATTEMPT_CONFIG_NVDATA
*
302 IScsiConfigGetAttemptByConfigIndex (
303 IN UINT8 AttemptConfigIndex
307 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
309 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
310 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
311 if (Attempt
->AttemptConfigIndex
== AttemptConfigIndex
) {
321 Get the existing attempt config data from global structure by the NicIndex.
323 @param[in] NewAttempt The created new attempt
324 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
327 @return Pointer to the existing attempt config data which
328 has the same NICIndex as the new created attempt.
329 @retval NULL The attempt with NicIndex does not exist.
332 ISCSI_ATTEMPT_CONFIG_NVDATA
*
333 IScsiConfigGetAttemptByNic (
334 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*NewAttempt
,
339 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
341 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
342 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
343 if (Attempt
!= NewAttempt
&& Attempt
->NicIndex
== NewAttempt
->NicIndex
&&
344 Attempt
->SessionConfigData
.Enabled
== IScsiMode
) {
354 Convert the iSCSI configuration data into the IFR data.
356 @param[in] Attempt The iSCSI attempt config data.
357 @param[in, out] IfrNvData The IFR nv data.
361 IScsiConvertAttemptConfigDataToIfrNvData (
362 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
,
363 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
366 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
367 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
371 // Normal session configuration parameters.
373 SessionConfigData
= &Attempt
->SessionConfigData
;
374 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
375 IfrNvData
->IpMode
= SessionConfigData
->IpMode
;
377 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
378 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
379 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
381 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
382 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
383 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->LocalIp
);
384 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
385 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->SubnetMask
);
386 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
387 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Gateway
);
388 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
389 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->TargetIp
);
390 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
391 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
392 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
393 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->TargetIp
);
396 AsciiStrToUnicodeStrS (
397 SessionConfigData
->TargetName
,
398 IfrNvData
->TargetName
,
399 sizeof (IfrNvData
->TargetName
) / sizeof (IfrNvData
->TargetName
[0])
401 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
402 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
404 IfrNvData
->ConnectRetryCount
= SessionConfigData
->ConnectRetryCount
;
405 IfrNvData
->ConnectTimeout
= SessionConfigData
->ConnectTimeout
;
408 // Authentication parameters.
410 IfrNvData
->AuthenticationType
= Attempt
->AuthenticationType
;
412 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
413 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
414 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
415 AsciiStrToUnicodeStrS (
416 AuthConfigData
->CHAPName
,
418 sizeof (IfrNvData
->CHAPName
) / sizeof (IfrNvData
->CHAPName
[0])
420 AsciiStrToUnicodeStrS (
421 AuthConfigData
->CHAPSecret
,
422 IfrNvData
->CHAPSecret
,
423 sizeof (IfrNvData
->CHAPSecret
) / sizeof (IfrNvData
->CHAPSecret
[0])
425 AsciiStrToUnicodeStrS (
426 AuthConfigData
->ReverseCHAPName
,
427 IfrNvData
->ReverseCHAPName
,
428 sizeof (IfrNvData
->ReverseCHAPName
) / sizeof (IfrNvData
->ReverseCHAPName
[0])
430 AsciiStrToUnicodeStrS (
431 AuthConfigData
->ReverseCHAPSecret
,
432 IfrNvData
->ReverseCHAPSecret
,
433 sizeof (IfrNvData
->ReverseCHAPSecret
) / sizeof (IfrNvData
->ReverseCHAPSecret
[0])
440 AsciiStrToUnicodeStrS (
441 Attempt
->AttemptName
,
442 IfrNvData
->AttemptName
,
443 sizeof (IfrNvData
->AttemptName
) / sizeof (IfrNvData
->AttemptName
[0])
448 Convert the IFR data to iSCSI configuration data.
450 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
451 @param[in, out] Attempt The iSCSI attempt config data.
453 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
454 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
455 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
456 @retval EFI_ABORTED The operation is aborted.
457 @retval EFI_SUCCESS The operation is completed successfully.
461 IScsiConvertIfrNvDataToAttemptConfigData (
462 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
463 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
466 EFI_IP_ADDRESS HostIp
;
467 EFI_IP_ADDRESS SubnetMask
;
468 EFI_IP_ADDRESS Gateway
;
470 CHAR16
*AttemptName1
;
471 CHAR16
*AttemptName2
;
472 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
473 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
474 CHAR16 IScsiMode
[64];
476 ISCSI_NIC_INFO
*NicInfo
;
478 UINT8
*AttemptConfigOrder
;
479 UINTN AttemptConfigOrderSize
;
480 UINT8
*AttemptOrderTmp
;
484 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
485 return EFI_INVALID_PARAMETER
;
489 // Update those fields which don't have INTERACTIVE attribute.
491 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
492 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
493 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
495 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
496 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
497 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
499 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
500 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
503 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
506 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
508 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
509 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
513 // Only do full parameter validation if iSCSI is enabled on this device.
515 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
516 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
518 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
520 L
"Connection Establishing Timeout is less than minimum value 100ms.",
524 return EFI_INVALID_PARAMETER
;
528 // Validate the address configuration of the Initiator if DHCP isn't
531 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
532 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
533 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
534 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
536 if ((Gateway
.Addr
[0] != 0)) {
537 if (SubnetMask
.Addr
[0] == 0) {
539 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
541 L
"Gateway address is set but subnet mask is zero.",
545 return EFI_INVALID_PARAMETER
;
546 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
548 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
550 L
"Local IP and Gateway are not in the same subnet.",
554 return EFI_INVALID_PARAMETER
;
559 // Validate target configuration if DHCP isn't deployed.
561 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
562 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
564 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
566 L
"Target IP is invalid!",
569 return EFI_INVALID_PARAMETER
;
573 // Validate iSCSI target name configuration again:
574 // The format of iSCSI target name is already verified in IScsiFormCallback() when
575 // user input the name; here we only check the case user does not input the name.
577 if (Attempt
->SessionConfigData
.TargetName
[0] == '\0') {
579 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
581 L
"iSCSI target name is NULL!",
584 return EFI_INVALID_PARAMETER
;
590 // Validate the authentication info.
592 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
593 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
595 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
597 L
"CHAP Name or CHAP Secret is invalid!",
601 return EFI_INVALID_PARAMETER
;
604 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
605 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
608 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
610 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
613 return EFI_INVALID_PARAMETER
;
618 // Check whether this attempt uses NIC which is already used by existing attempt.
620 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
621 if (SameNicAttempt
!= NULL
) {
622 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
623 if (AttemptName1
== NULL
) {
624 return EFI_OUT_OF_RESOURCES
;
627 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
628 if (AttemptName2
== NULL
) {
629 FreePool (AttemptName1
);
630 return EFI_OUT_OF_RESOURCES
;
633 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_MAX_SIZE
);
634 if (StrLen (AttemptName1
) > ATTEMPT_NAME_SIZE
) {
635 CopyMem (&AttemptName1
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
638 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_MAX_SIZE
);
639 if (StrLen (AttemptName2
) > ATTEMPT_NAME_SIZE
) {
640 CopyMem (&AttemptName2
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
644 mPrivate
->PortString
,
645 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
646 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
652 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
654 mPrivate
->PortString
,
658 FreePool (AttemptName1
);
659 FreePool (AttemptName2
);
664 // Update the iSCSI Mode data and record it in attempt help info.
666 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
667 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
668 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
669 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
670 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
671 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
672 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
675 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
676 UnicodeSPrint (IpMode
, 64, L
"IP4");
677 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
678 UnicodeSPrint (IpMode
, 64, L
"IP6");
679 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
680 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
683 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
684 if (NicInfo
== NULL
) {
685 return EFI_NOT_FOUND
;
688 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
689 if (MacString
== NULL
) {
690 return EFI_OUT_OF_RESOURCES
;
693 AsciiStrToUnicodeStrS (Attempt
->MacString
, MacString
, ISCSI_MAX_MAC_STRING_LEN
);
696 mPrivate
->PortString
,
697 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
698 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
701 NicInfo
->DeviceNumber
,
702 NicInfo
->FunctionNumber
,
707 Attempt
->AttemptTitleHelpToken
= HiiSetString (
708 mCallbackInfo
->RegisteredHandle
,
709 Attempt
->AttemptTitleHelpToken
,
710 mPrivate
->PortString
,
713 if (Attempt
->AttemptTitleHelpToken
== 0) {
714 FreePool (MacString
);
715 return EFI_OUT_OF_RESOURCES
;
719 // Check whether this attempt is an existing one.
721 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
722 if (ExistAttempt
!= NULL
) {
723 ASSERT (ExistAttempt
== Attempt
);
725 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
726 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
729 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
731 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
732 if (mPrivate
->MpioCount
< 1) {
736 if (--mPrivate
->MpioCount
== 0) {
737 mPrivate
->EnableMpio
= FALSE
;
739 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
740 if (mPrivate
->SinglePathCount
< 1) {
743 mPrivate
->SinglePathCount
--;
746 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
747 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
749 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
751 if (mPrivate
->SinglePathCount
< 1) {
755 mPrivate
->EnableMpio
= TRUE
;
756 mPrivate
->MpioCount
++;
757 mPrivate
->SinglePathCount
--;
759 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
760 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
762 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
764 if (mPrivate
->MpioCount
< 1) {
768 if (--mPrivate
->MpioCount
== 0) {
769 mPrivate
->EnableMpio
= FALSE
;
771 mPrivate
->SinglePathCount
++;
773 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
774 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
776 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
778 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
779 mPrivate
->EnableMpio
= TRUE
;
780 mPrivate
->MpioCount
++;
782 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
783 mPrivate
->SinglePathCount
++;
787 } else if (ExistAttempt
== NULL
) {
789 // When a new attempt is created, pointer of the attempt is saved to
790 // mPrivate->NewAttempt, and also saved to mCallbackInfo->Current in
791 // IScsiConfigProcessDefault. If input Attempt does not match any existing
792 // attempt, it should be a new created attempt. Save it to system now.
794 ASSERT (Attempt
== mPrivate
->NewAttempt
);
797 // Save current order number for this attempt.
799 AttemptConfigOrder
= IScsiGetVariableAndSize (
802 &AttemptConfigOrderSize
805 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
809 // Append the new created attempt order to the end.
811 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
812 if (AttemptOrderTmp
== NULL
) {
813 if (AttemptConfigOrder
!= NULL
) {
814 FreePool (AttemptConfigOrder
);
816 return EFI_OUT_OF_RESOURCES
;
819 if (AttemptConfigOrder
!= NULL
) {
820 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
821 FreePool (AttemptConfigOrder
);
824 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
825 AttemptConfigOrder
= AttemptOrderTmp
;
826 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
828 Status
= gRT
->SetVariable (
831 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
832 AttemptConfigOrderSize
,
835 FreePool (AttemptConfigOrder
);
836 if (EFI_ERROR (Status
)) {
841 // Insert new created attempt to array.
843 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
844 mPrivate
->AttemptCount
++;
846 // Reset mPrivate->NewAttempt to NULL, which indicates none attempt is created
847 // but not saved now.
849 mPrivate
->NewAttempt
= NULL
;
851 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
853 // This new Attempt is enabled for MPIO; enable the multipath mode.
855 mPrivate
->EnableMpio
= TRUE
;
856 mPrivate
->MpioCount
++;
857 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
858 mPrivate
->SinglePathCount
++;
861 IScsiConfigUpdateAttempt ();
865 // Record the user configuration information in NVR.
868 mPrivate
->PortString
,
869 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
872 (UINTN
) Attempt
->AttemptConfigIndex
875 FreePool (MacString
);
877 return gRT
->SetVariable (
878 mPrivate
->PortString
,
879 &gEfiIScsiInitiatorNameProtocolGuid
,
880 ISCSI_CONFIG_VAR_ATTR
,
881 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
887 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
890 @param[in] StartLabelNumber The number of start label.
891 @param[out] StartOpCodeHandle Points to the start opcode handle.
892 @param[out] StartLabel Points to the created start opcode.
893 @param[out] EndOpCodeHandle Points to the end opcode handle.
894 @param[out] EndLabel Points to the created end opcode.
896 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
898 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
899 @retval EFI_SUCCESS The operation is completed successfully.
904 IN UINT16 StartLabelNumber
,
905 OUT VOID
**StartOpCodeHandle
,
906 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
907 OUT VOID
**EndOpCodeHandle
,
908 OUT EFI_IFR_GUID_LABEL
**EndLabel
912 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
913 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
915 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
916 return EFI_INVALID_PARAMETER
;
919 *StartOpCodeHandle
= NULL
;
920 *EndOpCodeHandle
= NULL
;
921 Status
= EFI_OUT_OF_RESOURCES
;
924 // Initialize the container for dynamic opcodes.
926 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
927 if (*StartOpCodeHandle
== NULL
) {
931 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
932 if (*EndOpCodeHandle
== NULL
) {
937 // Create Hii Extend Label OpCode as the start opcode.
939 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
943 sizeof (EFI_IFR_GUID_LABEL
)
945 if (InternalStartLabel
== NULL
) {
949 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
950 InternalStartLabel
->Number
= StartLabelNumber
;
953 // Create Hii Extend Label OpCode as the end opcode.
955 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
959 sizeof (EFI_IFR_GUID_LABEL
)
961 if (InternalEndLabel
== NULL
) {
965 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
966 InternalEndLabel
->Number
= LABEL_END
;
968 *StartLabel
= InternalStartLabel
;
969 *EndLabel
= InternalEndLabel
;
975 if (*StartOpCodeHandle
!= NULL
) {
976 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
979 if (*EndOpCodeHandle
!= NULL
) {
980 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
987 Callback function when user presses "Add an Attempt".
989 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
991 @retval EFI_SUCCESS The operation is completed successfully.
995 IScsiConfigAddAttempt (
1000 ISCSI_NIC_INFO
*NicInfo
;
1001 EFI_STRING_ID PortTitleToken
;
1002 EFI_STRING_ID PortTitleHelpToken
;
1003 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1005 VOID
*StartOpCodeHandle
;
1006 EFI_IFR_GUID_LABEL
*StartLabel
;
1007 VOID
*EndOpCodeHandle
;
1008 EFI_IFR_GUID_LABEL
*EndLabel
;
1010 Status
= IScsiCreateOpCode (
1017 if (EFI_ERROR (Status
)) {
1022 // Ask user to select a MAC for this attempt.
1024 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
1025 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
1027 &NicInfo
->PermanentAddress
,
1028 NicInfo
->HwAddressSize
,
1033 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
1034 PortTitleToken
= HiiSetString (
1035 mCallbackInfo
->RegisteredHandle
,
1037 mPrivate
->PortString
,
1040 if (PortTitleToken
== 0) {
1041 Status
= EFI_INVALID_PARAMETER
;
1046 mPrivate
->PortString
,
1047 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1048 L
"PFA: Bus %d | Dev %d | Func %d",
1050 NicInfo
->DeviceNumber
,
1051 NicInfo
->FunctionNumber
1053 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
1054 if (PortTitleHelpToken
== 0) {
1055 Status
= EFI_INVALID_PARAMETER
;
1059 HiiCreateGotoOpCode (
1060 StartOpCodeHandle
, // Container for dynamic created opcodes
1061 FORMID_ATTEMPT_FORM
,
1064 EFI_IFR_FLAG_CALLBACK
, // Question flag
1065 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
1069 Status
= HiiUpdateForm (
1070 mCallbackInfo
->RegisteredHandle
, // HII handle
1071 &gIScsiConfigGuid
, // Formset GUID
1072 FORMID_MAC_FORM
, // Form ID
1073 StartOpCodeHandle
, // Label for where to insert opcodes
1074 EndOpCodeHandle
// Replace data
1078 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1079 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1086 Update the MAIN form to display the configured attempts.
1090 IScsiConfigUpdateAttempt (
1094 CHAR16 AttemptName
[ATTEMPT_NAME_MAX_SIZE
];
1096 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1097 VOID
*StartOpCodeHandle
;
1098 EFI_IFR_GUID_LABEL
*StartLabel
;
1099 VOID
*EndOpCodeHandle
;
1100 EFI_IFR_GUID_LABEL
*EndLabel
;
1103 Status
= IScsiCreateOpCode (
1104 ATTEMPT_ENTRY_LABEL
,
1110 if (EFI_ERROR (Status
)) {
1114 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1115 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1117 AsciiStrToUnicodeStrS (AttemptConfigData
->AttemptName
, AttemptName
, ARRAY_SIZE (AttemptName
));
1118 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) 128, L
"Attempt %s", AttemptName
);
1119 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1120 mCallbackInfo
->RegisteredHandle
,
1122 mPrivate
->PortString
,
1125 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1129 HiiCreateGotoOpCode (
1130 StartOpCodeHandle
, // Container for dynamic created opcodes
1131 FORMID_ATTEMPT_FORM
, // Form ID
1132 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1133 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1134 EFI_IFR_FLAG_CALLBACK
, // Question flag
1135 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1140 mCallbackInfo
->RegisteredHandle
, // HII handle
1141 &gIScsiConfigGuid
, // Formset GUID
1142 FORMID_MAIN_FORM
, // Form ID
1143 StartOpCodeHandle
, // Label for where to insert opcodes
1144 EndOpCodeHandle
// Replace data
1147 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1148 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1153 Callback function when user presses "Commit Changes and Exit" in Delete Attempts.
1155 @param[in] IfrNvData The IFR NV data.
1157 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1158 @retval EFI_SUCCESS The operation is completed successfully.
1159 @retval EFI_ABOTRED This operation is aborted cause of error
1161 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
1166 IScsiConfigDeleteAttempts (
1167 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1173 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1174 UINT8
*AttemptConfigOrder
;
1175 UINTN AttemptConfigOrderSize
;
1176 UINT8
*AttemptNewOrder
;
1181 LIST_ENTRY
*NextEntry
;
1182 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1184 AttemptConfigOrder
= IScsiGetVariableAndSize (
1187 &AttemptConfigOrderSize
1189 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
1190 return EFI_NOT_FOUND
;
1193 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
1194 if (AttemptNewOrder
== NULL
) {
1195 Status
= EFI_OUT_OF_RESOURCES
;
1199 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1203 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
1204 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
1210 // Delete the attempt.
1213 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1214 if (AttemptConfigData
== NULL
) {
1215 Status
= EFI_NOT_FOUND
;
1220 // Remove this attempt from UI configured attempt list.
1222 RemoveEntryList (&AttemptConfigData
->Link
);
1223 mPrivate
->AttemptCount
--;
1225 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1226 if (mPrivate
->MpioCount
< 1) {
1227 Status
= EFI_ABORTED
;
1232 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
1234 if (--mPrivate
->MpioCount
== 0) {
1235 mPrivate
->EnableMpio
= FALSE
;
1237 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1238 if (mPrivate
->SinglePathCount
< 1) {
1239 Status
= EFI_ABORTED
;
1243 mPrivate
->SinglePathCount
--;
1246 AsciiStrToUnicodeStrS (AttemptConfigData
->MacString
, MacString
, ARRAY_SIZE (MacString
));
1249 mPrivate
->PortString
,
1253 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1257 mPrivate
->PortString
,
1258 &gEfiIScsiInitiatorNameProtocolGuid
,
1265 // Mark the attempt order in NVR to be deleted - 0.
1267 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
1268 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
1269 AttemptConfigOrder
[NewIndex
] = 0;
1275 FreePool (AttemptConfigData
);
1278 // Check next Attempt.
1284 // Construct AttemptNewOrder.
1286 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
1287 if (AttemptConfigOrder
[Index
] != 0) {
1288 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
1293 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
1296 // Update AttemptOrder in NVR.
1298 Status
= gRT
->SetVariable (
1302 NewTotal
* sizeof (UINT8
),
1307 if (AttemptConfigOrder
!= NULL
) {
1308 FreePool (AttemptConfigOrder
);
1311 if (AttemptNewOrder
!= NULL
) {
1312 FreePool (AttemptNewOrder
);
1320 Callback function when user presses "Delete Attempts".
1322 @param[in] IfrNvData The IFR nv data.
1324 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1325 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
1326 @retval EFI_SUCCESS The operation is completed successfully.
1330 IScsiConfigDisplayDeleteAttempts (
1331 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1335 UINT8
*AttemptConfigOrder
;
1336 UINTN AttemptConfigOrderSize
;
1338 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1340 VOID
*StartOpCodeHandle
;
1341 EFI_IFR_GUID_LABEL
*StartLabel
;
1342 VOID
*EndOpCodeHandle
;
1343 EFI_IFR_GUID_LABEL
*EndLabel
;
1346 Status
= IScsiCreateOpCode (
1353 if (EFI_ERROR (Status
)) {
1357 AttemptConfigOrder
= IScsiGetVariableAndSize (
1360 &AttemptConfigOrderSize
1362 if (AttemptConfigOrder
!= NULL
) {
1364 // Create the check box opcode to be deleted.
1368 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1369 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1370 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
1372 HiiCreateCheckBoxOpCode(
1374 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
1375 CONFIGURATION_VARSTORE_ID
,
1376 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
1377 AttemptConfigData
->AttemptTitleToken
,
1378 AttemptConfigData
->AttemptTitleHelpToken
,
1386 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
1391 FreePool (AttemptConfigOrder
);
1394 Status
= HiiUpdateForm (
1395 mCallbackInfo
->RegisteredHandle
, // HII handle
1396 &gIScsiConfigGuid
, // Formset GUID
1397 FORMID_DELETE_FORM
, // Form ID
1398 StartOpCodeHandle
, // Label for where to insert opcodes
1399 EndOpCodeHandle
// Replace data
1402 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1403 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1410 Callback function when user presses "Change Attempt Order".
1412 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1413 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1415 @retval EFI_SUCCESS The operation is completed successfully.
1419 IScsiConfigDisplayOrderAttempts (
1426 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1427 VOID
*StartOpCodeHandle
;
1428 EFI_IFR_GUID_LABEL
*StartLabel
;
1429 VOID
*EndOpCodeHandle
;
1430 EFI_IFR_GUID_LABEL
*EndLabel
;
1431 VOID
*OptionsOpCodeHandle
;
1433 Status
= IScsiCreateOpCode (
1440 if (EFI_ERROR (Status
)) {
1443 ASSERT (StartOpCodeHandle
!= NULL
);
1445 OptionsOpCodeHandle
= NULL
;
1448 // If no attempt to be ordered, update the original form and exit.
1450 if (mPrivate
->AttemptCount
== 0) {
1455 // Create Option OpCode.
1457 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
1458 if (OptionsOpCodeHandle
== NULL
) {
1459 Status
= EFI_OUT_OF_RESOURCES
;
1465 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1466 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1467 HiiCreateOneOfOptionOpCode (
1468 OptionsOpCodeHandle
,
1469 AttemptConfigData
->AttemptTitleToken
,
1471 EFI_IFR_NUMERIC_SIZE_1
,
1472 AttemptConfigData
->AttemptConfigIndex
1477 ASSERT (Index
== mPrivate
->AttemptCount
);
1479 HiiCreateOrderedListOpCode (
1480 StartOpCodeHandle
, // Container for dynamic created opcodes
1481 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
1482 CONFIGURATION_VARSTORE_ID
, // VarStore ID
1483 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
1484 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
1485 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
1487 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1488 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
1489 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
1490 OptionsOpCodeHandle
, // Option Opcode list
1491 NULL
// Default Opcode is NULL
1495 Status
= HiiUpdateForm (
1496 mCallbackInfo
->RegisteredHandle
, // HII handle
1497 &gIScsiConfigGuid
, // Formset GUID
1498 FORMID_ORDER_FORM
, // Form ID
1499 StartOpCodeHandle
, // Label for where to insert opcodes
1500 EndOpCodeHandle
// Replace data
1504 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1505 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1506 if (OptionsOpCodeHandle
!= NULL
) {
1507 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
1515 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order.
1517 @param[in] IfrNvData The IFR nv data.
1519 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1521 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1522 @retval EFI_SUCCESS The operation is completed successfully.
1526 IScsiConfigOrderAttempts (
1527 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1533 UINT8 AttemptConfigIndex
;
1534 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1535 UINT8
*AttemptConfigOrder
;
1536 UINT8
*AttemptConfigOrderTmp
;
1537 UINTN AttemptConfigOrderSize
;
1539 AttemptConfigOrder
= IScsiGetVariableAndSize (
1542 &AttemptConfigOrderSize
1544 if (AttemptConfigOrder
== NULL
) {
1545 return EFI_NOT_FOUND
;
1548 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
1549 if (AttemptConfigOrderTmp
== NULL
) {
1550 Status
= EFI_OUT_OF_RESOURCES
;
1554 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
1556 // The real content ends with 0.
1558 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
1562 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
1563 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
1564 if (AttemptConfigData
== NULL
) {
1565 Status
= EFI_NOT_FOUND
;
1570 // Reorder the Attempt List.
1572 RemoveEntryList (&AttemptConfigData
->Link
);
1573 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
1575 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
1578 // Mark it to be deleted - 0.
1580 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1581 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
1582 AttemptConfigOrder
[Indexj
] = 0;
1589 // Adjust the attempt order in NVR.
1591 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
1592 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1593 if (AttemptConfigOrder
[Indexj
] != 0) {
1594 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
1595 AttemptConfigOrder
[Indexj
] = 0;
1601 Status
= gRT
->SetVariable (
1604 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1605 AttemptConfigOrderSize
,
1606 AttemptConfigOrderTmp
1610 if (AttemptConfigOrderTmp
!= NULL
) {
1611 FreePool (AttemptConfigOrderTmp
);
1614 FreePool (AttemptConfigOrder
);
1620 Callback function when a user presses "Attempt *" or when a user selects a NIC to
1621 create the new attempt.
1623 @param[in] KeyValue A unique value which is sent to the original
1624 exporting driver so that it can identify the type
1626 @param[in] IfrNvData The IFR nv data.
1628 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1630 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1631 @retval EFI_SUCCESS The operation is completed successfully.
1635 IScsiConfigProcessDefault (
1636 IN EFI_QUESTION_ID KeyValue
,
1637 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1641 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1642 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
1643 UINT8 CurrentAttemptConfigIndex
;
1644 ISCSI_NIC_INFO
*NicInfo
;
1646 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1647 UINT8
*AttemptConfigOrder
;
1648 UINTN AttemptConfigOrderSize
;
1653 // Is User creating a new attempt?
1657 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
1658 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
1660 // User has pressed "Add an Attempt" and then selects a NIC.
1663 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
1664 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
1667 // User has pressed "Attempt *".
1672 // Don't process anything.
1678 // Free any attempt that is previously created but not saved to system.
1680 if (mPrivate
->NewAttempt
!= NULL
) {
1681 FreePool (mPrivate
->NewAttempt
);
1682 mPrivate
->NewAttempt
= NULL
;
1687 // Determine which NIC user has selected for the new created attempt.
1689 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
1690 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
1691 if (NicInfo
== NULL
) {
1692 return EFI_NOT_FOUND
;
1696 // Create new attempt.
1699 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
1700 if (AttemptConfigData
== NULL
) {
1701 return EFI_OUT_OF_RESOURCES
;
1704 ConfigData
= &AttemptConfigData
->SessionConfigData
;
1705 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1706 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1707 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
1709 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
1710 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
1713 // Get current order number for this attempt.
1715 AttemptConfigOrder
= IScsiGetVariableAndSize (
1718 &AttemptConfigOrderSize
1721 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1723 if (AttemptConfigOrder
== NULL
) {
1724 CurrentAttemptConfigIndex
= 1;
1727 // Get the max attempt config index.
1729 CurrentAttemptConfigIndex
= AttemptConfigOrder
[0];
1730 for (Index
= 1; Index
< TotalNumber
; Index
++) {
1731 if (CurrentAttemptConfigIndex
< AttemptConfigOrder
[Index
]) {
1732 CurrentAttemptConfigIndex
= AttemptConfigOrder
[Index
];
1736 CurrentAttemptConfigIndex
++;
1742 // Record the mapping between attempt order and attempt's configdata.
1744 AttemptConfigData
->AttemptConfigIndex
= CurrentAttemptConfigIndex
;
1746 if (AttemptConfigOrder
!= NULL
) {
1747 FreePool (AttemptConfigOrder
);
1751 // Record the MAC info in Config Data.
1754 &NicInfo
->PermanentAddress
,
1755 NicInfo
->HwAddressSize
,
1760 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, sizeof (AttemptConfigData
->MacString
));
1761 AttemptConfigData
->NicIndex
= NicIndex
;
1764 // Generate OUI-format ISID based on MAC address.
1766 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
1767 AttemptConfigData
->SessionConfigData
.IsId
[0] =
1768 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
1771 // Add the help info for the new attempt.
1774 mPrivate
->PortString
,
1775 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1776 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
1779 NicInfo
->DeviceNumber
,
1780 NicInfo
->FunctionNumber
1783 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
1784 mCallbackInfo
->RegisteredHandle
,
1786 mPrivate
->PortString
,
1789 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
1790 FreePool (AttemptConfigData
);
1791 return EFI_INVALID_PARAMETER
;
1795 // Set the attempt name to default.
1798 mPrivate
->PortString
,
1801 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1803 UnicodeStrToAsciiStrS (mPrivate
->PortString
, AttemptConfigData
->AttemptName
, sizeof (AttemptConfigData
->AttemptName
));
1806 // Save the created Attempt temporarily. If user does not save the attempt
1807 // by press 'KEY_SAVE_ATTEMPT_CONFIG' later, iSCSI driver would know that
1808 // and free resources.
1810 mPrivate
->NewAttempt
= (VOID
*) AttemptConfigData
;
1814 // Determine which Attempt user has selected to configure.
1815 // Get the attempt configuration data.
1817 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
1819 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
1820 if (AttemptConfigData
== NULL
) {
1821 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
1822 return EFI_NOT_FOUND
;
1827 // Clear the old IFR data to avoid sharing it with other attempts.
1829 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1830 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
1831 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
1832 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
1833 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
1836 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
1839 // Update current attempt to be a new created attempt or an existing attempt.
1841 mCallbackInfo
->Current
= AttemptConfigData
;
1849 This function allows the caller to request the current
1850 configuration for one or more named elements. The resulting
1851 string is in <ConfigAltResp> format. Also, any and all alternative
1852 configuration strings shall be appended to the end of the
1853 current configuration string. If they are, they must appear
1854 after the current configuration. They must contain the same
1855 routing (GUID, NAME, PATH) as the current configuration string.
1856 They must have an additional description indicating the type of
1857 alternative configuration the string represents,
1858 "ALTCFG=<StringToken>". That <StringToken> (when
1859 converted from Hex UNICODE to binary) is a reference to a
1860 string in the associated string pack.
1862 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1864 @param[in] Request A null-terminated Unicode string in
1865 <ConfigRequest> format. Note that this
1866 includes the routing information as well as
1867 the configurable name / value pairs. It is
1868 invalid for this string to be in
1869 <MultiConfigRequest> format.
1871 @param[out] Progress On return, points to a character in the
1872 Request string. Points to the string's null
1873 terminator if request was successful. Points
1874 to the most recent "&" before the first
1875 failing name / value pair (or the beginning
1876 of the string if the failure is in the first
1877 name / value pair) if the request was not successful.
1879 @param[out] Results A null-terminated Unicode string in
1880 <ConfigAltResp> format which has all values
1881 filled in for the names in the Request string.
1882 String to be allocated by the called function.
1884 @retval EFI_SUCCESS The Results string is filled with the
1885 values corresponding to all requested
1888 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1889 parts of the results that must be
1890 stored awaiting possible future
1893 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
1894 for the Request parameter
1895 would result in this type of
1896 error. In this case, the
1897 Progress parameter would be
1900 @retval EFI_NOT_FOUND Routing data doesn't match any
1901 known driver. Progress set to the
1902 first character in the routing header.
1903 Note: There is no requirement that the
1904 driver validate the routing data. It
1905 must skip the <ConfigHdr> in order to
1908 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
1909 to most recent "&" before the
1910 error or the beginning of the
1913 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
1914 to the & before the name in
1920 IScsiFormExtractConfig (
1921 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1922 IN CONST EFI_STRING Request
,
1923 OUT EFI_STRING
*Progress
,
1924 OUT EFI_STRING
*Results
1928 CHAR8
*InitiatorName
;
1930 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
1931 ISCSI_FORM_CALLBACK_INFO
*Private
;
1932 EFI_STRING ConfigRequestHdr
;
1933 EFI_STRING ConfigRequest
;
1934 BOOLEAN AllocatedRequest
;
1937 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
1938 return EFI_INVALID_PARAMETER
;
1941 *Progress
= Request
;
1942 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
1943 return EFI_NOT_FOUND
;
1946 ConfigRequestHdr
= NULL
;
1947 ConfigRequest
= NULL
;
1948 AllocatedRequest
= FALSE
;
1951 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
1952 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
1953 if (IfrNvData
== NULL
) {
1954 return EFI_OUT_OF_RESOURCES
;
1957 if (Private
->Current
!= NULL
) {
1958 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
1961 BufferSize
= ISCSI_NAME_MAX_SIZE
;
1962 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
1963 if (InitiatorName
== NULL
) {
1964 FreePool (IfrNvData
);
1965 return EFI_OUT_OF_RESOURCES
;
1968 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
1969 if (EFI_ERROR (Status
)) {
1970 IfrNvData
->InitiatorName
[0] = L
'\0';
1972 AsciiStrToUnicodeStrS (
1974 IfrNvData
->InitiatorName
,
1975 sizeof (IfrNvData
->InitiatorName
) / sizeof (IfrNvData
->InitiatorName
[0])
1980 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
1982 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
1983 ConfigRequest
= Request
;
1984 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
1986 // Request has no request element, construct full request string.
1987 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1988 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
1990 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
1991 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
1992 ConfigRequest
= AllocateZeroPool (Size
);
1993 if (ConfigRequest
== NULL
) {
1994 FreePool (IfrNvData
);
1995 FreePool (InitiatorName
);
1996 return EFI_OUT_OF_RESOURCES
;
1998 AllocatedRequest
= TRUE
;
1999 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
2000 FreePool (ConfigRequestHdr
);
2003 Status
= gHiiConfigRouting
->BlockToConfig (
2006 (UINT8
*) IfrNvData
,
2011 FreePool (IfrNvData
);
2012 FreePool (InitiatorName
);
2015 // Free the allocated config request string.
2017 if (AllocatedRequest
) {
2018 FreePool (ConfigRequest
);
2019 ConfigRequest
= NULL
;
2022 // Set Progress string to the original request string.
2024 if (Request
== NULL
) {
2026 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
2027 *Progress
= Request
+ StrLen (Request
);
2036 This function applies changes in a driver's configuration.
2037 Input is a Configuration, which has the routing data for this
2038 driver followed by name / value configuration pairs. The driver
2039 must apply those pairs to its configurable storage. If the
2040 driver's configuration is stored in a linear block of data
2041 and the driver's name / value pairs are in <BlockConfig>
2042 format, it may use the ConfigToBlock helper function (above) to
2045 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2047 @param[in] Configuration A null-terminated Unicode string in
2048 <ConfigString> format.
2050 @param[out] Progress A pointer to a string filled in with the
2051 offset of the most recent '&' before the
2052 first failing name / value pair (or the
2053 beginning of the string if the failure
2054 is in the first name / value pair) or
2055 the terminating NULL if all was
2058 @retval EFI_SUCCESS The results have been distributed or are
2059 awaiting distribution.
2061 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2062 parts of the results that must be
2063 stored awaiting possible future
2066 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
2067 Results parameter would result
2068 in this type of error.
2070 @retval EFI_NOT_FOUND Target for the specified routing data
2076 IScsiFormRouteConfig (
2077 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2078 IN CONST EFI_STRING Configuration
,
2079 OUT EFI_STRING
*Progress
2082 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
2083 return EFI_INVALID_PARAMETER
;
2087 // Check routing data in <ConfigHdr>.
2088 // Note: if only one Storage is used, then this checking could be skipped.
2090 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
2091 *Progress
= Configuration
;
2092 return EFI_NOT_FOUND
;
2095 *Progress
= Configuration
+ StrLen (Configuration
);
2102 This function is called to provide results data to the driver.
2103 This data consists of a unique key that is used to identify
2104 which data is either being passed back or being asked for.
2106 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2107 @param[in] Action Specifies the type of action taken by the browser.
2108 @param[in] QuestionId A unique value which is sent to the original
2109 exporting driver so that it can identify the type
2110 of data to expect. The format of the data tends to
2111 vary based on the opcode that generated the callback.
2112 @param[in] Type The type of value for the question.
2113 @param[in, out] Value A pointer to the data being sent to the original
2115 @param[out] ActionRequest On return, points to the action requested by the
2118 @retval EFI_SUCCESS The callback successfully handled the action.
2119 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2120 variable and its data.
2121 @retval EFI_DEVICE_ERROR The variable could not be saved.
2122 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2128 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2129 IN EFI_BROWSER_ACTION Action
,
2130 IN EFI_QUESTION_ID QuestionId
,
2132 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
2133 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2136 ISCSI_FORM_CALLBACK_INFO
*Private
;
2139 CHAR8 IpString
[IP_STR_MAX_SIZE
];
2140 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
2142 EFI_IP_ADDRESS HostIp
;
2143 EFI_IP_ADDRESS SubnetMask
;
2144 EFI_IP_ADDRESS Gateway
;
2145 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
2146 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
2148 CHAR16 AttemptName
[ATTEMPT_NAME_SIZE
+ 4];
2151 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
2153 // Do nothing for UEFI OPEN/CLOSE Action
2158 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
2160 // All other type return unsupported.
2162 return EFI_UNSUPPORTED
;
2165 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
2166 return EFI_INVALID_PARAMETER
;
2169 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
2172 // Retrieve uncommitted data from Browser
2175 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2176 IfrNvData
= AllocateZeroPool (BufferSize
);
2177 if (IfrNvData
== NULL
) {
2178 return EFI_OUT_OF_RESOURCES
;
2181 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
2182 if (IScsiName
== NULL
) {
2183 FreePool (IfrNvData
);
2184 return EFI_OUT_OF_RESOURCES
;
2187 Status
= EFI_SUCCESS
;
2189 ZeroMem (&OldIfrNvData
, BufferSize
);
2191 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2193 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
2195 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2196 switch (QuestionId
) {
2197 case KEY_ADD_ATTEMPT
:
2199 // Check whether iSCSI initiator name is configured already.
2201 mPrivate
->InitiatorNameLength
= ISCSI_NAME_MAX_SIZE
;
2202 Status
= gIScsiInitiatorName
.Get (
2203 &gIScsiInitiatorName
,
2204 &mPrivate
->InitiatorNameLength
,
2205 mPrivate
->InitiatorName
2207 if (EFI_ERROR (Status
)) {
2209 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2211 L
"Error: please configure iSCSI initiator name first!",
2217 Status
= IScsiConfigAddAttempt ();
2220 case KEY_DELETE_ATTEMPT
:
2222 OldIfrNvData
.DeleteAttemptList
,
2223 IfrNvData
->DeleteAttemptList
,
2224 sizeof (IfrNvData
->DeleteAttemptList
)
2226 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
2229 case KEY_ORDER_ATTEMPT_CONFIG
:
2231 // Order the attempt according to user input.
2234 OldIfrNvData
.DynamicOrderedList
,
2235 IfrNvData
->DynamicOrderedList
,
2236 sizeof (IfrNvData
->DynamicOrderedList
)
2238 IScsiConfigDisplayOrderAttempts ();
2242 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
2245 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2246 switch (QuestionId
) {
2247 case KEY_INITIATOR_NAME
:
2248 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
2249 BufferSize
= AsciiStrSize (IScsiName
);
2251 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
2252 if (EFI_ERROR (Status
)) {
2254 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2256 L
"Invalid iSCSI Name!",
2261 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2263 case KEY_ATTEMPT_NAME
:
2264 if (StrLen (IfrNvData
->AttemptName
) > ATTEMPT_NAME_SIZE
) {
2265 CopyMem (AttemptName
, IfrNvData
->AttemptName
, ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
2266 CopyMem (&AttemptName
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
2270 IfrNvData
->AttemptName
,
2271 (StrLen (IfrNvData
->AttemptName
) + 1) * sizeof (CHAR16
)
2275 UnicodeStrToAsciiStrS (IfrNvData
->AttemptName
, Private
->Current
->AttemptName
, sizeof (Private
->Current
->AttemptName
));
2277 IScsiConfigUpdateAttempt ();
2279 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2282 case KEY_SAVE_ATTEMPT_CONFIG
:
2283 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
2284 if (EFI_ERROR (Status
)) {
2288 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2291 case KEY_SAVE_ORDER_CHANGES
:
2293 // Sync the Attempt Order to NVR.
2295 Status
= IScsiConfigOrderAttempts (IfrNvData
);
2296 if (EFI_ERROR (Status
)) {
2300 IScsiConfigUpdateAttempt ();
2301 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
2304 case KEY_IGNORE_ORDER_CHANGES
:
2306 IfrNvData
->DynamicOrderedList
,
2307 OldIfrNvData
.DynamicOrderedList
,
2308 sizeof (IfrNvData
->DynamicOrderedList
)
2310 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
2313 case KEY_SAVE_DELETE_ATTEMPT
:
2315 // Delete the Attempt Order from NVR
2317 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
2318 if (EFI_ERROR (Status
)) {
2322 IScsiConfigUpdateAttempt ();
2323 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
2326 case KEY_IGNORE_DELETE_ATTEMPT
:
2328 IfrNvData
->DeleteAttemptList
,
2329 OldIfrNvData
.DeleteAttemptList
,
2330 sizeof (IfrNvData
->DeleteAttemptList
)
2332 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
2336 switch (Value
->u8
) {
2338 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2339 IScsiIpToStr (&Private
->Current
->SessionConfigData
.TargetIp
, TRUE
, IfrNvData
->TargetIp
);
2340 Private
->Current
->AutoConfigureMode
= 0;
2344 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2345 IScsiIpToStr (&Private
->Current
->SessionConfigData
.TargetIp
, FALSE
, IfrNvData
->TargetIp
);
2346 Private
->Current
->AutoConfigureMode
= 0;
2354 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
2355 if (EFI_ERROR (Status
) ||
2356 ((Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
2357 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
2359 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2361 L
"Invalid IP address!",
2365 Status
= EFI_INVALID_PARAMETER
;
2367 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
2372 case KEY_SUBNET_MASK
:
2373 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
2374 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
2376 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2378 L
"Invalid Subnet Mask!",
2382 Status
= EFI_INVALID_PARAMETER
;
2384 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
2390 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
2391 if (EFI_ERROR (Status
) ||
2392 ((Gateway
.Addr
[0] != 0) &&
2393 (Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
2394 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
2396 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2398 L
"Invalid Gateway!",
2401 Status
= EFI_INVALID_PARAMETER
;
2403 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
2409 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, IpString
, sizeof (IpString
));
2410 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
2411 if (EFI_ERROR (Status
) || IP4_IS_LOCAL_BROADCAST (EFI_NTOHL(HostIp
.v4
)) || IP4_IS_UNSPECIFIED (EFI_NTOHL(HostIp
.v4
))) {
2413 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2415 L
"Invalid IP address!",
2418 Status
= EFI_INVALID_PARAMETER
;
2420 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
2425 case KEY_TARGET_NAME
:
2426 UnicodeStrToAsciiStrS (IfrNvData
->TargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
2427 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
2428 if (EFI_ERROR (Status
)) {
2430 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2432 L
"Invalid iSCSI Name!",
2436 AsciiStrCpyS (Private
->Current
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
2441 case KEY_DHCP_ENABLE
:
2442 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
2443 IfrNvData
->TargetInfoFromDhcp
= 0;
2449 UnicodeStrToAsciiStrS (IfrNvData
->BootLun
, LunString
, sizeof (LunString
));
2450 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
2451 if (EFI_ERROR (Status
)) {
2453 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2455 L
"Invalid LUN string!",
2459 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
2465 switch (Value
->u8
) {
2466 case ISCSI_AUTH_TYPE_CHAP
:
2467 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
2476 UnicodeStrToAsciiStrS (
2477 IfrNvData
->CHAPName
,
2478 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
,
2479 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPName
)
2483 case KEY_CHAP_SECRET
:
2484 UnicodeStrToAsciiStrS (
2485 IfrNvData
->CHAPSecret
,
2486 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
,
2487 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
)
2491 case KEY_REVERSE_CHAP_NAME
:
2492 UnicodeStrToAsciiStrS (
2493 IfrNvData
->ReverseCHAPName
,
2494 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
,
2495 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
)
2499 case KEY_REVERSE_CHAP_SECRET
:
2500 UnicodeStrToAsciiStrS (
2501 IfrNvData
->ReverseCHAPSecret
,
2502 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
2503 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
)
2507 case KEY_CONFIG_ISID
:
2508 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2509 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2518 if (!EFI_ERROR (Status
)) {
2520 // Pass changed uncommitted data back to Form Browser.
2522 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2523 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2526 FreePool (IfrNvData
);
2527 FreePool (IScsiName
);
2534 Initialize the iSCSI configuration form.
2536 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2538 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
2539 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2543 IScsiConfigFormInit (
2544 IN EFI_HANDLE DriverBindingHandle
2548 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
2550 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
2551 if (CallbackInfo
== NULL
) {
2552 return EFI_OUT_OF_RESOURCES
;
2555 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
2556 CallbackInfo
->Current
= NULL
;
2558 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
2559 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
2560 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
2563 // Install Device Path Protocol and Config Access protocol to driver handle.
2565 Status
= gBS
->InstallMultipleProtocolInterfaces (
2566 &CallbackInfo
->DriverHandle
,
2567 &gEfiDevicePathProtocolGuid
,
2568 &mIScsiHiiVendorDevicePath
,
2569 &gEfiHiiConfigAccessProtocolGuid
,
2570 &CallbackInfo
->ConfigAccess
,
2573 ASSERT_EFI_ERROR (Status
);
2576 // Publish our HII data.
2578 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
2580 CallbackInfo
->DriverHandle
,
2585 if (CallbackInfo
->RegisteredHandle
== NULL
) {
2586 gBS
->UninstallMultipleProtocolInterfaces (
2587 &CallbackInfo
->DriverHandle
,
2588 &gEfiDevicePathProtocolGuid
,
2589 &mIScsiHiiVendorDevicePath
,
2590 &gEfiHiiConfigAccessProtocolGuid
,
2591 &CallbackInfo
->ConfigAccess
,
2594 FreePool(CallbackInfo
);
2595 return EFI_OUT_OF_RESOURCES
;
2598 mCallbackInfo
= CallbackInfo
;
2605 Unload the iSCSI configuration form, this includes: delete all the iSCSI
2606 configuration entries, uninstall the form callback protocol, and
2607 free the resources used.
2609 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2611 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
2612 @retval Others Failed to unload the form.
2616 IScsiConfigFormUnload (
2617 IN EFI_HANDLE DriverBindingHandle
2620 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2621 ISCSI_NIC_INFO
*NicInfo
;
2625 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
2626 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
2627 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2628 FreePool (AttemptConfigData
);
2629 mPrivate
->AttemptCount
--;
2632 ASSERT (mPrivate
->AttemptCount
== 0);
2634 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
2635 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
2636 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
2638 mPrivate
->NicCount
--;
2641 ASSERT (mPrivate
->NicCount
== 0);
2644 // Free attempt is created but not saved to system.
2646 if (mPrivate
->NewAttempt
!= NULL
) {
2647 FreePool (mPrivate
->NewAttempt
);
2650 FreePool (mPrivate
);
2654 // Remove HII package list.
2656 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
2659 // Uninstall Device Path Protocol and Config Access protocol.
2661 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2662 mCallbackInfo
->DriverHandle
,
2663 &gEfiDevicePathProtocolGuid
,
2664 &mIScsiHiiVendorDevicePath
,
2665 &gEfiHiiConfigAccessProtocolGuid
,
2666 &mCallbackInfo
->ConfigAccess
,
2670 FreePool (mCallbackInfo
);