2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "IScsiImpl.h"
17 CHAR16 mVendorStorageName
[] = L
"ISCSI_CONFIG_IFR_NVDATA";
18 BOOLEAN mIScsiDeviceListUpdated
= FALSE
;
19 UINTN mNumberOfIScsiDevices
= 0;
20 ISCSI_FORM_CALLBACK_INFO
*mCallbackInfo
= NULL
;
22 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath
= {
28 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
29 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
36 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
38 (UINT8
) (END_DEVICE_PATH_LENGTH
),
39 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
46 Convert the IP address into a dotted string.
48 @param[in] Ip The IP address.
49 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.
50 @param[out] Str The formatted IP string.
55 IN EFI_IP_ADDRESS
*Ip
,
60 EFI_IPv4_ADDRESS
*Ip4
;
61 EFI_IPv6_ADDRESS
*Ip6
;
65 CHAR16 FormatString
[8];
72 (UINTN
) 2 * IP4_STR_MAX_SIZE
,
86 for (Index
= 0; Index
< 15; Index
= Index
+ 2) {
89 Ip6
->Addr
[Index
] == 0 &&
90 Ip6
->Addr
[Index
+ 1] == 0
93 // Deal with the case of ::.
104 while ((Index
< 15) && (Ip6
->Addr
[Index
] == 0) && (Ip6
->Addr
[Index
+ 1] == 0)) {
112 // :: is at the end of the address.
121 if (Ip6
->Addr
[Index
] == 0) {
122 Number
= UnicodeSPrint (Str
, 2 * IP_STR_MAX_SIZE
, L
"%x:", (UINTN
) Ip6
->Addr
[Index
+ 1]);
124 if (Ip6
->Addr
[Index
+ 1] < 0x10) {
125 CopyMem (FormatString
, L
"%x0%x:", StrSize (L
"%x0%x:"));
127 CopyMem (FormatString
, L
"%x%x:", StrSize (L
"%x%x:"));
130 Number
= UnicodeSPrint (
133 (CONST CHAR16
*) FormatString
,
134 (UINTN
) Ip6
->Addr
[Index
],
135 (UINTN
) Ip6
->Addr
[Index
+ 1]
141 if (Index
+ 2 == 16) {
143 if (*(Str
- 1) == L
':') {
151 Check whether the input IP address is valid.
153 @param[in] Ip The IP address.
154 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.
156 @retval TRUE The input IP address is valid.
157 @retval FALSE Otherwise
162 IN EFI_IP_ADDRESS
*Ip
,
166 if (IpMode
== IP_MODE_IP4
) {
167 return NetIp4IsUnicast (NTOHL (Ip
->Addr
[0]), 0);
168 } else if (IpMode
== IP_MODE_IP6
) {
169 return NetIp6IsValidUnicast (&Ip
->v6
);
171 DEBUG ((DEBUG_ERROR
, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode
));
177 Parse IsId in string format and convert it to binary.
179 @param[in] String The buffer of the string to be parsed.
180 @param[in, out] IsId The buffer to store IsId.
182 @retval EFI_SUCCESS The operation finished successfully.
183 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
187 IScsiParseIsIdFromString (
188 IN CONST CHAR16
*String
,
196 CHAR16 PortString
[ISCSI_NAME_IFR_MAX_SIZE
];
199 if ((String
== NULL
) || (IsId
== NULL
)) {
200 return EFI_INVALID_PARAMETER
;
203 IsIdStr
= (CHAR16
*) String
;
205 if (StrLen (IsIdStr
) != 6) {
208 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
209 L
"Error! Input is incorrect, please input 6 hex numbers!\n"
213 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
219 return EFI_INVALID_PARAMETER
;
222 for (Index
= 3; Index
< 6; Index
++) {
223 CopyMem (TempStr
, IsIdStr
, sizeof (TempStr
));
227 // Convert the string to IsId. StrHexToUintn stops at the first character
228 // that is not a valid hex character, '\0' here.
230 NodeVal
= StrHexToUintn (TempStr
);
232 IsId
[Index
] = (UINT8
) NodeVal
;
234 IsIdStr
= IsIdStr
+ 2;
241 Convert IsId from binary to string format.
243 @param[out] String The buffer to store the converted string.
244 @param[in] IsId The buffer to store IsId.
246 @retval EFI_SUCCESS The string converted successfully.
247 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
251 IScsiConvertIsIdToString (
259 if ((String
== NULL
) || (IsId
== NULL
)) {
260 return EFI_INVALID_PARAMETER
;
263 for (Index
= 0; Index
< 6; Index
++) {
264 if (IsId
[Index
] <= 0xF) {
265 Number
= UnicodeSPrint (
267 2 * ISID_CONFIGURABLE_STORAGE
,
272 Number
= UnicodeSPrint (
274 2 * ISID_CONFIGURABLE_STORAGE
,
281 String
= String
+ Number
;
290 Get the attempt config data from global structure by the ConfigIndex.
292 @param[in] AttemptConfigIndex The unique index indicates the attempt.
294 @return Pointer to the attempt config data.
295 @retval NULL The attempt configuration data cannot be found.
298 ISCSI_ATTEMPT_CONFIG_NVDATA
*
299 IScsiConfigGetAttemptByConfigIndex (
300 IN UINT8 AttemptConfigIndex
304 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
306 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
307 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
308 if (Attempt
->AttemptConfigIndex
== AttemptConfigIndex
) {
318 Get the existing attempt config data from global structure by the NicIndex.
320 @param[in] NewAttempt The created new attempt
321 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
324 @return Pointer to the existing attempt config data which
325 has the same NICIndex as the new created attempt.
326 @retval NULL The attempt with NicIndex does not exist.
329 ISCSI_ATTEMPT_CONFIG_NVDATA
*
330 IScsiConfigGetAttemptByNic (
331 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*NewAttempt
,
336 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
338 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
339 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
340 if (Attempt
!= NewAttempt
&& Attempt
->NicIndex
== NewAttempt
->NicIndex
&&
341 Attempt
->SessionConfigData
.Enabled
== IScsiMode
) {
351 Convert the iSCSI configuration data into the IFR data.
353 @param[in] Attempt The iSCSI attempt config data.
354 @param[in, out] IfrNvData The IFR nv data.
358 IScsiConvertAttemptConfigDataToIfrNvData (
359 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
,
360 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
363 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
364 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
368 // Normal session configuration parameters.
370 SessionConfigData
= &Attempt
->SessionConfigData
;
371 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
372 IfrNvData
->IpMode
= SessionConfigData
->IpMode
;
374 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
375 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
376 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
378 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
379 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
380 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->LocalIp
);
381 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
382 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->SubnetMask
);
383 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
384 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Gateway
);
385 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
386 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->TargetIp
);
387 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
388 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
389 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
390 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->TargetIp
);
393 AsciiStrToUnicodeStr (SessionConfigData
->TargetName
, IfrNvData
->TargetName
);
394 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
395 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
397 IfrNvData
->ConnectRetryCount
= SessionConfigData
->ConnectRetryCount
;
398 IfrNvData
->ConnectTimeout
= SessionConfigData
->ConnectTimeout
;
401 // Authentication parameters.
403 IfrNvData
->AuthenticationType
= Attempt
->AuthenticationType
;
405 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
406 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
407 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
408 AsciiStrToUnicodeStr (AuthConfigData
->CHAPName
, IfrNvData
->CHAPName
);
409 AsciiStrToUnicodeStr (AuthConfigData
->CHAPSecret
, IfrNvData
->CHAPSecret
);
410 AsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPName
, IfrNvData
->ReverseCHAPName
);
411 AsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPSecret
, IfrNvData
->ReverseCHAPSecret
);
417 AsciiStrToUnicodeStr (Attempt
->AttemptName
, IfrNvData
->AttemptName
);
421 Convert the IFR data to iSCSI configuration data.
423 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
424 @param[in, out] Attempt The iSCSI attempt config data.
426 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
427 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
428 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
429 @retval EFI_ABORTED The operation is aborted.
430 @retval EFI_SUCCESS The operation is completed successfully.
434 IScsiConvertIfrNvDataToAttemptConfigData (
435 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
436 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
439 EFI_IP_ADDRESS HostIp
;
440 EFI_IP_ADDRESS SubnetMask
;
441 EFI_IP_ADDRESS Gateway
;
443 CHAR16
*AttemptName1
;
444 CHAR16
*AttemptName2
;
445 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
446 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
447 CHAR16 IScsiMode
[64];
449 ISCSI_NIC_INFO
*NicInfo
;
451 UINT8
*AttemptConfigOrder
;
452 UINTN AttemptConfigOrderSize
;
453 UINT8
*AttemptOrderTmp
;
457 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
458 return EFI_INVALID_PARAMETER
;
462 // Update those fields which don't have INTERACTIVE attribute.
464 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
465 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
466 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
468 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
469 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
470 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
472 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
473 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
476 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
479 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
481 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
482 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
486 // Only do full parameter validation if iSCSI is enabled on this device.
488 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
489 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
491 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
493 L
"Connection Establishing Timeout is less than minimum value 100ms.",
497 return EFI_INVALID_PARAMETER
;
501 // Validate the address configuration of the Initiator if DHCP isn't
504 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
505 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
506 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
507 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
509 if ((Gateway
.Addr
[0] != 0)) {
510 if (SubnetMask
.Addr
[0] == 0) {
512 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
514 L
"Gateway address is set but subnet mask is zero.",
518 return EFI_INVALID_PARAMETER
;
519 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
521 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
523 L
"Local IP and Gateway are not in the same subnet.",
527 return EFI_INVALID_PARAMETER
;
532 // Validate target configuration if DHCP isn't deployed.
534 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
535 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
537 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
539 L
"Target IP is invalid!",
542 return EFI_INVALID_PARAMETER
;
546 // Validate the authentication info.
548 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
549 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
551 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
553 L
"CHAP Name or CHAP Secret is invalid!",
557 return EFI_INVALID_PARAMETER
;
560 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
561 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
564 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
566 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
569 return EFI_INVALID_PARAMETER
;
574 // Check whether this attempt uses NIC which is already used by existing attempt.
576 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
577 if (SameNicAttempt
!= NULL
) {
578 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
579 if (AttemptName1
== NULL
) {
580 return EFI_OUT_OF_RESOURCES
;
583 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
584 if (AttemptName2
== NULL
) {
585 FreePool (AttemptName1
);
586 return EFI_OUT_OF_RESOURCES
;
589 AsciiStrToUnicodeStr (Attempt
->AttemptName
, AttemptName1
);
590 if (StrLen (AttemptName1
) > ATTEMPT_NAME_SIZE
) {
591 CopyMem (&AttemptName1
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
594 AsciiStrToUnicodeStr (SameNicAttempt
->AttemptName
, AttemptName2
);
595 if (StrLen (AttemptName2
) > ATTEMPT_NAME_SIZE
) {
596 CopyMem (&AttemptName2
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
600 mPrivate
->PortString
,
601 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
602 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
608 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
610 mPrivate
->PortString
,
614 FreePool (AttemptName1
);
615 FreePool (AttemptName2
);
620 // Update the iSCSI Mode data and record it in attempt help info.
622 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
623 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
624 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
625 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
626 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
627 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
628 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
631 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
632 UnicodeSPrint (IpMode
, 64, L
"IP4");
633 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
634 UnicodeSPrint (IpMode
, 64, L
"IP6");
635 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
636 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
639 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
640 if (NicInfo
== NULL
) {
641 return EFI_NOT_FOUND
;
644 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
645 if (MacString
== NULL
) {
646 return EFI_OUT_OF_RESOURCES
;
649 AsciiStrToUnicodeStr (Attempt
->MacString
, MacString
);
652 mPrivate
->PortString
,
653 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
654 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
657 NicInfo
->DeviceNumber
,
658 NicInfo
->FunctionNumber
,
663 Attempt
->AttemptTitleHelpToken
= HiiSetString (
664 mCallbackInfo
->RegisteredHandle
,
665 Attempt
->AttemptTitleHelpToken
,
666 mPrivate
->PortString
,
669 if (Attempt
->AttemptTitleHelpToken
== 0) {
670 FreePool (MacString
);
671 return EFI_OUT_OF_RESOURCES
;
675 // Check whether this attempt is an existing one.
677 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
678 if (ExistAttempt
!= NULL
) {
679 ASSERT (ExistAttempt
== Attempt
);
681 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
682 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
685 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
687 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
688 if (mPrivate
->MpioCount
< 1) {
692 if (--mPrivate
->MpioCount
== 0) {
693 mPrivate
->EnableMpio
= FALSE
;
695 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
696 if (mPrivate
->SinglePathCount
< 1) {
699 mPrivate
->SinglePathCount
--;
702 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
703 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
705 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
707 if (mPrivate
->SinglePathCount
< 1) {
711 mPrivate
->EnableMpio
= TRUE
;
712 mPrivate
->MpioCount
++;
713 mPrivate
->SinglePathCount
--;
715 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
716 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
718 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
720 if (mPrivate
->MpioCount
< 1) {
724 if (--mPrivate
->MpioCount
== 0) {
725 mPrivate
->EnableMpio
= FALSE
;
727 mPrivate
->SinglePathCount
++;
729 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
730 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
732 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
734 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
735 mPrivate
->EnableMpio
= TRUE
;
736 mPrivate
->MpioCount
++;
738 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
739 mPrivate
->SinglePathCount
++;
743 } else if (ExistAttempt
== NULL
) {
745 // When a new attempt is created, pointer of the attempt is saved to
746 // mPrivate->NewAttempt, and also saved to mCallbackInfo->Current in
747 // IScsiConfigProcessDefault. If input Attempt does not match any existing
748 // attempt, it should be a new created attempt. Save it to system now.
750 ASSERT (Attempt
== mPrivate
->NewAttempt
);
753 // Save current order number for this attempt.
755 AttemptConfigOrder
= IScsiGetVariableAndSize (
758 &AttemptConfigOrderSize
761 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
765 // Append the new created attempt order to the end.
767 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
768 if (AttemptOrderTmp
== NULL
) {
769 if (AttemptConfigOrder
!= NULL
) {
770 FreePool (AttemptConfigOrder
);
772 return EFI_OUT_OF_RESOURCES
;
775 if (AttemptConfigOrder
!= NULL
) {
776 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
777 FreePool (AttemptConfigOrder
);
780 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
781 AttemptConfigOrder
= AttemptOrderTmp
;
782 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
784 Status
= gRT
->SetVariable (
787 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
788 AttemptConfigOrderSize
,
791 FreePool (AttemptConfigOrder
);
792 if (EFI_ERROR (Status
)) {
797 // Insert new created attempt to array.
799 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
800 mPrivate
->AttemptCount
++;
802 // Reset mPrivate->NewAttempt to NULL, which indicates none attempt is created
803 // but not saved now.
805 mPrivate
->NewAttempt
= NULL
;
807 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
809 // This new Attempt is enabled for MPIO; enable the multipath mode.
811 mPrivate
->EnableMpio
= TRUE
;
812 mPrivate
->MpioCount
++;
813 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
814 mPrivate
->SinglePathCount
++;
817 IScsiConfigUpdateAttempt ();
821 // Record the user configuration information in NVR.
824 mPrivate
->PortString
,
825 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
828 (UINTN
) Attempt
->AttemptConfigIndex
831 FreePool (MacString
);
833 return gRT
->SetVariable (
834 mPrivate
->PortString
,
835 &gEfiIScsiInitiatorNameProtocolGuid
,
836 ISCSI_CONFIG_VAR_ATTR
,
837 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
843 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
846 @param[in] StartLabelNumber The number of start label.
847 @param[out] StartOpCodeHandle Points to the start opcode handle.
848 @param[out] StartLabel Points to the created start opcode.
849 @param[out] EndOpCodeHandle Points to the end opcode handle.
850 @param[out] EndLabel Points to the created end opcode.
852 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
854 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
855 @retval EFI_SUCCESS The operation is completed successfully.
860 IN UINT16 StartLabelNumber
,
861 OUT VOID
**StartOpCodeHandle
,
862 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
863 OUT VOID
**EndOpCodeHandle
,
864 OUT EFI_IFR_GUID_LABEL
**EndLabel
868 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
869 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
871 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
872 return EFI_INVALID_PARAMETER
;
875 *StartOpCodeHandle
= NULL
;
876 *EndOpCodeHandle
= NULL
;
877 Status
= EFI_OUT_OF_RESOURCES
;
880 // Initialize the container for dynamic opcodes.
882 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
883 if (*StartOpCodeHandle
== NULL
) {
887 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
888 if (*EndOpCodeHandle
== NULL
) {
893 // Create Hii Extend Label OpCode as the start opcode.
895 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
899 sizeof (EFI_IFR_GUID_LABEL
)
901 if (InternalStartLabel
== NULL
) {
905 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
906 InternalStartLabel
->Number
= StartLabelNumber
;
909 // Create Hii Extend Label OpCode as the end opcode.
911 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
915 sizeof (EFI_IFR_GUID_LABEL
)
917 if (InternalEndLabel
== NULL
) {
921 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
922 InternalEndLabel
->Number
= LABEL_END
;
924 *StartLabel
= InternalStartLabel
;
925 *EndLabel
= InternalEndLabel
;
931 if (*StartOpCodeHandle
!= NULL
) {
932 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
935 if (*EndOpCodeHandle
!= NULL
) {
936 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
943 Callback function when user presses "Add an Attempt".
945 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
947 @retval EFI_SUCCESS The operation is completed successfully.
951 IScsiConfigAddAttempt (
956 ISCSI_NIC_INFO
*NicInfo
;
957 EFI_STRING_ID PortTitleToken
;
958 EFI_STRING_ID PortTitleHelpToken
;
959 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
961 VOID
*StartOpCodeHandle
;
962 EFI_IFR_GUID_LABEL
*StartLabel
;
963 VOID
*EndOpCodeHandle
;
964 EFI_IFR_GUID_LABEL
*EndLabel
;
966 Status
= IScsiCreateOpCode (
973 if (EFI_ERROR (Status
)) {
978 // Ask user to select a MAC for this attempt.
980 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
981 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
983 &NicInfo
->PermanentAddress
,
984 NicInfo
->HwAddressSize
,
989 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
990 PortTitleToken
= HiiSetString (
991 mCallbackInfo
->RegisteredHandle
,
993 mPrivate
->PortString
,
996 if (PortTitleToken
== 0) {
997 Status
= EFI_INVALID_PARAMETER
;
1002 mPrivate
->PortString
,
1003 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1004 L
"PFA: Bus %d | Dev %d | Func %d",
1006 NicInfo
->DeviceNumber
,
1007 NicInfo
->FunctionNumber
1009 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
1010 if (PortTitleHelpToken
== 0) {
1011 Status
= EFI_INVALID_PARAMETER
;
1015 HiiCreateGotoOpCode (
1016 StartOpCodeHandle
, // Container for dynamic created opcodes
1017 FORMID_ATTEMPT_FORM
,
1020 EFI_IFR_FLAG_CALLBACK
, // Question flag
1021 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
1025 Status
= HiiUpdateForm (
1026 mCallbackInfo
->RegisteredHandle
, // HII handle
1027 &gIScsiConfigGuid
, // Formset GUID
1028 FORMID_MAC_FORM
, // Form ID
1029 StartOpCodeHandle
, // Label for where to insert opcodes
1030 EndOpCodeHandle
// Replace data
1034 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1035 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1042 Update the MAIN form to display the configured attempts.
1046 IScsiConfigUpdateAttempt (
1050 CHAR16 AttemptName
[ATTEMPT_NAME_MAX_SIZE
];
1052 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1053 VOID
*StartOpCodeHandle
;
1054 EFI_IFR_GUID_LABEL
*StartLabel
;
1055 VOID
*EndOpCodeHandle
;
1056 EFI_IFR_GUID_LABEL
*EndLabel
;
1059 Status
= IScsiCreateOpCode (
1060 ATTEMPT_ENTRY_LABEL
,
1066 if (EFI_ERROR (Status
)) {
1070 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1071 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1073 AsciiStrToUnicodeStr (AttemptConfigData
->AttemptName
, AttemptName
);
1074 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) 128, L
"Attempt %s", AttemptName
);
1075 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1076 mCallbackInfo
->RegisteredHandle
,
1078 mPrivate
->PortString
,
1081 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1085 HiiCreateGotoOpCode (
1086 StartOpCodeHandle
, // Container for dynamic created opcodes
1087 FORMID_ATTEMPT_FORM
, // Form ID
1088 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1089 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1090 EFI_IFR_FLAG_CALLBACK
, // Question flag
1091 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1096 mCallbackInfo
->RegisteredHandle
, // HII handle
1097 &gIScsiConfigGuid
, // Formset GUID
1098 FORMID_MAIN_FORM
, // Form ID
1099 StartOpCodeHandle
, // Label for where to insert opcodes
1100 EndOpCodeHandle
// Replace data
1103 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1104 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1109 Callback function when user presses "Commit Changes and Exit" in Delete Attempts.
1111 @param[in] IfrNvData The IFR NV data.
1113 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1114 @retval EFI_SUCCESS The operation is completed successfully.
1115 @retval EFI_ABOTRED This operation is aborted cause of error
1117 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
1122 IScsiConfigDeleteAttempts (
1123 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1129 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1130 UINT8
*AttemptConfigOrder
;
1131 UINTN AttemptConfigOrderSize
;
1132 UINT8
*AttemptNewOrder
;
1137 LIST_ENTRY
*NextEntry
;
1138 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1140 AttemptConfigOrder
= IScsiGetVariableAndSize (
1143 &AttemptConfigOrderSize
1145 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
1146 return EFI_NOT_FOUND
;
1149 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
1150 if (AttemptNewOrder
== NULL
) {
1151 Status
= EFI_OUT_OF_RESOURCES
;
1155 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1159 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
1160 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
1166 // Delete the attempt.
1169 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1170 if (AttemptConfigData
== NULL
) {
1171 Status
= EFI_NOT_FOUND
;
1176 // Remove this attempt from UI configured attempt list.
1178 RemoveEntryList (&AttemptConfigData
->Link
);
1179 mPrivate
->AttemptCount
--;
1181 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1182 if (mPrivate
->MpioCount
< 1) {
1183 Status
= EFI_ABORTED
;
1188 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
1190 if (--mPrivate
->MpioCount
== 0) {
1191 mPrivate
->EnableMpio
= FALSE
;
1193 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1194 if (mPrivate
->SinglePathCount
< 1) {
1195 Status
= EFI_ABORTED
;
1199 mPrivate
->SinglePathCount
--;
1202 AsciiStrToUnicodeStr (AttemptConfigData
->MacString
, MacString
);
1205 mPrivate
->PortString
,
1209 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1213 mPrivate
->PortString
,
1214 &gEfiIScsiInitiatorNameProtocolGuid
,
1221 // Mark the attempt order in NVR to be deleted - 0.
1223 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
1224 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
1225 AttemptConfigOrder
[NewIndex
] = 0;
1231 FreePool (AttemptConfigData
);
1234 // Check next Attempt.
1240 // Construct AttemptNewOrder.
1242 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
1243 if (AttemptConfigOrder
[Index
] != 0) {
1244 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
1249 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
1250 | EFI_VARIABLE_NON_VOLATILE
;
1253 // Update AttemptOrder in NVR.
1255 Status
= gRT
->SetVariable (
1259 NewTotal
* sizeof (UINT8
),
1264 if (AttemptConfigOrder
!= NULL
) {
1265 FreePool (AttemptConfigOrder
);
1268 if (AttemptNewOrder
!= NULL
) {
1269 FreePool (AttemptNewOrder
);
1277 Callback function when user presses "Delete Attempts".
1279 @param[in] IfrNvData The IFR nv data.
1281 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1282 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
1283 @retval EFI_SUCCESS The operation is completed successfully.
1287 IScsiConfigDisplayDeleteAttempts (
1288 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1292 UINT8
*AttemptConfigOrder
;
1293 UINTN AttemptConfigOrderSize
;
1295 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1297 VOID
*StartOpCodeHandle
;
1298 EFI_IFR_GUID_LABEL
*StartLabel
;
1299 VOID
*EndOpCodeHandle
;
1300 EFI_IFR_GUID_LABEL
*EndLabel
;
1303 Status
= IScsiCreateOpCode (
1310 if (EFI_ERROR (Status
)) {
1314 AttemptConfigOrder
= IScsiGetVariableAndSize (
1317 &AttemptConfigOrderSize
1319 if (AttemptConfigOrder
!= NULL
) {
1321 // Create the check box opcode to be deleted.
1325 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1326 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1327 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
1329 HiiCreateCheckBoxOpCode(
1331 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
1332 CONFIGURATION_VARSTORE_ID
,
1333 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
1334 AttemptConfigData
->AttemptTitleToken
,
1335 AttemptConfigData
->AttemptTitleHelpToken
,
1343 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
1348 FreePool (AttemptConfigOrder
);
1351 Status
= HiiUpdateForm (
1352 mCallbackInfo
->RegisteredHandle
, // HII handle
1353 &gIScsiConfigGuid
, // Formset GUID
1354 FORMID_DELETE_FORM
, // Form ID
1355 StartOpCodeHandle
, // Label for where to insert opcodes
1356 EndOpCodeHandle
// Replace data
1359 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1360 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1367 Callback function when user presses "Change Attempt Order".
1369 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1370 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1372 @retval EFI_SUCCESS The operation is completed successfully.
1376 IScsiConfigDisplayOrderAttempts (
1383 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1384 VOID
*StartOpCodeHandle
;
1385 EFI_IFR_GUID_LABEL
*StartLabel
;
1386 VOID
*EndOpCodeHandle
;
1387 EFI_IFR_GUID_LABEL
*EndLabel
;
1388 VOID
*OptionsOpCodeHandle
;
1390 Status
= IScsiCreateOpCode (
1397 if (EFI_ERROR (Status
)) {
1400 ASSERT (StartOpCodeHandle
!= NULL
);
1402 OptionsOpCodeHandle
= NULL
;
1405 // If no attempt to be ordered, update the original form and exit.
1407 if (mPrivate
->AttemptCount
== 0) {
1412 // Create Option OpCode.
1414 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
1415 if (OptionsOpCodeHandle
== NULL
) {
1416 Status
= EFI_OUT_OF_RESOURCES
;
1422 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1423 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1424 HiiCreateOneOfOptionOpCode (
1425 OptionsOpCodeHandle
,
1426 AttemptConfigData
->AttemptTitleToken
,
1428 EFI_IFR_NUMERIC_SIZE_1
,
1429 AttemptConfigData
->AttemptConfigIndex
1434 ASSERT (Index
== mPrivate
->AttemptCount
);
1436 HiiCreateOrderedListOpCode (
1437 StartOpCodeHandle
, // Container for dynamic created opcodes
1438 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
1439 CONFIGURATION_VARSTORE_ID
, // VarStore ID
1440 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
1441 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
1442 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
1444 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1445 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
1446 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
1447 OptionsOpCodeHandle
, // Option Opcode list
1448 NULL
// Default Opcode is NULL
1452 Status
= HiiUpdateForm (
1453 mCallbackInfo
->RegisteredHandle
, // HII handle
1454 &gIScsiConfigGuid
, // Formset GUID
1455 FORMID_ORDER_FORM
, // Form ID
1456 StartOpCodeHandle
, // Label for where to insert opcodes
1457 EndOpCodeHandle
// Replace data
1461 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1462 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1463 if (OptionsOpCodeHandle
!= NULL
) {
1464 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
1472 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order.
1474 @param[in] IfrNvData The IFR nv data.
1476 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1478 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1479 @retval EFI_SUCCESS The operation is completed successfully.
1483 IScsiConfigOrderAttempts (
1484 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1490 UINT8 AttemptConfigIndex
;
1491 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1492 UINT8
*AttemptConfigOrder
;
1493 UINT8
*AttemptConfigOrderTmp
;
1494 UINTN AttemptConfigOrderSize
;
1496 AttemptConfigOrder
= IScsiGetVariableAndSize (
1499 &AttemptConfigOrderSize
1501 if (AttemptConfigOrder
== NULL
) {
1502 return EFI_NOT_FOUND
;
1505 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
1506 if (AttemptConfigOrderTmp
== NULL
) {
1507 Status
= EFI_OUT_OF_RESOURCES
;
1511 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
1513 // The real content ends with 0.
1515 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
1519 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
1520 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
1521 if (AttemptConfigData
== NULL
) {
1522 Status
= EFI_NOT_FOUND
;
1527 // Reorder the Attempt List.
1529 RemoveEntryList (&AttemptConfigData
->Link
);
1530 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
1532 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
1535 // Mark it to be deleted - 0.
1537 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1538 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
1539 AttemptConfigOrder
[Indexj
] = 0;
1546 // Adjust the attempt order in NVR.
1548 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
1549 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1550 if (AttemptConfigOrder
[Indexj
] != 0) {
1551 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
1552 AttemptConfigOrder
[Indexj
] = 0;
1558 Status
= gRT
->SetVariable (
1561 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1562 AttemptConfigOrderSize
,
1563 AttemptConfigOrderTmp
1567 if (AttemptConfigOrderTmp
!= NULL
) {
1568 FreePool (AttemptConfigOrderTmp
);
1571 FreePool (AttemptConfigOrder
);
1577 Callback function when a user presses "Attempt *" or when a user selects a NIC to
1578 create the new attempt.
1580 @param[in] KeyValue A unique value which is sent to the original
1581 exporting driver so that it can identify the type
1583 @param[in] IfrNvData The IFR nv data.
1585 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1587 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1588 @retval EFI_SUCCESS The operation is completed successfully.
1592 IScsiConfigProcessDefault (
1593 IN EFI_QUESTION_ID KeyValue
,
1594 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1598 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1599 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
1600 UINT8 CurrentAttemptConfigIndex
;
1601 ISCSI_NIC_INFO
*NicInfo
;
1603 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1604 UINT8
*AttemptConfigOrder
;
1605 UINTN AttemptConfigOrderSize
;
1610 // Is User creating a new attempt?
1614 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
1615 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
1617 // User has pressed "Add an Attempt" and then selects a NIC.
1620 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
1621 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
1624 // User has pressed "Attempt *".
1629 // Don't process anything.
1635 // Free any attempt that is previously created but not saved to system.
1637 if (mPrivate
->NewAttempt
!= NULL
) {
1638 FreePool (mPrivate
->NewAttempt
);
1639 mPrivate
->NewAttempt
= NULL
;
1644 // Determine which NIC user has selected for the new created attempt.
1646 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
1647 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
1648 if (NicInfo
== NULL
) {
1649 return EFI_NOT_FOUND
;
1653 // Create new attempt.
1656 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
1657 if (AttemptConfigData
== NULL
) {
1658 return EFI_OUT_OF_RESOURCES
;
1661 ConfigData
= &AttemptConfigData
->SessionConfigData
;
1662 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1663 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1664 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
1666 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
1667 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
1670 // Get current order number for this attempt.
1672 AttemptConfigOrder
= IScsiGetVariableAndSize (
1675 &AttemptConfigOrderSize
1678 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1680 if (AttemptConfigOrder
== NULL
) {
1681 CurrentAttemptConfigIndex
= 1;
1684 // Get the max attempt config index.
1686 CurrentAttemptConfigIndex
= AttemptConfigOrder
[0];
1687 for (Index
= 1; Index
< TotalNumber
; Index
++) {
1688 if (CurrentAttemptConfigIndex
< AttemptConfigOrder
[Index
]) {
1689 CurrentAttemptConfigIndex
= AttemptConfigOrder
[Index
];
1693 CurrentAttemptConfigIndex
++;
1699 // Record the mapping between attempt order and attempt's configdata.
1701 AttemptConfigData
->AttemptConfigIndex
= CurrentAttemptConfigIndex
;
1703 if (AttemptConfigOrder
!= NULL
) {
1704 FreePool (AttemptConfigOrder
);
1708 // Record the MAC info in Config Data.
1711 &NicInfo
->PermanentAddress
,
1712 NicInfo
->HwAddressSize
,
1717 UnicodeStrToAsciiStr (MacString
, AttemptConfigData
->MacString
);
1718 AttemptConfigData
->NicIndex
= NicIndex
;
1721 // Generate OUI-format ISID based on MAC address.
1723 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
1724 AttemptConfigData
->SessionConfigData
.IsId
[0] =
1725 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
1728 // Add the help info for the new attempt.
1731 mPrivate
->PortString
,
1732 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1733 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
1736 NicInfo
->DeviceNumber
,
1737 NicInfo
->FunctionNumber
1740 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
1741 mCallbackInfo
->RegisteredHandle
,
1743 mPrivate
->PortString
,
1746 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
1747 FreePool (AttemptConfigData
);
1748 return EFI_INVALID_PARAMETER
;
1752 // Set the attempt name to default.
1755 mPrivate
->PortString
,
1758 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1760 UnicodeStrToAsciiStr (mPrivate
->PortString
, AttemptConfigData
->AttemptName
);
1763 // Save the created Attempt temporarily. If user does not save the attempt
1764 // by press 'KEY_SAVE_ATTEMPT_CONFIG' later, iSCSI driver would know that
1765 // and free resources.
1767 mPrivate
->NewAttempt
= (VOID
*) AttemptConfigData
;
1771 // Determine which Attempt user has selected to configure.
1772 // Get the attempt configuration data.
1774 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
1776 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
1777 if (AttemptConfigData
== NULL
) {
1778 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
1779 return EFI_NOT_FOUND
;
1784 // Clear the old IFR data to avoid sharing it with other attempts.
1786 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1787 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
1788 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
1789 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
1790 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
1793 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
1796 // Update current attempt to be a new created attempt or an existing attempt.
1798 mCallbackInfo
->Current
= AttemptConfigData
;
1806 This function allows the caller to request the current
1807 configuration for one or more named elements. The resulting
1808 string is in <ConfigAltResp> format. Also, any and all alternative
1809 configuration strings shall be appended to the end of the
1810 current configuration string. If they are, they must appear
1811 after the current configuration. They must contain the same
1812 routing (GUID, NAME, PATH) as the current configuration string.
1813 They must have an additional description indicating the type of
1814 alternative configuration the string represents,
1815 "ALTCFG=<StringToken>". That <StringToken> (when
1816 converted from Hex UNICODE to binary) is a reference to a
1817 string in the associated string pack.
1819 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1821 @param[in] Request A null-terminated Unicode string in
1822 <ConfigRequest> format. Note that this
1823 includes the routing information as well as
1824 the configurable name / value pairs. It is
1825 invalid for this string to be in
1826 <MultiConfigRequest> format.
1828 @param[out] Progress On return, points to a character in the
1829 Request string. Points to the string's null
1830 terminator if request was successful. Points
1831 to the most recent "&" before the first
1832 failing name / value pair (or the beginning
1833 of the string if the failure is in the first
1834 name / value pair) if the request was not successful.
1836 @param[out] Results A null-terminated Unicode string in
1837 <ConfigAltResp> format which has all values
1838 filled in for the names in the Request string.
1839 String to be allocated by the called function.
1841 @retval EFI_SUCCESS The Results string is filled with the
1842 values corresponding to all requested
1845 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1846 parts of the results that must be
1847 stored awaiting possible future
1850 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
1851 for the Request parameter
1852 would result in this type of
1853 error. In this case, the
1854 Progress parameter would be
1857 @retval EFI_NOT_FOUND Routing data doesn't match any
1858 known driver. Progress set to the
1859 first character in the routing header.
1860 Note: There is no requirement that the
1861 driver validate the routing data. It
1862 must skip the <ConfigHdr> in order to
1865 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
1866 to most recent "&" before the
1867 error or the beginning of the
1870 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
1871 to the & before the name in
1877 IScsiFormExtractConfig (
1878 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1879 IN CONST EFI_STRING Request
,
1880 OUT EFI_STRING
*Progress
,
1881 OUT EFI_STRING
*Results
1885 CHAR8
*InitiatorName
;
1887 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
1888 ISCSI_FORM_CALLBACK_INFO
*Private
;
1889 EFI_STRING ConfigRequestHdr
;
1890 EFI_STRING ConfigRequest
;
1891 BOOLEAN AllocatedRequest
;
1894 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
1895 return EFI_INVALID_PARAMETER
;
1898 *Progress
= Request
;
1899 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
1900 return EFI_NOT_FOUND
;
1903 ConfigRequestHdr
= NULL
;
1904 ConfigRequest
= NULL
;
1905 AllocatedRequest
= FALSE
;
1908 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
1909 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
1910 if (IfrNvData
== NULL
) {
1911 return EFI_OUT_OF_RESOURCES
;
1914 if (Private
->Current
!= NULL
) {
1915 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
1918 BufferSize
= ISCSI_NAME_MAX_SIZE
;
1919 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
1920 if (InitiatorName
== NULL
) {
1921 FreePool (IfrNvData
);
1922 return EFI_OUT_OF_RESOURCES
;
1925 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
1926 if (EFI_ERROR (Status
)) {
1927 IfrNvData
->InitiatorName
[0] = L
'\0';
1929 AsciiStrToUnicodeStr (InitiatorName
, IfrNvData
->InitiatorName
);
1933 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
1935 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
1936 ConfigRequest
= Request
;
1937 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
1939 // Request has no request element, construct full request string.
1940 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1941 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
1943 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
1944 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
1945 ConfigRequest
= AllocateZeroPool (Size
);
1946 ASSERT (ConfigRequest
!= NULL
);
1947 AllocatedRequest
= TRUE
;
1948 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
1949 FreePool (ConfigRequestHdr
);
1952 Status
= gHiiConfigRouting
->BlockToConfig (
1955 (UINT8
*) IfrNvData
,
1960 FreePool (IfrNvData
);
1961 FreePool (InitiatorName
);
1964 // Free the allocated config request string.
1966 if (AllocatedRequest
) {
1967 FreePool (ConfigRequest
);
1968 ConfigRequest
= NULL
;
1971 // Set Progress string to the original request string.
1973 if (Request
== NULL
) {
1975 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
1976 *Progress
= Request
+ StrLen (Request
);
1985 This function applies changes in a driver's configuration.
1986 Input is a Configuration, which has the routing data for this
1987 driver followed by name / value configuration pairs. The driver
1988 must apply those pairs to its configurable storage. If the
1989 driver's configuration is stored in a linear block of data
1990 and the driver's name / value pairs are in <BlockConfig>
1991 format, it may use the ConfigToBlock helper function (above) to
1994 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1996 @param[in] Configuration A null-terminated Unicode string in
1997 <ConfigString> format.
1999 @param[out] Progress A pointer to a string filled in with the
2000 offset of the most recent '&' before the
2001 first failing name / value pair (or the
2002 beginning of the string if the failure
2003 is in the first name / value pair) or
2004 the terminating NULL if all was
2007 @retval EFI_SUCCESS The results have been distributed or are
2008 awaiting distribution.
2010 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2011 parts of the results that must be
2012 stored awaiting possible future
2015 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
2016 Results parameter would result
2017 in this type of error.
2019 @retval EFI_NOT_FOUND Target for the specified routing data
2025 IScsiFormRouteConfig (
2026 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2027 IN CONST EFI_STRING Configuration
,
2028 OUT EFI_STRING
*Progress
2031 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
2032 return EFI_INVALID_PARAMETER
;
2036 // Check routing data in <ConfigHdr>.
2037 // Note: if only one Storage is used, then this checking could be skipped.
2039 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
2040 *Progress
= Configuration
;
2041 return EFI_NOT_FOUND
;
2044 *Progress
= Configuration
+ StrLen (Configuration
);
2051 This function is called to provide results data to the driver.
2052 This data consists of a unique key that is used to identify
2053 which data is either being passed back or being asked for.
2055 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2056 @param[in] Action Specifies the type of action taken by the browser.
2057 @param[in] QuestionId A unique value which is sent to the original
2058 exporting driver so that it can identify the type
2059 of data to expect. The format of the data tends to
2060 vary based on the opcode that generated the callback.
2061 @param[in] Type The type of value for the question.
2062 @param[in, out] Value A pointer to the data being sent to the original
2064 @param[out] ActionRequest On return, points to the action requested by the
2067 @retval EFI_SUCCESS The callback successfully handled the action.
2068 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2069 variable and its data.
2070 @retval EFI_DEVICE_ERROR The variable could not be saved.
2071 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2077 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2078 IN EFI_BROWSER_ACTION Action
,
2079 IN EFI_QUESTION_ID QuestionId
,
2081 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
2082 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2085 ISCSI_FORM_CALLBACK_INFO
*Private
;
2088 CHAR8 IpString
[IP_STR_MAX_SIZE
];
2089 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
2091 EFI_IP_ADDRESS HostIp
;
2092 EFI_IP_ADDRESS SubnetMask
;
2093 EFI_IP_ADDRESS Gateway
;
2094 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
2095 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
2097 CHAR16 AttemptName
[ATTEMPT_NAME_SIZE
+ 4];
2100 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
2102 // Do nothing for UEFI OPEN/CLOSE Action
2107 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
2109 // All other type return unsupported.
2111 return EFI_UNSUPPORTED
;
2114 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
2115 return EFI_INVALID_PARAMETER
;
2118 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
2121 // Retrieve uncommitted data from Browser
2124 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2125 IfrNvData
= AllocateZeroPool (BufferSize
);
2126 if (IfrNvData
== NULL
) {
2127 return EFI_OUT_OF_RESOURCES
;
2130 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
2131 if (IScsiName
== NULL
) {
2132 FreePool (IfrNvData
);
2133 return EFI_OUT_OF_RESOURCES
;
2136 Status
= EFI_SUCCESS
;
2138 ZeroMem (&OldIfrNvData
, BufferSize
);
2140 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2142 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
2144 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2145 switch (QuestionId
) {
2146 case KEY_ADD_ATTEMPT
:
2147 Status
= IScsiConfigAddAttempt ();
2150 case KEY_DELETE_ATTEMPT
:
2152 OldIfrNvData
.DeleteAttemptList
,
2153 IfrNvData
->DeleteAttemptList
,
2154 sizeof (IfrNvData
->DeleteAttemptList
)
2156 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
2159 case KEY_ORDER_ATTEMPT_CONFIG
:
2161 // Order the attempt according to user input.
2164 OldIfrNvData
.DynamicOrderedList
,
2165 IfrNvData
->DynamicOrderedList
,
2166 sizeof (IfrNvData
->DynamicOrderedList
)
2168 IScsiConfigDisplayOrderAttempts ();
2172 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
2175 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2176 switch (QuestionId
) {
2177 case KEY_INITIATOR_NAME
:
2178 UnicodeStrToAsciiStr (IfrNvData
->InitiatorName
, IScsiName
);
2179 BufferSize
= AsciiStrSize (IScsiName
);
2181 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
2182 if (EFI_ERROR (Status
)) {
2184 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2186 L
"Invalid iSCSI Name!",
2191 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2193 case KEY_ATTEMPT_NAME
:
2194 if (StrLen (IfrNvData
->AttemptName
) > ATTEMPT_NAME_SIZE
) {
2195 CopyMem (AttemptName
, IfrNvData
->AttemptName
, ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
2196 CopyMem (&AttemptName
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
2200 IfrNvData
->AttemptName
,
2201 (StrLen (IfrNvData
->AttemptName
) + 1) * sizeof (CHAR16
)
2205 UnicodeStrToAsciiStr (IfrNvData
->AttemptName
, Private
->Current
->AttemptName
);
2207 IScsiConfigUpdateAttempt ();
2209 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2212 case KEY_SAVE_ATTEMPT_CONFIG
:
2213 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
2214 if (EFI_ERROR (Status
)) {
2218 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2221 case KEY_SAVE_ORDER_CHANGES
:
2223 // Sync the Attempt Order to NVR.
2225 Status
= IScsiConfigOrderAttempts (IfrNvData
);
2226 if (EFI_ERROR (Status
)) {
2230 IScsiConfigUpdateAttempt ();
2231 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
2234 case KEY_IGNORE_ORDER_CHANGES
:
2236 IfrNvData
->DynamicOrderedList
,
2237 OldIfrNvData
.DynamicOrderedList
,
2238 sizeof (IfrNvData
->DynamicOrderedList
)
2240 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
2243 case KEY_SAVE_DELETE_ATTEMPT
:
2245 // Delete the Attempt Order from NVR
2247 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
2248 if (EFI_ERROR (Status
)) {
2252 IScsiConfigUpdateAttempt ();
2253 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
2256 case KEY_IGNORE_DELETE_ATTEMPT
:
2258 IfrNvData
->DeleteAttemptList
,
2259 OldIfrNvData
.DeleteAttemptList
,
2260 sizeof (IfrNvData
->DeleteAttemptList
)
2262 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
2266 switch (Value
->u8
) {
2268 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2269 IScsiIpToStr (&Private
->Current
->SessionConfigData
.TargetIp
, TRUE
, IfrNvData
->TargetIp
);
2270 Private
->Current
->AutoConfigureMode
= 0;
2274 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2275 IScsiIpToStr (&Private
->Current
->SessionConfigData
.TargetIp
, FALSE
, IfrNvData
->TargetIp
);
2276 Private
->Current
->AutoConfigureMode
= 0;
2284 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
2285 if (EFI_ERROR (Status
) || !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
2287 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2289 L
"Invalid IP address!",
2293 Status
= EFI_INVALID_PARAMETER
;
2295 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
2300 case KEY_SUBNET_MASK
:
2301 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
2302 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
2304 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2306 L
"Invalid Subnet Mask!",
2310 Status
= EFI_INVALID_PARAMETER
;
2312 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
2318 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
2319 if (EFI_ERROR (Status
) || ((Gateway
.Addr
[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), 0))) {
2321 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2323 L
"Invalid Gateway!",
2326 Status
= EFI_INVALID_PARAMETER
;
2328 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
2334 UnicodeStrToAsciiStr (IfrNvData
->TargetIp
, IpString
);
2335 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
2336 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
2338 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2340 L
"Invalid IP address!",
2343 Status
= EFI_INVALID_PARAMETER
;
2345 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
2350 case KEY_TARGET_NAME
:
2351 UnicodeStrToAsciiStr (IfrNvData
->TargetName
, IScsiName
);
2352 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
2353 if (EFI_ERROR (Status
)) {
2355 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2357 L
"Invalid iSCSI Name!",
2361 AsciiStrCpy (Private
->Current
->SessionConfigData
.TargetName
, IScsiName
);
2366 case KEY_DHCP_ENABLE
:
2367 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
2368 IfrNvData
->TargetInfoFromDhcp
= 0;
2374 UnicodeStrToAsciiStr (IfrNvData
->BootLun
, LunString
);
2375 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
2376 if (EFI_ERROR (Status
)) {
2378 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2380 L
"Invalid LUN string!",
2384 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
2390 switch (Value
->u8
) {
2391 case ISCSI_AUTH_TYPE_CHAP
:
2392 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
2401 UnicodeStrToAsciiStr (
2402 IfrNvData
->CHAPName
,
2403 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
2407 case KEY_CHAP_SECRET
:
2408 UnicodeStrToAsciiStr (
2409 IfrNvData
->CHAPSecret
,
2410 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
2414 case KEY_REVERSE_CHAP_NAME
:
2415 UnicodeStrToAsciiStr (
2416 IfrNvData
->ReverseCHAPName
,
2417 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
2421 case KEY_REVERSE_CHAP_SECRET
:
2422 UnicodeStrToAsciiStr (
2423 IfrNvData
->ReverseCHAPSecret
,
2424 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
2428 case KEY_CONFIG_ISID
:
2429 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2430 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2439 if (!EFI_ERROR (Status
)) {
2441 // Pass changed uncommitted data back to Form Browser.
2443 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2444 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2447 FreePool (IfrNvData
);
2448 FreePool (IScsiName
);
2455 Initialize the iSCSI configuration form.
2457 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2459 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
2460 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2464 IScsiConfigFormInit (
2465 IN EFI_HANDLE DriverBindingHandle
2469 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
2471 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
2472 if (CallbackInfo
== NULL
) {
2473 return EFI_OUT_OF_RESOURCES
;
2476 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
2477 CallbackInfo
->Current
= NULL
;
2479 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
2480 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
2481 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
2484 // Install Device Path Protocol and Config Access protocol to driver handle.
2486 Status
= gBS
->InstallMultipleProtocolInterfaces (
2487 &CallbackInfo
->DriverHandle
,
2488 &gEfiDevicePathProtocolGuid
,
2489 &mIScsiHiiVendorDevicePath
,
2490 &gEfiHiiConfigAccessProtocolGuid
,
2491 &CallbackInfo
->ConfigAccess
,
2494 ASSERT_EFI_ERROR (Status
);
2497 // Publish our HII data.
2499 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
2501 CallbackInfo
->DriverHandle
,
2506 if (CallbackInfo
->RegisteredHandle
== NULL
) {
2507 gBS
->UninstallMultipleProtocolInterfaces (
2508 &CallbackInfo
->DriverHandle
,
2509 &gEfiDevicePathProtocolGuid
,
2510 &mIScsiHiiVendorDevicePath
,
2511 &gEfiHiiConfigAccessProtocolGuid
,
2512 &CallbackInfo
->ConfigAccess
,
2515 FreePool(CallbackInfo
);
2516 return EFI_OUT_OF_RESOURCES
;
2519 mCallbackInfo
= CallbackInfo
;
2526 Unload the iSCSI configuration form, this includes: delete all the iSCSI
2527 configuration entries, uninstall the form callback protocol, and
2528 free the resources used.
2530 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2532 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
2533 @retval Others Failed to unload the form.
2537 IScsiConfigFormUnload (
2538 IN EFI_HANDLE DriverBindingHandle
2541 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2542 ISCSI_NIC_INFO
*NicInfo
;
2546 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
2547 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
2548 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2549 FreePool (AttemptConfigData
);
2550 mPrivate
->AttemptCount
--;
2553 ASSERT (mPrivate
->AttemptCount
== 0);
2555 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
2556 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
2557 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
2559 mPrivate
->NicCount
--;
2562 ASSERT (mPrivate
->NicCount
== 0);
2565 // Free attempt is created but not saved to system.
2567 if (mPrivate
->NewAttempt
!= NULL
) {
2568 FreePool (mPrivate
->NewAttempt
);
2571 FreePool (mPrivate
);
2575 // Remove HII package list.
2577 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
2580 // Uninstall Device Path Protocol and Config Access protocol.
2582 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2583 mCallbackInfo
->DriverHandle
,
2584 &gEfiDevicePathProtocolGuid
,
2585 &mIScsiHiiVendorDevicePath
,
2586 &gEfiHiiConfigAccessProtocolGuid
,
2587 &mCallbackInfo
->ConfigAccess
,
2591 FreePool (mCallbackInfo
);