2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2011, 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 EFI_GUID mVendorGuid
= ISCSI_CONFIG_GUID
;
18 CHAR16 mVendorStorageName
[] = L
"ISCSI_CONFIG_IFR_NVDATA";
19 BOOLEAN mIScsiDeviceListUpdated
= FALSE
;
20 UINTN mNumberOfIScsiDevices
= 0;
21 ISCSI_FORM_CALLBACK_INFO
*mCallbackInfo
= NULL
;
23 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath
= {
29 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
30 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
34 // {49D7B73E-143D-4716-977B-C45F1CB038CC}
36 { 0x49d7b73e, 0x143d, 0x4716, { 0x97, 0x7b, 0xc4, 0x5f, 0x1c, 0xb0, 0x38, 0xcc } }
40 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
42 (UINT8
) (END_DEVICE_PATH_LENGTH
),
43 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
50 Convert the IP address into a dotted string.
52 @param[in] Ip The IP address.
53 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.
54 @param[out] Str The formatted IP string.
59 IN EFI_IP_ADDRESS
*Ip
,
64 EFI_IPv4_ADDRESS
*Ip4
;
65 EFI_IPv6_ADDRESS
*Ip6
;
69 CHAR16 FormatString
[8];
76 (UINTN
) 2 * IP4_STR_MAX_SIZE
,
90 for (Index
= 0; Index
< 15; Index
= Index
+ 2) {
93 Ip6
->Addr
[Index
] == 0 &&
94 Ip6
->Addr
[Index
+ 1] == 0
97 // Deal with the case of ::.
108 while ((Index
< 15) && (Ip6
->Addr
[Index
] == 0) && (Ip6
->Addr
[Index
+ 1] == 0)) {
116 // :: is at the end of the address.
125 if (Ip6
->Addr
[Index
] == 0) {
126 Number
= UnicodeSPrint (Str
, 2 * IP_STR_MAX_SIZE
, L
"%x:", (UINTN
) Ip6
->Addr
[Index
+ 1]);
128 if (Ip6
->Addr
[Index
+ 1] < 0x10) {
129 CopyMem (FormatString
, L
"%x0%x:", StrSize (L
"%x0%x:"));
131 CopyMem (FormatString
, L
"%x%x:", StrSize (L
"%x%x:"));
134 Number
= UnicodeSPrint (
137 (CONST CHAR16
*) FormatString
,
138 (UINTN
) Ip6
->Addr
[Index
],
139 (UINTN
) Ip6
->Addr
[Index
+ 1]
145 if (Index
+ 2 == 16) {
147 if (*(Str
- 1) == L
':') {
155 Check whether the input IP address is valid.
157 @param[in] Ip The IP address.
158 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.
160 @retval TRUE The input IP address is valid.
161 @retval FALSE Otherwise
166 IN EFI_IP_ADDRESS
*Ip
,
170 if (IpMode
== IP_MODE_IP4
) {
171 return NetIp4IsUnicast (NTOHL (Ip
->Addr
[0]), 0);
172 } else if (IpMode
== IP_MODE_IP6
) {
173 return NetIp6IsValidUnicast (&Ip
->v6
);
175 DEBUG ((DEBUG_ERROR
, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode
));
181 Parse IsId in string format and convert it to binary.
183 @param[in] String The buffer of the string to be parsed.
184 @param[in, out] IsId The buffer to store IsId.
186 @retval EFI_SUCCESS The operation finished successfully.
187 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
191 IScsiParseIsIdFromString (
192 IN CONST CHAR16
*String
,
200 CHAR16 PortString
[ISCSI_NAME_IFR_MAX_SIZE
];
203 if ((String
== NULL
) || (IsId
== NULL
)) {
204 return EFI_INVALID_PARAMETER
;
207 IsIdStr
= (CHAR16
*) String
;
209 if (StrLen (IsIdStr
) != 6) {
212 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
213 L
"Error! Input is incorrect, please input 6 hex numbers!\n"
217 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
223 return EFI_INVALID_PARAMETER
;
226 for (Index
= 3; Index
< 6; Index
++) {
227 CopyMem (TempStr
, IsIdStr
, sizeof (TempStr
));
231 // Convert the string to IsId. StrHexToUintn stops at the first character
232 // that is not a valid hex character, '\0' here.
234 NodeVal
= StrHexToUintn (TempStr
);
236 IsId
[Index
] = (UINT8
) NodeVal
;
238 IsIdStr
= IsIdStr
+ 2;
245 Convert IsId from binary to string format.
247 @param[out] String The buffer to store the converted string.
248 @param[in] IsId The buffer to store IsId.
250 @retval EFI_SUCCESS The string converted successfully.
251 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
255 IScsiConvertIsIdToString (
263 if ((String
== NULL
) || (IsId
== NULL
)) {
264 return EFI_INVALID_PARAMETER
;
267 for (Index
= 0; Index
< 6; Index
++) {
268 if (IsId
[Index
] <= 0xF) {
269 Number
= UnicodeSPrint (
271 2 * ISID_CONFIGURABLE_STORAGE
,
276 Number
= UnicodeSPrint (
278 2 * ISID_CONFIGURABLE_STORAGE
,
285 String
= String
+ Number
;
294 Get the attempt config data from global structure by the ConfigIndex.
296 @param[in] AttemptConfigIndex The unique index indicates the attempt.
298 @return Pointer to the attempt config data.
299 @retval NULL The attempt configuration data cannot be found.
302 ISCSI_ATTEMPT_CONFIG_NVDATA
*
303 IScsiConfigGetAttemptByConfigIndex (
304 IN UINT8 AttemptConfigIndex
308 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
310 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
311 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
312 if (Attempt
->AttemptConfigIndex
== AttemptConfigIndex
) {
322 Get the existing attempt config data from global structure by the NicIndex.
324 @param[in] NewAttempt The created new attempt
325 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
328 @return Pointer to the existing attempt config data which
329 has the same NICIndex as the new created attempt.
330 @retval NULL The attempt with NicIndex does not exist.
333 ISCSI_ATTEMPT_CONFIG_NVDATA
*
334 IScsiConfigGetAttemptByNic (
335 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*NewAttempt
,
340 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
342 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
343 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
344 if (Attempt
!= NewAttempt
&& Attempt
->NicIndex
== NewAttempt
->NicIndex
&&
345 Attempt
->SessionConfigData
.Enabled
== IScsiMode
) {
355 Convert the iSCSI configuration data into the IFR data.
357 @param[in] Attempt The iSCSI attempt config data.
358 @param[in, out] IfrNvData The IFR nv data.
362 IScsiConvertAttemptConfigDataToIfrNvData (
363 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
,
364 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
367 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
368 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
372 // Normal session configuration parameters.
374 SessionConfigData
= &Attempt
->SessionConfigData
;
375 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
376 IfrNvData
->IpMode
= SessionConfigData
->IpMode
;
378 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
379 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
380 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
382 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
383 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
384 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->LocalIp
);
385 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
386 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->SubnetMask
);
387 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
388 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Gateway
);
389 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
390 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->TargetIp
);
391 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
392 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
393 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
394 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->TargetIp
);
397 AsciiStrToUnicodeStr (SessionConfigData
->TargetName
, IfrNvData
->TargetName
);
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 AsciiStrToUnicodeStr (AuthConfigData
->CHAPName
, IfrNvData
->CHAPName
);
413 AsciiStrToUnicodeStr (AuthConfigData
->CHAPSecret
, IfrNvData
->CHAPSecret
);
414 AsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPName
, IfrNvData
->ReverseCHAPName
);
415 AsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPSecret
, IfrNvData
->ReverseCHAPSecret
);
421 AsciiStrToUnicodeStr (Attempt
->AttemptName
, IfrNvData
->AttemptName
);
425 Convert the IFR data to iSCSI configuration data.
427 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
428 @param[in, out] Attempt The iSCSI attempt config data.
430 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
431 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
432 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
433 @retval EFI_ABORTED The operation is aborted.
434 @retval EFI_SUCCESS The operation is completed successfully.
438 IScsiConvertIfrNvDataToAttemptConfigData (
439 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
440 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
443 EFI_IP_ADDRESS HostIp
;
444 EFI_IP_ADDRESS SubnetMask
;
445 EFI_IP_ADDRESS Gateway
;
447 CHAR16
*AttemptName1
;
448 CHAR16
*AttemptName2
;
449 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
450 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
451 CHAR16 IScsiMode
[64];
453 ISCSI_NIC_INFO
*NicInfo
;
455 UINT8
*AttemptConfigOrder
;
456 UINTN AttemptConfigOrderSize
;
457 UINT8
*AttemptOrderTmp
;
461 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
462 return EFI_INVALID_PARAMETER
;
466 // Update those fields which don't have INTERACTIVE attribute.
468 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
469 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
470 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
472 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
473 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
474 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
476 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
477 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
480 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
483 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
485 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
486 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
490 // Only do full parameter validation if iSCSI is enabled on this device.
492 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
493 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
495 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
497 L
"Connection Establishing Timeout is less than minimum value 100ms.",
501 return EFI_INVALID_PARAMETER
;
505 // Validate the address configuration of the Initiator if DHCP isn't
508 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
509 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
510 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
511 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
513 if ((Gateway
.Addr
[0] != 0)) {
514 if (SubnetMask
.Addr
[0] == 0) {
516 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
518 L
"Gateway address is set but subnet mask is zero.",
522 return EFI_INVALID_PARAMETER
;
523 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
525 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
527 L
"Local IP and Gateway are not in the same subnet.",
531 return EFI_INVALID_PARAMETER
;
536 // Validate target configuration if DHCP isn't deployed.
538 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
539 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
541 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
543 L
"Target IP is invalid!",
546 return EFI_INVALID_PARAMETER
;
550 // Validate the authentication info.
552 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
553 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
555 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
557 L
"CHAP Name or CHAP Secret is invalid!",
561 return EFI_INVALID_PARAMETER
;
564 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
565 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
568 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
570 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
573 return EFI_INVALID_PARAMETER
;
578 // Check whether this attempt uses NIC which is already used by existing attempt.
580 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
581 if (SameNicAttempt
!= NULL
) {
582 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
583 if (AttemptName1
== NULL
) {
584 return EFI_OUT_OF_RESOURCES
;
587 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
588 if (AttemptName2
== NULL
) {
589 FreePool (AttemptName1
);
590 return EFI_OUT_OF_RESOURCES
;
593 AsciiStrToUnicodeStr (Attempt
->AttemptName
, AttemptName1
);
594 if (StrLen (AttemptName1
) > ATTEMPT_NAME_SIZE
) {
595 CopyMem (&AttemptName1
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
598 AsciiStrToUnicodeStr (SameNicAttempt
->AttemptName
, AttemptName2
);
599 if (StrLen (AttemptName2
) > ATTEMPT_NAME_SIZE
) {
600 CopyMem (&AttemptName2
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
604 mPrivate
->PortString
,
605 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
606 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
612 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
614 mPrivate
->PortString
,
618 FreePool (AttemptName1
);
619 FreePool (AttemptName2
);
624 // Update the iSCSI Mode data and record it in attempt help info.
626 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
627 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
628 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
629 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
630 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
631 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
632 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
635 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
636 UnicodeSPrint (IpMode
, 64, L
"IP4");
637 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
638 UnicodeSPrint (IpMode
, 64, L
"IP6");
639 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
640 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
643 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
644 if (NicInfo
== NULL
) {
645 return EFI_NOT_FOUND
;
648 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
649 if (MacString
== NULL
) {
650 return EFI_OUT_OF_RESOURCES
;
653 AsciiStrToUnicodeStr (Attempt
->MacString
, MacString
);
656 mPrivate
->PortString
,
657 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
658 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
661 NicInfo
->DeviceNumber
,
662 NicInfo
->FunctionNumber
,
667 Attempt
->AttemptTitleHelpToken
= HiiSetString (
668 mCallbackInfo
->RegisteredHandle
,
669 Attempt
->AttemptTitleHelpToken
,
670 mPrivate
->PortString
,
673 if (Attempt
->AttemptTitleHelpToken
== 0) {
674 FreePool (MacString
);
675 return EFI_OUT_OF_RESOURCES
;
679 // Check whether this attempt is an existing one.
681 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
682 if (ExistAttempt
!= NULL
) {
683 ASSERT (ExistAttempt
== Attempt
);
685 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
686 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
689 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
691 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
692 if (mPrivate
->MpioCount
< 1) {
696 if (--mPrivate
->MpioCount
== 0) {
697 mPrivate
->EnableMpio
= FALSE
;
699 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
700 if (mPrivate
->SinglePathCount
< 1) {
703 mPrivate
->SinglePathCount
--;
706 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
707 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
709 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
711 if (mPrivate
->SinglePathCount
< 1) {
715 mPrivate
->EnableMpio
= TRUE
;
716 mPrivate
->MpioCount
++;
717 mPrivate
->SinglePathCount
--;
719 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
720 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
722 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
724 if (mPrivate
->MpioCount
< 1) {
728 if (--mPrivate
->MpioCount
== 0) {
729 mPrivate
->EnableMpio
= FALSE
;
731 mPrivate
->SinglePathCount
++;
733 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
734 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
736 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
738 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
739 mPrivate
->EnableMpio
= TRUE
;
740 mPrivate
->MpioCount
++;
742 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
743 mPrivate
->SinglePathCount
++;
747 } else if (ExistAttempt
== NULL
) {
749 // When a new attempt is created, pointer of the attempt is saved to
750 // mPrivate->NewAttempt, and also saved to mCallbackInfo->Current in
751 // IScsiConfigProcessDefault. If input Attempt does not match any existing
752 // attempt, it should be a new created attempt. Save it to system now.
754 ASSERT (Attempt
== mPrivate
->NewAttempt
);
757 // Save current order number for this attempt.
759 AttemptConfigOrder
= IScsiGetVariableAndSize (
762 &AttemptConfigOrderSize
765 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
769 // Append the new created attempt order to the end.
771 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
772 if (AttemptOrderTmp
== NULL
) {
773 if (AttemptConfigOrder
!= NULL
) {
774 FreePool (AttemptConfigOrder
);
776 return EFI_OUT_OF_RESOURCES
;
779 if (AttemptConfigOrder
!= NULL
) {
780 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
781 FreePool (AttemptConfigOrder
);
784 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
785 AttemptConfigOrder
= AttemptOrderTmp
;
786 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
788 Status
= gRT
->SetVariable (
791 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
792 AttemptConfigOrderSize
,
795 FreePool (AttemptConfigOrder
);
796 if (EFI_ERROR (Status
)) {
801 // Insert new created attempt to array.
803 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
804 mPrivate
->AttemptCount
++;
806 // Reset mPrivate->NewAttempt to NULL, which indicates none attempt is created
807 // but not saved now.
809 mPrivate
->NewAttempt
= NULL
;
811 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
813 // This new Attempt is enabled for MPIO; enable the multipath mode.
815 mPrivate
->EnableMpio
= TRUE
;
816 mPrivate
->MpioCount
++;
817 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
818 mPrivate
->SinglePathCount
++;
821 IScsiConfigUpdateAttempt ();
825 // Record the user configuration information in NVR.
828 mPrivate
->PortString
,
829 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
832 (UINTN
) Attempt
->AttemptConfigIndex
835 FreePool (MacString
);
837 return gRT
->SetVariable (
838 mPrivate
->PortString
,
839 &gEfiIScsiInitiatorNameProtocolGuid
,
840 ISCSI_CONFIG_VAR_ATTR
,
841 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
847 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
850 @param[in] StartLabelNumber The number of start label.
851 @param[out] StartOpCodeHandle Points to the start opcode handle.
852 @param[out] StartLabel Points to the created start opcode.
853 @param[out] EndOpCodeHandle Points to the end opcode handle.
854 @param[out] EndLabel Points to the created end opcode.
856 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
858 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
859 @retval EFI_SUCCESS The operation is completed successfully.
864 IN UINT16 StartLabelNumber
,
865 OUT VOID
**StartOpCodeHandle
,
866 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
867 OUT VOID
**EndOpCodeHandle
,
868 OUT EFI_IFR_GUID_LABEL
**EndLabel
872 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
873 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
875 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
876 return EFI_INVALID_PARAMETER
;
879 *StartOpCodeHandle
= NULL
;
880 *EndOpCodeHandle
= NULL
;
881 Status
= EFI_OUT_OF_RESOURCES
;
884 // Initialize the container for dynamic opcodes.
886 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
887 if (*StartOpCodeHandle
== NULL
) {
891 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
892 if (*EndOpCodeHandle
== NULL
) {
897 // Create Hii Extend Label OpCode as the start opcode.
899 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
903 sizeof (EFI_IFR_GUID_LABEL
)
905 if (InternalStartLabel
== NULL
) {
909 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
910 InternalStartLabel
->Number
= StartLabelNumber
;
913 // Create Hii Extend Label OpCode as the end opcode.
915 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
919 sizeof (EFI_IFR_GUID_LABEL
)
921 if (InternalEndLabel
== NULL
) {
925 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
926 InternalEndLabel
->Number
= LABEL_END
;
928 *StartLabel
= InternalStartLabel
;
929 *EndLabel
= InternalEndLabel
;
935 if (*StartOpCodeHandle
!= NULL
) {
936 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
939 if (*EndOpCodeHandle
!= NULL
) {
940 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
947 Callback function when user presses "Add an Attempt".
949 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
951 @retval EFI_SUCCESS The operation is completed successfully.
955 IScsiConfigAddAttempt (
960 ISCSI_NIC_INFO
*NicInfo
;
961 EFI_STRING_ID PortTitleToken
;
962 EFI_STRING_ID PortTitleHelpToken
;
963 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
965 VOID
*StartOpCodeHandle
;
966 EFI_IFR_GUID_LABEL
*StartLabel
;
967 VOID
*EndOpCodeHandle
;
968 EFI_IFR_GUID_LABEL
*EndLabel
;
970 Status
= IScsiCreateOpCode (
977 if (EFI_ERROR (Status
)) {
982 // Ask user to select a MAC for this attempt.
984 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
985 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
987 &NicInfo
->PermanentAddress
,
988 NicInfo
->HwAddressSize
,
993 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
994 PortTitleToken
= HiiSetString (
995 mCallbackInfo
->RegisteredHandle
,
997 mPrivate
->PortString
,
1000 if (PortTitleToken
== 0) {
1001 Status
= EFI_INVALID_PARAMETER
;
1006 mPrivate
->PortString
,
1007 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1008 L
"PFA: Bus %d | Dev %d | Func %d",
1010 NicInfo
->DeviceNumber
,
1011 NicInfo
->FunctionNumber
1013 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
1014 if (PortTitleHelpToken
== 0) {
1015 Status
= EFI_INVALID_PARAMETER
;
1019 HiiCreateGotoOpCode (
1020 StartOpCodeHandle
, // Container for dynamic created opcodes
1021 FORMID_ATTEMPT_FORM
,
1024 EFI_IFR_FLAG_CALLBACK
, // Question flag
1025 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
1029 Status
= HiiUpdateForm (
1030 mCallbackInfo
->RegisteredHandle
, // HII handle
1031 &mVendorGuid
, // Formset GUID
1032 FORMID_MAC_FORM
, // Form ID
1033 StartOpCodeHandle
, // Label for where to insert opcodes
1034 EndOpCodeHandle
// Replace data
1038 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1039 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1046 Update the MAIN form to display the configured attempts.
1050 IScsiConfigUpdateAttempt (
1054 CHAR16 AttemptName
[ATTEMPT_NAME_MAX_SIZE
];
1056 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1057 VOID
*StartOpCodeHandle
;
1058 EFI_IFR_GUID_LABEL
*StartLabel
;
1059 VOID
*EndOpCodeHandle
;
1060 EFI_IFR_GUID_LABEL
*EndLabel
;
1063 Status
= IScsiCreateOpCode (
1064 ATTEMPT_ENTRY_LABEL
,
1070 if (EFI_ERROR (Status
)) {
1074 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1075 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1077 AsciiStrToUnicodeStr (AttemptConfigData
->AttemptName
, AttemptName
);
1078 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) 128, L
"Attempt %s", AttemptName
);
1079 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1080 mCallbackInfo
->RegisteredHandle
,
1082 mPrivate
->PortString
,
1085 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1089 HiiCreateGotoOpCode (
1090 StartOpCodeHandle
, // Container for dynamic created opcodes
1091 FORMID_ATTEMPT_FORM
, // Form ID
1092 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1093 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1094 EFI_IFR_FLAG_CALLBACK
, // Question flag
1095 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1100 mCallbackInfo
->RegisteredHandle
, // HII handle
1101 &mVendorGuid
, // Formset GUID
1102 FORMID_MAIN_FORM
, // Form ID
1103 StartOpCodeHandle
, // Label for where to insert opcodes
1104 EndOpCodeHandle
// Replace data
1107 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1108 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1113 Callback function when user presses "Commit Changes and Exit" in Delete Attempts.
1115 @param[in] IfrNvData The IFR NV data.
1117 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1118 @retval EFI_SUCCESS The operation is completed successfully.
1119 @retval EFI_ABOTRED This operation is aborted cause of error
1121 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
1126 IScsiConfigDeleteAttempts (
1127 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1133 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1134 UINT8
*AttemptConfigOrder
;
1135 UINTN AttemptConfigOrderSize
;
1136 UINT8
*AttemptNewOrder
;
1141 LIST_ENTRY
*NextEntry
;
1142 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1144 AttemptConfigOrder
= IScsiGetVariableAndSize (
1147 &AttemptConfigOrderSize
1149 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
1150 return EFI_NOT_FOUND
;
1153 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
1154 if (AttemptNewOrder
== NULL
) {
1155 Status
= EFI_OUT_OF_RESOURCES
;
1159 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1163 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
1164 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
1170 // Delete the attempt.
1173 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1174 if (AttemptConfigData
== NULL
) {
1175 Status
= EFI_NOT_FOUND
;
1180 // Remove this attempt from UI configured attempt list.
1182 RemoveEntryList (&AttemptConfigData
->Link
);
1183 mPrivate
->AttemptCount
--;
1185 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1186 if (mPrivate
->MpioCount
< 1) {
1187 Status
= EFI_ABORTED
;
1192 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
1194 if (--mPrivate
->MpioCount
== 0) {
1195 mPrivate
->EnableMpio
= FALSE
;
1197 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1198 if (mPrivate
->SinglePathCount
< 1) {
1199 Status
= EFI_ABORTED
;
1203 mPrivate
->SinglePathCount
--;
1206 AsciiStrToUnicodeStr (AttemptConfigData
->MacString
, MacString
);
1209 mPrivate
->PortString
,
1213 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1217 mPrivate
->PortString
,
1218 &gEfiIScsiInitiatorNameProtocolGuid
,
1225 // Mark the attempt order in NVR to be deleted - 0.
1227 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
1228 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
1229 AttemptConfigOrder
[NewIndex
] = 0;
1235 FreePool (AttemptConfigData
);
1238 // Check next Attempt.
1244 // Construct AttemptNewOrder.
1246 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
1247 if (AttemptConfigOrder
[Index
] != 0) {
1248 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
1253 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
1254 | EFI_VARIABLE_NON_VOLATILE
;
1257 // Update AttemptOrder in NVR.
1259 Status
= gRT
->SetVariable (
1263 NewTotal
* sizeof (UINT8
),
1268 if (AttemptConfigOrder
!= NULL
) {
1269 FreePool (AttemptConfigOrder
);
1272 if (AttemptNewOrder
!= NULL
) {
1273 FreePool (AttemptNewOrder
);
1281 Callback function when user presses "Delete Attempts".
1283 @param[in] IfrNvData The IFR nv data.
1285 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1286 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
1287 @retval EFI_SUCCESS The operation is completed successfully.
1291 IScsiConfigDisplayDeleteAttempts (
1292 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1296 UINT8
*AttemptConfigOrder
;
1297 UINTN AttemptConfigOrderSize
;
1299 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1301 VOID
*StartOpCodeHandle
;
1302 EFI_IFR_GUID_LABEL
*StartLabel
;
1303 VOID
*EndOpCodeHandle
;
1304 EFI_IFR_GUID_LABEL
*EndLabel
;
1307 Status
= IScsiCreateOpCode (
1314 if (EFI_ERROR (Status
)) {
1318 AttemptConfigOrder
= IScsiGetVariableAndSize (
1321 &AttemptConfigOrderSize
1323 if (AttemptConfigOrder
!= NULL
) {
1325 // Create the check box opcode to be deleted.
1329 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1330 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1331 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
1333 HiiCreateCheckBoxOpCode(
1335 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
1336 CONFIGURATION_VARSTORE_ID
,
1337 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
1338 AttemptConfigData
->AttemptTitleToken
,
1339 AttemptConfigData
->AttemptTitleHelpToken
,
1347 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
1352 FreePool (AttemptConfigOrder
);
1355 Status
= HiiUpdateForm (
1356 mCallbackInfo
->RegisteredHandle
, // HII handle
1357 &mVendorGuid
, // Formset GUID
1358 FORMID_DELETE_FORM
, // Form ID
1359 StartOpCodeHandle
, // Label for where to insert opcodes
1360 EndOpCodeHandle
// Replace data
1363 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1364 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1371 Callback function when user presses "Change Attempt Order".
1373 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1374 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1376 @retval EFI_SUCCESS The operation is completed successfully.
1380 IScsiConfigDisplayOrderAttempts (
1387 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1388 VOID
*StartOpCodeHandle
;
1389 EFI_IFR_GUID_LABEL
*StartLabel
;
1390 VOID
*EndOpCodeHandle
;
1391 EFI_IFR_GUID_LABEL
*EndLabel
;
1392 VOID
*OptionsOpCodeHandle
;
1394 Status
= IScsiCreateOpCode (
1401 if (EFI_ERROR (Status
)) {
1405 OptionsOpCodeHandle
= NULL
;
1408 // If no attempt to be ordered, update the original form and exit.
1410 if (mPrivate
->AttemptCount
== 0) {
1415 // Create Option OpCode.
1417 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
1418 if (OptionsOpCodeHandle
== NULL
) {
1419 Status
= EFI_OUT_OF_RESOURCES
;
1425 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1426 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1427 HiiCreateOneOfOptionOpCode (
1428 OptionsOpCodeHandle
,
1429 AttemptConfigData
->AttemptTitleToken
,
1431 EFI_IFR_NUMERIC_SIZE_1
,
1432 AttemptConfigData
->AttemptConfigIndex
1437 ASSERT (Index
== mPrivate
->AttemptCount
);
1439 HiiCreateOrderedListOpCode (
1440 StartOpCodeHandle
, // Container for dynamic created opcodes
1441 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
1442 CONFIGURATION_VARSTORE_ID
, // VarStore ID
1443 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
1444 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
1445 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
1447 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1448 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
1449 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
1450 OptionsOpCodeHandle
, // Option Opcode list
1451 NULL
// Default Opcode is NULL
1455 Status
= HiiUpdateForm (
1456 mCallbackInfo
->RegisteredHandle
, // HII handle
1457 &mVendorGuid
, // Formset GUID
1458 FORMID_ORDER_FORM
, // Form ID
1459 StartOpCodeHandle
, // Label for where to insert opcodes
1460 EndOpCodeHandle
// Replace data
1464 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1465 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1466 if (OptionsOpCodeHandle
!= NULL
) {
1467 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
1475 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order.
1477 @param[in] IfrNvData The IFR nv data.
1479 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1481 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1482 @retval EFI_SUCCESS The operation is completed successfully.
1486 IScsiConfigOrderAttempts (
1487 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1493 UINT8 AttemptConfigIndex
;
1494 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1495 UINT8
*AttemptConfigOrder
;
1496 UINT8
*AttemptConfigOrderTmp
;
1497 UINTN AttemptConfigOrderSize
;
1499 AttemptConfigOrder
= IScsiGetVariableAndSize (
1502 &AttemptConfigOrderSize
1504 if (AttemptConfigOrder
== NULL
) {
1505 return EFI_NOT_FOUND
;
1508 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
1509 if (AttemptConfigOrderTmp
== NULL
) {
1510 Status
= EFI_OUT_OF_RESOURCES
;
1514 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
1516 // The real content ends with 0.
1518 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
1522 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
1523 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
1524 if (AttemptConfigData
== NULL
) {
1525 Status
= EFI_NOT_FOUND
;
1530 // Reorder the Attempt List.
1532 RemoveEntryList (&AttemptConfigData
->Link
);
1533 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
1535 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
1538 // Mark it to be deleted - 0.
1540 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1541 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
1542 AttemptConfigOrder
[Indexj
] = 0;
1549 // Adjust the attempt order in NVR.
1551 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
1552 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1553 if (AttemptConfigOrder
[Indexj
] != 0) {
1554 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
1555 AttemptConfigOrder
[Indexj
] = 0;
1561 Status
= gRT
->SetVariable (
1564 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1565 AttemptConfigOrderSize
,
1566 AttemptConfigOrderTmp
1570 if (AttemptConfigOrderTmp
!= NULL
) {
1571 FreePool (AttemptConfigOrderTmp
);
1574 FreePool (AttemptConfigOrder
);
1580 Callback function when a user presses "Attempt *" or when a user selects a NIC to
1581 create the new attempt.
1583 @param[in] KeyValue A unique value which is sent to the original
1584 exporting driver so that it can identify the type
1586 @param[in] IfrNvData The IFR nv data.
1588 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1590 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1591 @retval EFI_SUCCESS The operation is completed successfully.
1595 IScsiConfigProcessDefault (
1596 IN EFI_QUESTION_ID KeyValue
,
1597 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1601 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1602 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
1603 UINT8 CurrentAttemptConfigIndex
;
1604 ISCSI_NIC_INFO
*NicInfo
;
1606 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1607 UINT8
*AttemptConfigOrder
;
1608 UINTN AttemptConfigOrderSize
;
1613 // Free any attempt that is previously created but not saved to system.
1615 if (mPrivate
->NewAttempt
!= NULL
) {
1616 FreePool (mPrivate
->NewAttempt
);
1617 mPrivate
->NewAttempt
= NULL
;
1621 // Is User creating a new attempt?
1625 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
1626 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
1628 // User has pressed "Add an Attempt" and then selects a NIC.
1631 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
1632 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
1635 // User has pressed "Attempt *".
1640 // Don't process anything.
1647 // Determine which NIC user has selected for the new created attempt.
1649 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
1650 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
1651 if (NicInfo
== NULL
) {
1652 return EFI_NOT_FOUND
;
1656 // Create new attempt.
1659 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
1660 if (AttemptConfigData
== NULL
) {
1661 return EFI_OUT_OF_RESOURCES
;
1664 ConfigData
= &AttemptConfigData
->SessionConfigData
;
1665 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1666 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1667 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
1669 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
1670 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
1673 // Get current order number for this attempt.
1675 AttemptConfigOrder
= IScsiGetVariableAndSize (
1678 &AttemptConfigOrderSize
1681 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1683 if (AttemptConfigOrder
== NULL
) {
1684 CurrentAttemptConfigIndex
= 1;
1687 // Get the max attempt config index.
1689 CurrentAttemptConfigIndex
= AttemptConfigOrder
[0];
1690 for (Index
= 1; Index
< TotalNumber
; Index
++) {
1691 if (CurrentAttemptConfigIndex
< AttemptConfigOrder
[Index
]) {
1692 CurrentAttemptConfigIndex
= AttemptConfigOrder
[Index
];
1696 CurrentAttemptConfigIndex
++;
1702 // Record the mapping between attempt order and attempt's configdata.
1704 AttemptConfigData
->AttemptConfigIndex
= CurrentAttemptConfigIndex
;
1706 if (AttemptConfigOrder
!= NULL
) {
1707 FreePool (AttemptConfigOrder
);
1711 // Record the MAC info in Config Data.
1714 &NicInfo
->PermanentAddress
,
1715 NicInfo
->HwAddressSize
,
1720 UnicodeStrToAsciiStr (MacString
, AttemptConfigData
->MacString
);
1721 AttemptConfigData
->NicIndex
= NicIndex
;
1724 // Generate OUI-format ISID based on MAC address.
1726 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
1727 AttemptConfigData
->SessionConfigData
.IsId
[0] =
1728 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
1731 // Add the help info for the new attempt.
1734 mPrivate
->PortString
,
1735 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1736 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
1739 NicInfo
->DeviceNumber
,
1740 NicInfo
->FunctionNumber
1743 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
1744 mCallbackInfo
->RegisteredHandle
,
1746 mPrivate
->PortString
,
1749 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
1750 FreePool (AttemptConfigData
);
1751 return EFI_INVALID_PARAMETER
;
1755 // Set the attempt name to default.
1758 mPrivate
->PortString
,
1761 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1763 UnicodeStrToAsciiStr (mPrivate
->PortString
, AttemptConfigData
->AttemptName
);
1766 // Save the created Attempt temporarily. If user does not save the attempt
1767 // by press 'KEY_SAVE_ATTEMPT_CONFIG' later, iSCSI driver would know that
1768 // and free resources.
1770 mPrivate
->NewAttempt
= (VOID
*) AttemptConfigData
;
1774 // Determine which Attempt user has selected to configure.
1775 // Get the attempt configuration data.
1777 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
1779 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
1780 if (AttemptConfigData
== NULL
) {
1781 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
1782 return EFI_NOT_FOUND
;
1787 // Clear the old IFR data to avoid sharing it with other attempts.
1789 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1790 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
1791 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
1792 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
1793 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
1796 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
1799 // Update current attempt to be a new created attempt or an existing attempt.
1801 mCallbackInfo
->Current
= AttemptConfigData
;
1809 This function allows the caller to request the current
1810 configuration for one or more named elements. The resulting
1811 string is in <ConfigAltResp> format. Also, any and all alternative
1812 configuration strings shall be appended to the end of the
1813 current configuration string. If they are, they must appear
1814 after the current configuration. They must contain the same
1815 routing (GUID, NAME, PATH) as the current configuration string.
1816 They must have an additional description indicating the type of
1817 alternative configuration the string represents,
1818 "ALTCFG=<StringToken>". That <StringToken> (when
1819 converted from Hex UNICODE to binary) is a reference to a
1820 string in the associated string pack.
1822 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1824 @param[in] Request A null-terminated Unicode string in
1825 <ConfigRequest> format. Note that this
1826 includes the routing information as well as
1827 the configurable name / value pairs. It is
1828 invalid for this string to be in
1829 <MultiConfigRequest> format.
1831 @param[out] Progress On return, points to a character in the
1832 Request string. Points to the string's null
1833 terminator if request was successful. Points
1834 to the most recent "&" before the first
1835 failing name / value pair (or the beginning
1836 of the string if the failure is in the first
1837 name / value pair) if the request was not successful.
1839 @param[out] Results A null-terminated Unicode string in
1840 <ConfigAltResp> format which has all values
1841 filled in for the names in the Request string.
1842 String to be allocated by the called function.
1844 @retval EFI_SUCCESS The Results string is filled with the
1845 values corresponding to all requested
1848 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1849 parts of the results that must be
1850 stored awaiting possible future
1853 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
1854 for the Request parameter
1855 would result in this type of
1856 error. In this case, the
1857 Progress parameter would be
1860 @retval EFI_NOT_FOUND Routing data doesn't match any
1861 known driver. Progress set to the
1862 first character in the routing header.
1863 Note: There is no requirement that the
1864 driver validate the routing data. It
1865 must skip the <ConfigHdr> in order to
1868 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
1869 to most recent "&" before the
1870 error or the beginning of the
1873 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
1874 to the & before the name in
1880 IScsiFormExtractConfig (
1881 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1882 IN CONST EFI_STRING Request
,
1883 OUT EFI_STRING
*Progress
,
1884 OUT EFI_STRING
*Results
1888 CHAR8
*InitiatorName
;
1890 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
1891 ISCSI_FORM_CALLBACK_INFO
*Private
;
1892 EFI_STRING ConfigRequestHdr
;
1893 EFI_STRING ConfigRequest
;
1894 BOOLEAN AllocatedRequest
;
1897 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
1898 return EFI_INVALID_PARAMETER
;
1901 *Progress
= Request
;
1902 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &mVendorGuid
, mVendorStorageName
)) {
1903 return EFI_NOT_FOUND
;
1906 ConfigRequestHdr
= NULL
;
1907 ConfigRequest
= NULL
;
1908 AllocatedRequest
= FALSE
;
1911 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
1912 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
1913 if (IfrNvData
== NULL
) {
1914 return EFI_OUT_OF_RESOURCES
;
1917 if (Private
->Current
!= NULL
) {
1918 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
1921 BufferSize
= ISCSI_NAME_MAX_SIZE
;
1922 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
1923 if (InitiatorName
== NULL
) {
1924 FreePool (IfrNvData
);
1925 return EFI_OUT_OF_RESOURCES
;
1928 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
1929 if (EFI_ERROR (Status
)) {
1930 IfrNvData
->InitiatorName
[0] = L
'\0';
1932 AsciiStrToUnicodeStr (InitiatorName
, IfrNvData
->InitiatorName
);
1936 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
1938 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
1939 ConfigRequest
= Request
;
1940 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
1942 // Request has no request element, construct full request string.
1943 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1944 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
1946 ConfigRequestHdr
= HiiConstructConfigHdr (&mVendorGuid
, mVendorStorageName
, Private
->DriverHandle
);
1947 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
1948 ConfigRequest
= AllocateZeroPool (Size
);
1949 ASSERT (ConfigRequest
!= NULL
);
1950 AllocatedRequest
= TRUE
;
1951 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
1952 FreePool (ConfigRequestHdr
);
1955 Status
= gHiiConfigRouting
->BlockToConfig (
1958 (UINT8
*) IfrNvData
,
1963 FreePool (IfrNvData
);
1964 FreePool (InitiatorName
);
1967 // Free the allocated config request string.
1969 if (AllocatedRequest
) {
1970 FreePool (ConfigRequest
);
1971 ConfigRequest
= NULL
;
1974 // Set Progress string to the original request string.
1976 if (Request
== NULL
) {
1978 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
1979 *Progress
= Request
+ StrLen (Request
);
1988 This function applies changes in a driver's configuration.
1989 Input is a Configuration, which has the routing data for this
1990 driver followed by name / value configuration pairs. The driver
1991 must apply those pairs to its configurable storage. If the
1992 driver's configuration is stored in a linear block of data
1993 and the driver's name / value pairs are in <BlockConfig>
1994 format, it may use the ConfigToBlock helper function (above) to
1997 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1999 @param[in] Configuration A null-terminated Unicode string in
2000 <ConfigString> format.
2002 @param[out] Progress A pointer to a string filled in with the
2003 offset of the most recent '&' before the
2004 first failing name / value pair (or the
2005 beginning of the string if the failure
2006 is in the first name / value pair) or
2007 the terminating NULL if all was
2010 @retval EFI_SUCCESS The results have been distributed or are
2011 awaiting distribution.
2013 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2014 parts of the results that must be
2015 stored awaiting possible future
2018 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
2019 Results parameter would result
2020 in this type of error.
2022 @retval EFI_NOT_FOUND Target for the specified routing data
2028 IScsiFormRouteConfig (
2029 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2030 IN CONST EFI_STRING Configuration
,
2031 OUT EFI_STRING
*Progress
2034 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
2035 return EFI_INVALID_PARAMETER
;
2039 // Check routing data in <ConfigHdr>.
2040 // Note: if only one Storage is used, then this checking could be skipped.
2042 if (!HiiIsConfigHdrMatch (Configuration
, &mVendorGuid
, mVendorStorageName
)) {
2043 *Progress
= Configuration
;
2044 return EFI_NOT_FOUND
;
2047 *Progress
= Configuration
+ StrLen (Configuration
);
2054 This function is called to provide results data to the driver.
2055 This data consists of a unique key that is used to identify
2056 which data is either being passed back or being asked for.
2058 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2059 @param[in] Action Specifies the type of action taken by the browser.
2060 @param[in] QuestionId A unique value which is sent to the original
2061 exporting driver so that it can identify the type
2062 of data to expect. The format of the data tends to
2063 vary based on the opcode that generated the callback.
2064 @param[in] Type The type of value for the question.
2065 @param[in, out] Value A pointer to the data being sent to the original
2067 @param[out] ActionRequest On return, points to the action requested by the
2070 @retval EFI_SUCCESS The callback successfully handled the action.
2071 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2072 variable and its data.
2073 @retval EFI_DEVICE_ERROR The variable could not be saved.
2074 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2080 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2081 IN EFI_BROWSER_ACTION Action
,
2082 IN EFI_QUESTION_ID QuestionId
,
2084 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
2085 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2088 ISCSI_FORM_CALLBACK_INFO
*Private
;
2091 CHAR8 IpString
[IP_STR_MAX_SIZE
];
2092 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
2094 EFI_IP_ADDRESS HostIp
;
2095 EFI_IP_ADDRESS SubnetMask
;
2096 EFI_IP_ADDRESS Gateway
;
2097 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
2098 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
2100 CHAR16 AttemptName
[ATTEMPT_NAME_SIZE
+ 4];
2103 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
2105 // Do nothing for UEFI OPEN/CLOSE Action
2110 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2111 if (This
== NULL
|| Value
== NULL
|| ActionRequest
== NULL
) {
2112 return EFI_INVALID_PARAMETER
;
2115 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
2118 // Retrieve uncommitted data from Browser
2121 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2122 IfrNvData
= AllocateZeroPool (BufferSize
);
2123 if (IfrNvData
== NULL
) {
2124 return EFI_OUT_OF_RESOURCES
;
2127 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
2128 if (IScsiName
== NULL
) {
2129 FreePool (IfrNvData
);
2130 return EFI_OUT_OF_RESOURCES
;
2133 Status
= EFI_SUCCESS
;
2135 ZeroMem (&OldIfrNvData
, BufferSize
);
2137 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2139 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
2141 switch (QuestionId
) {
2142 case KEY_INITIATOR_NAME
:
2143 UnicodeStrToAsciiStr (IfrNvData
->InitiatorName
, IScsiName
);
2144 BufferSize
= AsciiStrSize (IScsiName
);
2146 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
2147 if (EFI_ERROR (Status
)) {
2149 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2151 L
"Invalid iSCSI Name!",
2156 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2159 case KEY_ADD_ATTEMPT
:
2160 Status
= IScsiConfigAddAttempt ();
2163 case KEY_DELETE_ATTEMPT
:
2165 OldIfrNvData
.DeleteAttemptList
,
2166 IfrNvData
->DeleteAttemptList
,
2167 sizeof (IfrNvData
->DeleteAttemptList
)
2169 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
2172 case KEY_SAVE_DELETE_ATTEMPT
:
2174 // Delete the Attempt Order from NVR
2176 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
2177 if (EFI_ERROR (Status
)) {
2181 IScsiConfigUpdateAttempt ();
2182 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2185 case KEY_IGNORE_DELETE_ATTEMPT
:
2187 IfrNvData
->DeleteAttemptList
,
2188 OldIfrNvData
.DeleteAttemptList
,
2189 sizeof (IfrNvData
->DeleteAttemptList
)
2191 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD
;
2194 case KEY_ORDER_ATTEMPT_CONFIG
:
2196 // Order the attempt according to user input.
2199 OldIfrNvData
.DynamicOrderedList
,
2200 IfrNvData
->DynamicOrderedList
,
2201 sizeof (IfrNvData
->DynamicOrderedList
)
2203 IScsiConfigDisplayOrderAttempts ();
2206 case KEY_SAVE_ORDER_CHANGES
:
2208 // Sync the Attempt Order to NVR.
2210 Status
= IScsiConfigOrderAttempts (IfrNvData
);
2211 if (EFI_ERROR (Status
)) {
2215 IScsiConfigUpdateAttempt ();
2216 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2219 case KEY_IGNORE_ORDER_CHANGES
:
2221 IfrNvData
->DynamicOrderedList
,
2222 OldIfrNvData
.DynamicOrderedList
,
2223 sizeof (IfrNvData
->DynamicOrderedList
)
2225 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD
;
2228 case KEY_ATTEMPT_NAME
:
2229 if (StrLen (IfrNvData
->AttemptName
) > ATTEMPT_NAME_SIZE
) {
2230 CopyMem (AttemptName
, IfrNvData
->AttemptName
, ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
2231 CopyMem (&AttemptName
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
2235 IfrNvData
->AttemptName
,
2236 (StrLen (IfrNvData
->AttemptName
) + 1) * sizeof (CHAR16
)
2240 UnicodeStrToAsciiStr (IfrNvData
->AttemptName
, Private
->Current
->AttemptName
);
2242 IScsiConfigUpdateAttempt ();
2244 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2248 switch (Value
->u8
) {
2250 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2251 IScsiIpToStr (&Private
->Current
->SessionConfigData
.TargetIp
, TRUE
, IfrNvData
->TargetIp
);
2252 Private
->Current
->AutoConfigureMode
= 0;
2256 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2257 IScsiIpToStr (&Private
->Current
->SessionConfigData
.TargetIp
, FALSE
, IfrNvData
->TargetIp
);
2258 Private
->Current
->AutoConfigureMode
= 0;
2266 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
2267 if (EFI_ERROR (Status
) || !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
2269 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2271 L
"Invalid IP address!",
2275 Status
= EFI_INVALID_PARAMETER
;
2277 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
2282 case KEY_SUBNET_MASK
:
2283 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
2284 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
2286 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2288 L
"Invalid Subnet Mask!",
2292 Status
= EFI_INVALID_PARAMETER
;
2294 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
2300 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
2301 if (EFI_ERROR (Status
) || ((Gateway
.Addr
[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), 0))) {
2303 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2305 L
"Invalid Gateway!",
2308 Status
= EFI_INVALID_PARAMETER
;
2310 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
2316 UnicodeStrToAsciiStr (IfrNvData
->TargetIp
, IpString
);
2317 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
2318 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
2320 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2322 L
"Invalid IP address!",
2325 Status
= EFI_INVALID_PARAMETER
;
2327 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
2332 case KEY_TARGET_NAME
:
2333 UnicodeStrToAsciiStr (IfrNvData
->TargetName
, IScsiName
);
2334 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
2335 if (EFI_ERROR (Status
)) {
2337 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2339 L
"Invalid iSCSI Name!",
2343 AsciiStrCpy (Private
->Current
->SessionConfigData
.TargetName
, IScsiName
);
2348 case KEY_DHCP_ENABLE
:
2349 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
2350 IfrNvData
->TargetInfoFromDhcp
= 0;
2356 UnicodeStrToAsciiStr (IfrNvData
->BootLun
, LunString
);
2357 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
2358 if (EFI_ERROR (Status
)) {
2360 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2362 L
"Invalid LUN string!",
2366 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
2372 switch (Value
->u8
) {
2373 case ISCSI_AUTH_TYPE_CHAP
:
2374 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
2383 UnicodeStrToAsciiStr (
2384 IfrNvData
->CHAPName
,
2385 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
2389 case KEY_CHAP_SECRET
:
2390 UnicodeStrToAsciiStr (
2391 IfrNvData
->CHAPSecret
,
2392 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
2396 case KEY_REVERSE_CHAP_NAME
:
2397 UnicodeStrToAsciiStr (
2398 IfrNvData
->ReverseCHAPName
,
2399 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
2403 case KEY_REVERSE_CHAP_SECRET
:
2404 UnicodeStrToAsciiStr (
2405 IfrNvData
->ReverseCHAPSecret
,
2406 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
2410 case KEY_CONFIG_ISID
:
2411 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2412 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2416 case KEY_SAVE_ATTEMPT_CONFIG
:
2417 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
2418 if (EFI_ERROR (Status
)) {
2422 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2426 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
2430 if (!EFI_ERROR (Status
)) {
2432 // Pass changed uncommitted data back to Form Browser.
2434 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2435 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2438 FreePool (IfrNvData
);
2439 FreePool (IScsiName
);
2445 // All other action return unsupported.
2447 return EFI_UNSUPPORTED
;
2452 Initialize the iSCSI configuration form.
2454 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2456 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
2457 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2461 IScsiConfigFormInit (
2462 IN EFI_HANDLE DriverBindingHandle
2466 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
2468 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
2469 if (CallbackInfo
== NULL
) {
2470 return EFI_OUT_OF_RESOURCES
;
2473 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
2474 CallbackInfo
->Current
= NULL
;
2476 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
2477 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
2478 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
2481 // Install Device Path Protocol and Config Access protocol to driver handle.
2483 Status
= gBS
->InstallMultipleProtocolInterfaces (
2484 &CallbackInfo
->DriverHandle
,
2485 &gEfiDevicePathProtocolGuid
,
2486 &mIScsiHiiVendorDevicePath
,
2487 &gEfiHiiConfigAccessProtocolGuid
,
2488 &CallbackInfo
->ConfigAccess
,
2491 ASSERT_EFI_ERROR (Status
);
2494 // Publish our HII data.
2496 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
2498 CallbackInfo
->DriverHandle
,
2503 if (CallbackInfo
->RegisteredHandle
== NULL
) {
2504 gBS
->UninstallMultipleProtocolInterfaces (
2505 &CallbackInfo
->DriverHandle
,
2506 &gEfiDevicePathProtocolGuid
,
2507 &mIScsiHiiVendorDevicePath
,
2508 &gEfiHiiConfigAccessProtocolGuid
,
2509 &CallbackInfo
->ConfigAccess
,
2512 FreePool(CallbackInfo
);
2513 return EFI_OUT_OF_RESOURCES
;
2516 mCallbackInfo
= CallbackInfo
;
2523 Unload the iSCSI configuration form, this includes: delete all the iSCSI
2524 configuration entries, uninstall the form callback protocol, and
2525 free the resources used.
2527 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2529 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
2530 @retval Others Failed to unload the form.
2534 IScsiConfigFormUnload (
2535 IN EFI_HANDLE DriverBindingHandle
2538 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2539 ISCSI_NIC_INFO
*NicInfo
;
2543 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
2544 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
2545 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2546 FreePool (AttemptConfigData
);
2547 mPrivate
->AttemptCount
--;
2550 ASSERT (mPrivate
->AttemptCount
== 0);
2552 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
2553 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
2554 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
2556 mPrivate
->NicCount
--;
2559 ASSERT (mPrivate
->NicCount
== 0);
2562 // Free attempt is created but not saved to system.
2564 if (mPrivate
->NewAttempt
!= NULL
) {
2565 FreePool (mPrivate
->NewAttempt
);
2568 FreePool (mPrivate
);
2572 // Remove HII package list.
2574 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
2577 // Uninstall Device Path Protocol and Config Access protocol.
2579 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2580 mCallbackInfo
->DriverHandle
,
2581 &gEfiDevicePathProtocolGuid
,
2582 &mIScsiHiiVendorDevicePath
,
2583 &gEfiHiiConfigAccessProtocolGuid
,
2584 &mCallbackInfo
->ConfigAccess
,
2588 FreePool (mCallbackInfo
);