2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "IScsiImpl.h"
17 CHAR16 mVendorStorageName
[] = L
"ISCSI_CONFIG_IFR_NVDATA";
18 BOOLEAN mIScsiDeviceListUpdated
= FALSE
;
19 UINTN mNumberOfIScsiDevices
= 0;
20 ISCSI_FORM_CALLBACK_INFO
*mCallbackInfo
= NULL
;
22 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath
= {
28 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
29 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
36 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
38 (UINT8
) (END_DEVICE_PATH_LENGTH
),
39 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
46 Convert the IP address into a dotted string.
48 @param[in] Ip The IP address.
49 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.
50 @param[out] Str The formatted IP string.
55 IN EFI_IP_ADDRESS
*Ip
,
60 EFI_IPv4_ADDRESS
*Ip4
;
61 EFI_IPv6_ADDRESS
*Ip6
;
65 CHAR16 FormatString
[8];
72 (UINTN
) 2 * IP4_STR_MAX_SIZE
,
86 for (Index
= 0; Index
< 15; Index
= Index
+ 2) {
89 Ip6
->Addr
[Index
] == 0 &&
90 Ip6
->Addr
[Index
+ 1] == 0
93 // Deal with the case of ::.
104 while ((Index
< 15) && (Ip6
->Addr
[Index
] == 0) && (Ip6
->Addr
[Index
+ 1] == 0)) {
112 // :: is at the end of the address.
121 if (Ip6
->Addr
[Index
] == 0) {
122 Number
= UnicodeSPrint (Str
, 2 * IP_STR_MAX_SIZE
, L
"%x:", (UINTN
) Ip6
->Addr
[Index
+ 1]);
124 if (Ip6
->Addr
[Index
+ 1] < 0x10) {
125 CopyMem (FormatString
, L
"%x0%x:", StrSize (L
"%x0%x:"));
127 CopyMem (FormatString
, L
"%x%x:", StrSize (L
"%x%x:"));
130 Number
= UnicodeSPrint (
133 (CONST CHAR16
*) FormatString
,
134 (UINTN
) Ip6
->Addr
[Index
],
135 (UINTN
) Ip6
->Addr
[Index
+ 1]
141 if (Index
+ 2 == 16) {
143 if (*(Str
- 1) == L
':') {
151 Check whether the input IP address is valid.
153 @param[in] Ip The IP address.
154 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.
156 @retval TRUE The input IP address is valid.
157 @retval FALSE Otherwise
162 IN EFI_IP_ADDRESS
*Ip
,
166 if (IpMode
== IP_MODE_IP4
) {
167 if (IP4_IS_UNSPECIFIED (NTOHL (Ip
->Addr
[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip
->Addr
[0]))) {
171 } else if (IpMode
== IP_MODE_IP6
) {
172 return NetIp6IsValidUnicast (&Ip
->v6
);
174 DEBUG ((DEBUG_ERROR
, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode
));
180 Parse IsId in string format and convert it to binary.
182 @param[in] String The buffer of the string to be parsed.
183 @param[in, out] IsId The buffer to store IsId.
185 @retval EFI_SUCCESS The operation finished successfully.
186 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
190 IScsiParseIsIdFromString (
191 IN CONST CHAR16
*String
,
199 CHAR16 PortString
[ISCSI_NAME_IFR_MAX_SIZE
];
202 if ((String
== NULL
) || (IsId
== NULL
)) {
203 return EFI_INVALID_PARAMETER
;
206 IsIdStr
= (CHAR16
*) String
;
208 if (StrLen (IsIdStr
) != 6) {
211 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
212 L
"Error! Input is incorrect, please input 6 hex numbers!\n"
216 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
222 return EFI_INVALID_PARAMETER
;
225 for (Index
= 3; Index
< 6; Index
++) {
226 CopyMem (TempStr
, IsIdStr
, sizeof (TempStr
));
230 // Convert the string to IsId. StrHexToUintn stops at the first character
231 // that is not a valid hex character, '\0' here.
233 NodeVal
= StrHexToUintn (TempStr
);
235 IsId
[Index
] = (UINT8
) NodeVal
;
237 IsIdStr
= IsIdStr
+ 2;
244 Convert IsId from binary to string format.
246 @param[out] String The buffer to store the converted string.
247 @param[in] IsId The buffer to store IsId.
249 @retval EFI_SUCCESS The string converted successfully.
250 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
254 IScsiConvertIsIdToString (
262 if ((String
== NULL
) || (IsId
== NULL
)) {
263 return EFI_INVALID_PARAMETER
;
266 for (Index
= 0; Index
< 6; Index
++) {
267 if (IsId
[Index
] <= 0xF) {
268 Number
= UnicodeSPrint (
270 2 * ISID_CONFIGURABLE_STORAGE
,
275 Number
= UnicodeSPrint (
277 2 * ISID_CONFIGURABLE_STORAGE
,
284 String
= String
+ Number
;
293 Get the attempt config data from global structure by the ConfigIndex.
295 @param[in] AttemptConfigIndex The unique index indicates the attempt.
297 @return Pointer to the attempt config data.
298 @retval NULL The attempt configuration data cannot be found.
301 ISCSI_ATTEMPT_CONFIG_NVDATA
*
302 IScsiConfigGetAttemptByConfigIndex (
303 IN UINT8 AttemptConfigIndex
307 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
309 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
310 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
311 if (Attempt
->AttemptConfigIndex
== AttemptConfigIndex
) {
321 Get the existing attempt config data from global structure by the NicIndex.
323 @param[in] NewAttempt The created new attempt
324 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
327 @return Pointer to the existing attempt config data which
328 has the same NICIndex as the new created attempt.
329 @retval NULL The attempt with NicIndex does not exist.
332 ISCSI_ATTEMPT_CONFIG_NVDATA
*
333 IScsiConfigGetAttemptByNic (
334 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*NewAttempt
,
339 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
341 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
342 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
343 if (Attempt
!= NewAttempt
&& Attempt
->NicIndex
== NewAttempt
->NicIndex
&&
344 Attempt
->SessionConfigData
.Enabled
== IScsiMode
) {
354 Convert the iSCSI configuration data into the IFR data.
356 @param[in] Attempt The iSCSI attempt config data.
357 @param[in, out] IfrNvData The IFR nv data.
361 IScsiConvertAttemptConfigDataToIfrNvData (
362 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
,
363 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
366 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
367 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
372 // Normal session configuration parameters.
374 SessionConfigData
= &Attempt
->SessionConfigData
;
375 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
376 IfrNvData
->IpMode
= SessionConfigData
->IpMode
;
377 DnsMode
= SessionConfigData
->DnsMode
;
379 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
380 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
381 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
383 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
384 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
385 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->LocalIp
);
386 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
387 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->SubnetMask
);
388 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
389 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Gateway
);
390 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
391 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
392 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->TargetIp
);
395 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
396 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
397 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
398 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
399 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->TargetIp
);
403 AsciiStrToUnicodeStrS (
404 SessionConfigData
->TargetName
,
405 IfrNvData
->TargetName
,
406 sizeof (IfrNvData
->TargetName
) / sizeof (IfrNvData
->TargetName
[0])
410 AsciiStrToUnicodeStrS (
411 SessionConfigData
->TargetUrl
,
413 sizeof (IfrNvData
->TargetIp
) / sizeof (IfrNvData
->TargetIp
[0])
417 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
418 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
420 IfrNvData
->ConnectRetryCount
= SessionConfigData
->ConnectRetryCount
;
421 IfrNvData
->ConnectTimeout
= SessionConfigData
->ConnectTimeout
;
424 // Authentication parameters.
426 IfrNvData
->AuthenticationType
= Attempt
->AuthenticationType
;
428 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
429 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
430 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
431 AsciiStrToUnicodeStrS (
432 AuthConfigData
->CHAPName
,
434 sizeof (IfrNvData
->CHAPName
) / sizeof (IfrNvData
->CHAPName
[0])
436 AsciiStrToUnicodeStrS (
437 AuthConfigData
->CHAPSecret
,
438 IfrNvData
->CHAPSecret
,
439 sizeof (IfrNvData
->CHAPSecret
) / sizeof (IfrNvData
->CHAPSecret
[0])
441 AsciiStrToUnicodeStrS (
442 AuthConfigData
->ReverseCHAPName
,
443 IfrNvData
->ReverseCHAPName
,
444 sizeof (IfrNvData
->ReverseCHAPName
) / sizeof (IfrNvData
->ReverseCHAPName
[0])
446 AsciiStrToUnicodeStrS (
447 AuthConfigData
->ReverseCHAPSecret
,
448 IfrNvData
->ReverseCHAPSecret
,
449 sizeof (IfrNvData
->ReverseCHAPSecret
) / sizeof (IfrNvData
->ReverseCHAPSecret
[0])
456 AsciiStrToUnicodeStrS (
457 Attempt
->AttemptName
,
458 IfrNvData
->AttemptName
,
459 sizeof (IfrNvData
->AttemptName
) / sizeof (IfrNvData
->AttemptName
[0])
464 Convert the IFR data to iSCSI configuration data.
466 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
467 @param[in, out] Attempt The iSCSI attempt config data.
469 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
470 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
471 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
472 @retval EFI_ABORTED The operation is aborted.
473 @retval EFI_SUCCESS The operation is completed successfully.
477 IScsiConvertIfrNvDataToAttemptConfigData (
478 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
479 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
482 EFI_IP_ADDRESS HostIp
;
483 EFI_IP_ADDRESS SubnetMask
;
484 EFI_IP_ADDRESS Gateway
;
486 CHAR16
*AttemptName1
;
487 CHAR16
*AttemptName2
;
488 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
489 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
490 CHAR16 IScsiMode
[64];
492 ISCSI_NIC_INFO
*NicInfo
;
494 UINT8
*AttemptConfigOrder
;
495 UINTN AttemptConfigOrderSize
;
496 UINT8
*AttemptOrderTmp
;
500 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
501 return EFI_INVALID_PARAMETER
;
505 // Update those fields which don't have INTERACTIVE attribute.
507 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
508 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
509 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
511 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
512 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
513 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
515 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
516 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
519 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
522 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
524 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
525 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
529 // Only do full parameter validation if iSCSI is enabled on this device.
531 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
532 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
534 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
536 L
"Connection Establishing Timeout is less than minimum value 100ms.",
540 return EFI_INVALID_PARAMETER
;
544 // Validate the address configuration of the Initiator if DHCP isn't
547 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
548 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
549 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
550 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
552 if ((Gateway
.Addr
[0] != 0)) {
553 if (SubnetMask
.Addr
[0] == 0) {
555 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
557 L
"Gateway address is set but subnet mask is zero.",
561 return EFI_INVALID_PARAMETER
;
562 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
564 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
566 L
"Local IP and Gateway are not in the same subnet.",
570 return EFI_INVALID_PARAMETER
;
575 // Validate target configuration if DHCP isn't deployed.
577 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
578 if (!Attempt
->SessionConfigData
.DnsMode
) {
579 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
581 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
583 L
"Target IP is invalid!",
586 return EFI_INVALID_PARAMETER
;
589 if (Attempt
->SessionConfigData
.TargetUrl
[0] == '\0') {
591 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
593 L
"iSCSI target Url should not be NULL!",
596 return EFI_INVALID_PARAMETER
;
601 // Validate iSCSI target name configuration again:
602 // The format of iSCSI target name is already verified in IScsiFormCallback() when
603 // user input the name; here we only check the case user does not input the name.
605 if (Attempt
->SessionConfigData
.TargetName
[0] == '\0') {
607 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
609 L
"iSCSI target name is NULL!",
612 return EFI_INVALID_PARAMETER
;
618 // Validate the authentication info.
620 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
621 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
623 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
625 L
"CHAP Name or CHAP Secret is invalid!",
629 return EFI_INVALID_PARAMETER
;
632 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
633 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
636 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
638 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
641 return EFI_INVALID_PARAMETER
;
646 // Check whether this attempt uses NIC which is already used by existing attempt.
648 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
649 if (SameNicAttempt
!= NULL
) {
650 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
651 if (AttemptName1
== NULL
) {
652 return EFI_OUT_OF_RESOURCES
;
655 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
656 if (AttemptName2
== NULL
) {
657 FreePool (AttemptName1
);
658 return EFI_OUT_OF_RESOURCES
;
661 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_MAX_SIZE
);
662 if (StrLen (AttemptName1
) > ATTEMPT_NAME_SIZE
) {
663 CopyMem (&AttemptName1
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
666 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_MAX_SIZE
);
667 if (StrLen (AttemptName2
) > ATTEMPT_NAME_SIZE
) {
668 CopyMem (&AttemptName2
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
672 mPrivate
->PortString
,
673 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
674 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
680 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
682 mPrivate
->PortString
,
686 FreePool (AttemptName1
);
687 FreePool (AttemptName2
);
692 // Update the iSCSI Mode data and record it in attempt help info.
694 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
695 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
696 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
697 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
698 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
699 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
700 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
703 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
704 UnicodeSPrint (IpMode
, 64, L
"IP4");
705 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
706 UnicodeSPrint (IpMode
, 64, L
"IP6");
707 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
708 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
711 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
712 if (NicInfo
== NULL
) {
713 return EFI_NOT_FOUND
;
716 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
717 if (MacString
== NULL
) {
718 return EFI_OUT_OF_RESOURCES
;
721 AsciiStrToUnicodeStrS (Attempt
->MacString
, MacString
, ISCSI_MAX_MAC_STRING_LEN
);
724 mPrivate
->PortString
,
725 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
726 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
729 NicInfo
->DeviceNumber
,
730 NicInfo
->FunctionNumber
,
735 Attempt
->AttemptTitleHelpToken
= HiiSetString (
736 mCallbackInfo
->RegisteredHandle
,
737 Attempt
->AttemptTitleHelpToken
,
738 mPrivate
->PortString
,
741 if (Attempt
->AttemptTitleHelpToken
== 0) {
742 FreePool (MacString
);
743 return EFI_OUT_OF_RESOURCES
;
747 // Check whether this attempt is an existing one.
749 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
750 if (ExistAttempt
!= NULL
) {
751 ASSERT (ExistAttempt
== Attempt
);
753 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
754 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
757 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
759 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
760 if (mPrivate
->MpioCount
< 1) {
764 if (--mPrivate
->MpioCount
== 0) {
765 mPrivate
->EnableMpio
= FALSE
;
767 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
768 if (mPrivate
->SinglePathCount
< 1) {
771 mPrivate
->SinglePathCount
--;
774 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
775 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
777 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
779 if (mPrivate
->SinglePathCount
< 1) {
783 mPrivate
->EnableMpio
= TRUE
;
784 mPrivate
->MpioCount
++;
785 mPrivate
->SinglePathCount
--;
787 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
788 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
790 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
792 if (mPrivate
->MpioCount
< 1) {
796 if (--mPrivate
->MpioCount
== 0) {
797 mPrivate
->EnableMpio
= FALSE
;
799 mPrivate
->SinglePathCount
++;
801 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
802 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
804 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
806 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
807 mPrivate
->EnableMpio
= TRUE
;
808 mPrivate
->MpioCount
++;
810 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
811 mPrivate
->SinglePathCount
++;
815 } else if (ExistAttempt
== NULL
) {
817 // When a new attempt is created, pointer of the attempt is saved to
818 // mPrivate->NewAttempt, and also saved to mCallbackInfo->Current in
819 // IScsiConfigProcessDefault. If input Attempt does not match any existing
820 // attempt, it should be a new created attempt. Save it to system now.
822 ASSERT (Attempt
== mPrivate
->NewAttempt
);
825 // Save current order number for this attempt.
827 AttemptConfigOrder
= IScsiGetVariableAndSize (
830 &AttemptConfigOrderSize
833 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
837 // Append the new created attempt order to the end.
839 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
840 if (AttemptOrderTmp
== NULL
) {
841 if (AttemptConfigOrder
!= NULL
) {
842 FreePool (AttemptConfigOrder
);
844 return EFI_OUT_OF_RESOURCES
;
847 if (AttemptConfigOrder
!= NULL
) {
848 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
849 FreePool (AttemptConfigOrder
);
852 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
853 AttemptConfigOrder
= AttemptOrderTmp
;
854 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
856 Status
= gRT
->SetVariable (
859 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
860 AttemptConfigOrderSize
,
863 FreePool (AttemptConfigOrder
);
864 if (EFI_ERROR (Status
)) {
869 // Insert new created attempt to array.
871 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
872 mPrivate
->AttemptCount
++;
874 // Reset mPrivate->NewAttempt to NULL, which indicates none attempt is created
875 // but not saved now.
877 mPrivate
->NewAttempt
= NULL
;
879 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
881 // This new Attempt is enabled for MPIO; enable the multipath mode.
883 mPrivate
->EnableMpio
= TRUE
;
884 mPrivate
->MpioCount
++;
885 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
886 mPrivate
->SinglePathCount
++;
889 IScsiConfigUpdateAttempt ();
893 // Record the user configuration information in NVR.
896 mPrivate
->PortString
,
897 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
900 (UINTN
) Attempt
->AttemptConfigIndex
903 FreePool (MacString
);
905 return gRT
->SetVariable (
906 mPrivate
->PortString
,
907 &gEfiIScsiInitiatorNameProtocolGuid
,
908 ISCSI_CONFIG_VAR_ATTR
,
909 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
915 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
918 @param[in] StartLabelNumber The number of start label.
919 @param[out] StartOpCodeHandle Points to the start opcode handle.
920 @param[out] StartLabel Points to the created start opcode.
921 @param[out] EndOpCodeHandle Points to the end opcode handle.
922 @param[out] EndLabel Points to the created end opcode.
924 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
926 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
927 @retval EFI_SUCCESS The operation is completed successfully.
932 IN UINT16 StartLabelNumber
,
933 OUT VOID
**StartOpCodeHandle
,
934 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
935 OUT VOID
**EndOpCodeHandle
,
936 OUT EFI_IFR_GUID_LABEL
**EndLabel
940 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
941 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
943 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
944 return EFI_INVALID_PARAMETER
;
947 *StartOpCodeHandle
= NULL
;
948 *EndOpCodeHandle
= NULL
;
949 Status
= EFI_OUT_OF_RESOURCES
;
952 // Initialize the container for dynamic opcodes.
954 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
955 if (*StartOpCodeHandle
== NULL
) {
959 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
960 if (*EndOpCodeHandle
== NULL
) {
965 // Create Hii Extend Label OpCode as the start opcode.
967 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
971 sizeof (EFI_IFR_GUID_LABEL
)
973 if (InternalStartLabel
== NULL
) {
977 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
978 InternalStartLabel
->Number
= StartLabelNumber
;
981 // Create Hii Extend Label OpCode as the end opcode.
983 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
987 sizeof (EFI_IFR_GUID_LABEL
)
989 if (InternalEndLabel
== NULL
) {
993 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
994 InternalEndLabel
->Number
= LABEL_END
;
996 *StartLabel
= InternalStartLabel
;
997 *EndLabel
= InternalEndLabel
;
1003 if (*StartOpCodeHandle
!= NULL
) {
1004 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
1007 if (*EndOpCodeHandle
!= NULL
) {
1008 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
1015 Callback function when user presses "Add an Attempt".
1017 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1019 @retval EFI_SUCCESS The operation is completed successfully.
1023 IScsiConfigAddAttempt (
1028 ISCSI_NIC_INFO
*NicInfo
;
1029 EFI_STRING_ID PortTitleToken
;
1030 EFI_STRING_ID PortTitleHelpToken
;
1031 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1033 VOID
*StartOpCodeHandle
;
1034 EFI_IFR_GUID_LABEL
*StartLabel
;
1035 VOID
*EndOpCodeHandle
;
1036 EFI_IFR_GUID_LABEL
*EndLabel
;
1038 Status
= IScsiCreateOpCode (
1045 if (EFI_ERROR (Status
)) {
1050 // Ask user to select a MAC for this attempt.
1052 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
1053 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
1055 &NicInfo
->PermanentAddress
,
1056 NicInfo
->HwAddressSize
,
1061 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
1062 PortTitleToken
= HiiSetString (
1063 mCallbackInfo
->RegisteredHandle
,
1065 mPrivate
->PortString
,
1068 if (PortTitleToken
== 0) {
1069 Status
= EFI_INVALID_PARAMETER
;
1074 mPrivate
->PortString
,
1075 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1076 L
"PFA: Bus %d | Dev %d | Func %d",
1078 NicInfo
->DeviceNumber
,
1079 NicInfo
->FunctionNumber
1081 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
1082 if (PortTitleHelpToken
== 0) {
1083 Status
= EFI_INVALID_PARAMETER
;
1087 HiiCreateGotoOpCode (
1088 StartOpCodeHandle
, // Container for dynamic created opcodes
1089 FORMID_ATTEMPT_FORM
,
1092 EFI_IFR_FLAG_CALLBACK
, // Question flag
1093 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
1097 Status
= HiiUpdateForm (
1098 mCallbackInfo
->RegisteredHandle
, // HII handle
1099 &gIScsiConfigGuid
, // Formset GUID
1100 FORMID_MAC_FORM
, // Form ID
1101 StartOpCodeHandle
, // Label for where to insert opcodes
1102 EndOpCodeHandle
// Replace data
1106 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1107 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1114 Update the MAIN form to display the configured attempts.
1118 IScsiConfigUpdateAttempt (
1122 CHAR16 AttemptName
[ATTEMPT_NAME_MAX_SIZE
];
1124 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1125 VOID
*StartOpCodeHandle
;
1126 EFI_IFR_GUID_LABEL
*StartLabel
;
1127 VOID
*EndOpCodeHandle
;
1128 EFI_IFR_GUID_LABEL
*EndLabel
;
1131 Status
= IScsiCreateOpCode (
1132 ATTEMPT_ENTRY_LABEL
,
1138 if (EFI_ERROR (Status
)) {
1142 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1143 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1145 AsciiStrToUnicodeStrS (AttemptConfigData
->AttemptName
, AttemptName
, ARRAY_SIZE (AttemptName
));
1146 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) 128, L
"Attempt %s", AttemptName
);
1147 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1148 mCallbackInfo
->RegisteredHandle
,
1150 mPrivate
->PortString
,
1153 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1157 HiiCreateGotoOpCode (
1158 StartOpCodeHandle
, // Container for dynamic created opcodes
1159 FORMID_ATTEMPT_FORM
, // Form ID
1160 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1161 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1162 EFI_IFR_FLAG_CALLBACK
, // Question flag
1163 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1168 mCallbackInfo
->RegisteredHandle
, // HII handle
1169 &gIScsiConfigGuid
, // Formset GUID
1170 FORMID_MAIN_FORM
, // Form ID
1171 StartOpCodeHandle
, // Label for where to insert opcodes
1172 EndOpCodeHandle
// Replace data
1175 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1176 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1181 Callback function when user presses "Commit Changes and Exit" in Delete Attempts.
1183 @param[in] IfrNvData The IFR NV data.
1185 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1186 @retval EFI_SUCCESS The operation is completed successfully.
1187 @retval EFI_ABOTRED This operation is aborted cause of error
1189 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
1194 IScsiConfigDeleteAttempts (
1195 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1201 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1202 UINT8
*AttemptConfigOrder
;
1203 UINTN AttemptConfigOrderSize
;
1204 UINT8
*AttemptNewOrder
;
1209 LIST_ENTRY
*NextEntry
;
1210 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1212 AttemptConfigOrder
= IScsiGetVariableAndSize (
1215 &AttemptConfigOrderSize
1217 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
1218 return EFI_NOT_FOUND
;
1221 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
1222 if (AttemptNewOrder
== NULL
) {
1223 Status
= EFI_OUT_OF_RESOURCES
;
1227 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1231 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
1232 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
1238 // Delete the attempt.
1241 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1242 if (AttemptConfigData
== NULL
) {
1243 Status
= EFI_NOT_FOUND
;
1248 // Remove this attempt from UI configured attempt list.
1250 RemoveEntryList (&AttemptConfigData
->Link
);
1251 mPrivate
->AttemptCount
--;
1253 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1254 if (mPrivate
->MpioCount
< 1) {
1255 Status
= EFI_ABORTED
;
1260 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
1262 if (--mPrivate
->MpioCount
== 0) {
1263 mPrivate
->EnableMpio
= FALSE
;
1265 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1266 if (mPrivate
->SinglePathCount
< 1) {
1267 Status
= EFI_ABORTED
;
1271 mPrivate
->SinglePathCount
--;
1274 AsciiStrToUnicodeStrS (AttemptConfigData
->MacString
, MacString
, ARRAY_SIZE (MacString
));
1277 mPrivate
->PortString
,
1281 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1285 mPrivate
->PortString
,
1286 &gEfiIScsiInitiatorNameProtocolGuid
,
1293 // Mark the attempt order in NVR to be deleted - 0.
1295 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
1296 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
1297 AttemptConfigOrder
[NewIndex
] = 0;
1303 FreePool (AttemptConfigData
);
1306 // Check next Attempt.
1312 // Construct AttemptNewOrder.
1314 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
1315 if (AttemptConfigOrder
[Index
] != 0) {
1316 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
1321 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
1324 // Update AttemptOrder in NVR.
1326 Status
= gRT
->SetVariable (
1330 NewTotal
* sizeof (UINT8
),
1335 if (AttemptConfigOrder
!= NULL
) {
1336 FreePool (AttemptConfigOrder
);
1339 if (AttemptNewOrder
!= NULL
) {
1340 FreePool (AttemptNewOrder
);
1348 Callback function when user presses "Delete Attempts".
1350 @param[in] IfrNvData The IFR nv data.
1352 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1353 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
1354 @retval EFI_SUCCESS The operation is completed successfully.
1358 IScsiConfigDisplayDeleteAttempts (
1359 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1363 UINT8
*AttemptConfigOrder
;
1364 UINTN AttemptConfigOrderSize
;
1366 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1368 VOID
*StartOpCodeHandle
;
1369 EFI_IFR_GUID_LABEL
*StartLabel
;
1370 VOID
*EndOpCodeHandle
;
1371 EFI_IFR_GUID_LABEL
*EndLabel
;
1374 Status
= IScsiCreateOpCode (
1381 if (EFI_ERROR (Status
)) {
1385 AttemptConfigOrder
= IScsiGetVariableAndSize (
1388 &AttemptConfigOrderSize
1390 if (AttemptConfigOrder
!= NULL
) {
1392 // Create the check box opcode to be deleted.
1396 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1397 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1398 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
1400 HiiCreateCheckBoxOpCode(
1402 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
1403 CONFIGURATION_VARSTORE_ID
,
1404 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
1405 AttemptConfigData
->AttemptTitleToken
,
1406 AttemptConfigData
->AttemptTitleHelpToken
,
1414 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
1419 FreePool (AttemptConfigOrder
);
1422 Status
= HiiUpdateForm (
1423 mCallbackInfo
->RegisteredHandle
, // HII handle
1424 &gIScsiConfigGuid
, // Formset GUID
1425 FORMID_DELETE_FORM
, // Form ID
1426 StartOpCodeHandle
, // Label for where to insert opcodes
1427 EndOpCodeHandle
// Replace data
1430 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1431 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1438 Callback function when user presses "Change Attempt Order".
1440 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1441 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1443 @retval EFI_SUCCESS The operation is completed successfully.
1447 IScsiConfigDisplayOrderAttempts (
1454 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1455 VOID
*StartOpCodeHandle
;
1456 EFI_IFR_GUID_LABEL
*StartLabel
;
1457 VOID
*EndOpCodeHandle
;
1458 EFI_IFR_GUID_LABEL
*EndLabel
;
1459 VOID
*OptionsOpCodeHandle
;
1461 Status
= IScsiCreateOpCode (
1468 if (EFI_ERROR (Status
)) {
1471 ASSERT (StartOpCodeHandle
!= NULL
);
1473 OptionsOpCodeHandle
= NULL
;
1476 // If no attempt to be ordered, update the original form and exit.
1478 if (mPrivate
->AttemptCount
== 0) {
1483 // Create Option OpCode.
1485 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
1486 if (OptionsOpCodeHandle
== NULL
) {
1487 Status
= EFI_OUT_OF_RESOURCES
;
1493 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1494 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1495 HiiCreateOneOfOptionOpCode (
1496 OptionsOpCodeHandle
,
1497 AttemptConfigData
->AttemptTitleToken
,
1499 EFI_IFR_NUMERIC_SIZE_1
,
1500 AttemptConfigData
->AttemptConfigIndex
1505 ASSERT (Index
== mPrivate
->AttemptCount
);
1507 HiiCreateOrderedListOpCode (
1508 StartOpCodeHandle
, // Container for dynamic created opcodes
1509 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
1510 CONFIGURATION_VARSTORE_ID
, // VarStore ID
1511 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
1512 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
1513 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
1515 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1516 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
1517 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
1518 OptionsOpCodeHandle
, // Option Opcode list
1519 NULL
// Default Opcode is NULL
1523 Status
= HiiUpdateForm (
1524 mCallbackInfo
->RegisteredHandle
, // HII handle
1525 &gIScsiConfigGuid
, // Formset GUID
1526 FORMID_ORDER_FORM
, // Form ID
1527 StartOpCodeHandle
, // Label for where to insert opcodes
1528 EndOpCodeHandle
// Replace data
1532 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1533 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1534 if (OptionsOpCodeHandle
!= NULL
) {
1535 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
1543 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order.
1545 @param[in] IfrNvData The IFR nv data.
1547 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1549 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1550 @retval EFI_SUCCESS The operation is completed successfully.
1554 IScsiConfigOrderAttempts (
1555 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1561 UINT8 AttemptConfigIndex
;
1562 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1563 UINT8
*AttemptConfigOrder
;
1564 UINT8
*AttemptConfigOrderTmp
;
1565 UINTN AttemptConfigOrderSize
;
1567 AttemptConfigOrder
= IScsiGetVariableAndSize (
1570 &AttemptConfigOrderSize
1572 if (AttemptConfigOrder
== NULL
) {
1573 return EFI_NOT_FOUND
;
1576 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
1577 if (AttemptConfigOrderTmp
== NULL
) {
1578 Status
= EFI_OUT_OF_RESOURCES
;
1582 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
1584 // The real content ends with 0.
1586 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
1590 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
1591 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
1592 if (AttemptConfigData
== NULL
) {
1593 Status
= EFI_NOT_FOUND
;
1598 // Reorder the Attempt List.
1600 RemoveEntryList (&AttemptConfigData
->Link
);
1601 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
1603 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
1606 // Mark it to be deleted - 0.
1608 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1609 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
1610 AttemptConfigOrder
[Indexj
] = 0;
1617 // Adjust the attempt order in NVR.
1619 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
1620 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1621 if (AttemptConfigOrder
[Indexj
] != 0) {
1622 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
1623 AttemptConfigOrder
[Indexj
] = 0;
1629 Status
= gRT
->SetVariable (
1632 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1633 AttemptConfigOrderSize
,
1634 AttemptConfigOrderTmp
1638 if (AttemptConfigOrderTmp
!= NULL
) {
1639 FreePool (AttemptConfigOrderTmp
);
1642 FreePool (AttemptConfigOrder
);
1648 Callback function when a user presses "Attempt *" or when a user selects a NIC to
1649 create the new attempt.
1651 @param[in] KeyValue A unique value which is sent to the original
1652 exporting driver so that it can identify the type
1654 @param[in] IfrNvData The IFR nv data.
1656 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1658 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1659 @retval EFI_SUCCESS The operation is completed successfully.
1663 IScsiConfigProcessDefault (
1664 IN EFI_QUESTION_ID KeyValue
,
1665 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1669 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1670 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
1671 UINT8 CurrentAttemptConfigIndex
;
1672 ISCSI_NIC_INFO
*NicInfo
;
1674 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1675 UINT8
*AttemptConfigOrder
;
1676 UINTN AttemptConfigOrderSize
;
1681 // Is User creating a new attempt?
1685 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
1686 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
1688 // User has pressed "Add an Attempt" and then selects a NIC.
1691 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
1692 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
1695 // User has pressed "Attempt *".
1700 // Don't process anything.
1706 // Free any attempt that is previously created but not saved to system.
1708 if (mPrivate
->NewAttempt
!= NULL
) {
1709 FreePool (mPrivate
->NewAttempt
);
1710 mPrivate
->NewAttempt
= NULL
;
1715 // Determine which NIC user has selected for the new created attempt.
1717 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
1718 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
1719 if (NicInfo
== NULL
) {
1720 return EFI_NOT_FOUND
;
1724 // Create new attempt.
1727 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
1728 if (AttemptConfigData
== NULL
) {
1729 return EFI_OUT_OF_RESOURCES
;
1732 ConfigData
= &AttemptConfigData
->SessionConfigData
;
1733 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1734 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1735 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
1737 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
1738 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
1741 // Get current order number for this attempt.
1743 AttemptConfigOrder
= IScsiGetVariableAndSize (
1746 &AttemptConfigOrderSize
1749 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1751 if (AttemptConfigOrder
== NULL
) {
1752 CurrentAttemptConfigIndex
= 1;
1755 // Get the max attempt config index.
1757 CurrentAttemptConfigIndex
= AttemptConfigOrder
[0];
1758 for (Index
= 1; Index
< TotalNumber
; Index
++) {
1759 if (CurrentAttemptConfigIndex
< AttemptConfigOrder
[Index
]) {
1760 CurrentAttemptConfigIndex
= AttemptConfigOrder
[Index
];
1764 CurrentAttemptConfigIndex
++;
1770 // Record the mapping between attempt order and attempt's configdata.
1772 AttemptConfigData
->AttemptConfigIndex
= CurrentAttemptConfigIndex
;
1774 if (AttemptConfigOrder
!= NULL
) {
1775 FreePool (AttemptConfigOrder
);
1779 // Record the MAC info in Config Data.
1782 &NicInfo
->PermanentAddress
,
1783 NicInfo
->HwAddressSize
,
1788 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, sizeof (AttemptConfigData
->MacString
));
1789 AttemptConfigData
->NicIndex
= NicIndex
;
1792 // Generate OUI-format ISID based on MAC address.
1794 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
1795 AttemptConfigData
->SessionConfigData
.IsId
[0] =
1796 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
1799 // Add the help info for the new attempt.
1802 mPrivate
->PortString
,
1803 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1804 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
1807 NicInfo
->DeviceNumber
,
1808 NicInfo
->FunctionNumber
1811 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
1812 mCallbackInfo
->RegisteredHandle
,
1814 mPrivate
->PortString
,
1817 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
1818 FreePool (AttemptConfigData
);
1819 return EFI_INVALID_PARAMETER
;
1823 // Set the attempt name to default.
1826 mPrivate
->PortString
,
1829 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1831 UnicodeStrToAsciiStrS (mPrivate
->PortString
, AttemptConfigData
->AttemptName
, sizeof (AttemptConfigData
->AttemptName
));
1834 // Save the created Attempt temporarily. If user does not save the attempt
1835 // by press 'KEY_SAVE_ATTEMPT_CONFIG' later, iSCSI driver would know that
1836 // and free resources.
1838 mPrivate
->NewAttempt
= (VOID
*) AttemptConfigData
;
1842 // Determine which Attempt user has selected to configure.
1843 // Get the attempt configuration data.
1845 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
1847 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
1848 if (AttemptConfigData
== NULL
) {
1849 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
1850 return EFI_NOT_FOUND
;
1855 // Clear the old IFR data to avoid sharing it with other attempts.
1857 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1858 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
1859 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
1860 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
1861 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
1864 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
1867 // Update current attempt to be a new created attempt or an existing attempt.
1869 mCallbackInfo
->Current
= AttemptConfigData
;
1877 This function allows the caller to request the current
1878 configuration for one or more named elements. The resulting
1879 string is in <ConfigAltResp> format. Also, any and all alternative
1880 configuration strings shall be appended to the end of the
1881 current configuration string. If they are, they must appear
1882 after the current configuration. They must contain the same
1883 routing (GUID, NAME, PATH) as the current configuration string.
1884 They must have an additional description indicating the type of
1885 alternative configuration the string represents,
1886 "ALTCFG=<StringToken>". That <StringToken> (when
1887 converted from Hex UNICODE to binary) is a reference to a
1888 string in the associated string pack.
1890 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1892 @param[in] Request A null-terminated Unicode string in
1893 <ConfigRequest> format. Note that this
1894 includes the routing information as well as
1895 the configurable name / value pairs. It is
1896 invalid for this string to be in
1897 <MultiConfigRequest> format.
1899 @param[out] Progress On return, points to a character in the
1900 Request string. Points to the string's null
1901 terminator if request was successful. Points
1902 to the most recent "&" before the first
1903 failing name / value pair (or the beginning
1904 of the string if the failure is in the first
1905 name / value pair) if the request was not successful.
1907 @param[out] Results A null-terminated Unicode string in
1908 <ConfigAltResp> format which has all values
1909 filled in for the names in the Request string.
1910 String to be allocated by the called function.
1912 @retval EFI_SUCCESS The Results string is filled with the
1913 values corresponding to all requested
1916 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1917 parts of the results that must be
1918 stored awaiting possible future
1921 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
1922 for the Request parameter
1923 would result in this type of
1924 error. In this case, the
1925 Progress parameter would be
1928 @retval EFI_NOT_FOUND Routing data doesn't match any
1929 known driver. Progress set to the
1930 first character in the routing header.
1931 Note: There is no requirement that the
1932 driver validate the routing data. It
1933 must skip the <ConfigHdr> in order to
1936 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
1937 to most recent "&" before the
1938 error or the beginning of the
1941 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
1942 to the & before the name in
1948 IScsiFormExtractConfig (
1949 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1950 IN CONST EFI_STRING Request
,
1951 OUT EFI_STRING
*Progress
,
1952 OUT EFI_STRING
*Results
1956 CHAR8
*InitiatorName
;
1958 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
1959 ISCSI_FORM_CALLBACK_INFO
*Private
;
1960 EFI_STRING ConfigRequestHdr
;
1961 EFI_STRING ConfigRequest
;
1962 BOOLEAN AllocatedRequest
;
1965 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
1966 return EFI_INVALID_PARAMETER
;
1969 *Progress
= Request
;
1970 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
1971 return EFI_NOT_FOUND
;
1974 ConfigRequestHdr
= NULL
;
1975 ConfigRequest
= NULL
;
1976 AllocatedRequest
= FALSE
;
1979 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
1980 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
1981 if (IfrNvData
== NULL
) {
1982 return EFI_OUT_OF_RESOURCES
;
1985 if (Private
->Current
!= NULL
) {
1986 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
1989 BufferSize
= ISCSI_NAME_MAX_SIZE
;
1990 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
1991 if (InitiatorName
== NULL
) {
1992 FreePool (IfrNvData
);
1993 return EFI_OUT_OF_RESOURCES
;
1996 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
1997 if (EFI_ERROR (Status
)) {
1998 IfrNvData
->InitiatorName
[0] = L
'\0';
2000 AsciiStrToUnicodeStrS (
2002 IfrNvData
->InitiatorName
,
2003 sizeof (IfrNvData
->InitiatorName
) / sizeof (IfrNvData
->InitiatorName
[0])
2008 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
2010 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2011 ConfigRequest
= Request
;
2012 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
2014 // Request has no request element, construct full request string.
2015 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2016 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2018 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
2019 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
2020 ConfigRequest
= AllocateZeroPool (Size
);
2021 if (ConfigRequest
== NULL
) {
2022 FreePool (IfrNvData
);
2023 FreePool (InitiatorName
);
2024 return EFI_OUT_OF_RESOURCES
;
2026 AllocatedRequest
= TRUE
;
2027 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
2028 FreePool (ConfigRequestHdr
);
2031 Status
= gHiiConfigRouting
->BlockToConfig (
2034 (UINT8
*) IfrNvData
,
2039 FreePool (IfrNvData
);
2040 FreePool (InitiatorName
);
2043 // Free the allocated config request string.
2045 if (AllocatedRequest
) {
2046 FreePool (ConfigRequest
);
2047 ConfigRequest
= NULL
;
2050 // Set Progress string to the original request string.
2052 if (Request
== NULL
) {
2054 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
2055 *Progress
= Request
+ StrLen (Request
);
2064 This function applies changes in a driver's configuration.
2065 Input is a Configuration, which has the routing data for this
2066 driver followed by name / value configuration pairs. The driver
2067 must apply those pairs to its configurable storage. If the
2068 driver's configuration is stored in a linear block of data
2069 and the driver's name / value pairs are in <BlockConfig>
2070 format, it may use the ConfigToBlock helper function (above) to
2073 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2075 @param[in] Configuration A null-terminated Unicode string in
2076 <ConfigString> format.
2078 @param[out] Progress A pointer to a string filled in with the
2079 offset of the most recent '&' before the
2080 first failing name / value pair (or the
2081 beginning of the string if the failure
2082 is in the first name / value pair) or
2083 the terminating NULL if all was
2086 @retval EFI_SUCCESS The results have been distributed or are
2087 awaiting distribution.
2089 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2090 parts of the results that must be
2091 stored awaiting possible future
2094 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
2095 Results parameter would result
2096 in this type of error.
2098 @retval EFI_NOT_FOUND Target for the specified routing data
2104 IScsiFormRouteConfig (
2105 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2106 IN CONST EFI_STRING Configuration
,
2107 OUT EFI_STRING
*Progress
2110 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
2111 return EFI_INVALID_PARAMETER
;
2115 // Check routing data in <ConfigHdr>.
2116 // Note: if only one Storage is used, then this checking could be skipped.
2118 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
2119 *Progress
= Configuration
;
2120 return EFI_NOT_FOUND
;
2123 *Progress
= Configuration
+ StrLen (Configuration
);
2130 This function is called to provide results data to the driver.
2131 This data consists of a unique key that is used to identify
2132 which data is either being passed back or being asked for.
2134 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2135 @param[in] Action Specifies the type of action taken by the browser.
2136 @param[in] QuestionId A unique value which is sent to the original
2137 exporting driver so that it can identify the type
2138 of data to expect. The format of the data tends to
2139 vary based on the opcode that generated the callback.
2140 @param[in] Type The type of value for the question.
2141 @param[in, out] Value A pointer to the data being sent to the original
2143 @param[out] ActionRequest On return, points to the action requested by the
2146 @retval EFI_SUCCESS The callback successfully handled the action.
2147 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2148 variable and its data.
2149 @retval EFI_DEVICE_ERROR The variable could not be saved.
2150 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2156 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2157 IN EFI_BROWSER_ACTION Action
,
2158 IN EFI_QUESTION_ID QuestionId
,
2160 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
2161 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2164 ISCSI_FORM_CALLBACK_INFO
*Private
;
2167 CHAR8 IpString
[ISCSI_NAME_MAX_SIZE
];
2168 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
2170 EFI_IP_ADDRESS HostIp
;
2171 EFI_IP_ADDRESS SubnetMask
;
2172 EFI_IP_ADDRESS Gateway
;
2173 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
2174 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
2176 CHAR16 AttemptName
[ATTEMPT_NAME_SIZE
+ 4];
2179 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
2181 // Do nothing for UEFI OPEN/CLOSE Action
2186 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
2188 // All other type return unsupported.
2190 return EFI_UNSUPPORTED
;
2193 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
2194 return EFI_INVALID_PARAMETER
;
2197 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
2200 // Retrieve uncommitted data from Browser
2203 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2204 IfrNvData
= AllocateZeroPool (BufferSize
);
2205 if (IfrNvData
== NULL
) {
2206 return EFI_OUT_OF_RESOURCES
;
2209 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
2210 if (IScsiName
== NULL
) {
2211 FreePool (IfrNvData
);
2212 return EFI_OUT_OF_RESOURCES
;
2215 Status
= EFI_SUCCESS
;
2217 ZeroMem (&OldIfrNvData
, BufferSize
);
2219 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2221 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
2223 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2224 switch (QuestionId
) {
2225 case KEY_ADD_ATTEMPT
:
2227 // Check whether iSCSI initiator name is configured already.
2229 mPrivate
->InitiatorNameLength
= ISCSI_NAME_MAX_SIZE
;
2230 Status
= gIScsiInitiatorName
.Get (
2231 &gIScsiInitiatorName
,
2232 &mPrivate
->InitiatorNameLength
,
2233 mPrivate
->InitiatorName
2235 if (EFI_ERROR (Status
)) {
2237 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2239 L
"Error: please configure iSCSI initiator name first!",
2245 Status
= IScsiConfigAddAttempt ();
2248 case KEY_DELETE_ATTEMPT
:
2250 OldIfrNvData
.DeleteAttemptList
,
2251 IfrNvData
->DeleteAttemptList
,
2252 sizeof (IfrNvData
->DeleteAttemptList
)
2254 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
2257 case KEY_ORDER_ATTEMPT_CONFIG
:
2259 // Order the attempt according to user input.
2262 OldIfrNvData
.DynamicOrderedList
,
2263 IfrNvData
->DynamicOrderedList
,
2264 sizeof (IfrNvData
->DynamicOrderedList
)
2266 IScsiConfigDisplayOrderAttempts ();
2270 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
2273 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2274 switch (QuestionId
) {
2275 case KEY_INITIATOR_NAME
:
2276 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
2277 BufferSize
= AsciiStrSize (IScsiName
);
2279 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
2280 if (EFI_ERROR (Status
)) {
2282 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2284 L
"Invalid iSCSI Name!",
2289 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2291 case KEY_ATTEMPT_NAME
:
2292 if (StrLen (IfrNvData
->AttemptName
) > ATTEMPT_NAME_SIZE
) {
2293 CopyMem (AttemptName
, IfrNvData
->AttemptName
, ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
2294 CopyMem (&AttemptName
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
2298 IfrNvData
->AttemptName
,
2299 (StrLen (IfrNvData
->AttemptName
) + 1) * sizeof (CHAR16
)
2303 UnicodeStrToAsciiStrS (IfrNvData
->AttemptName
, Private
->Current
->AttemptName
, sizeof (Private
->Current
->AttemptName
));
2305 IScsiConfigUpdateAttempt ();
2307 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2310 case KEY_SAVE_ATTEMPT_CONFIG
:
2311 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
2312 if (EFI_ERROR (Status
)) {
2316 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2319 case KEY_SAVE_ORDER_CHANGES
:
2321 // Sync the Attempt Order to NVR.
2323 Status
= IScsiConfigOrderAttempts (IfrNvData
);
2324 if (EFI_ERROR (Status
)) {
2328 IScsiConfigUpdateAttempt ();
2329 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
2332 case KEY_IGNORE_ORDER_CHANGES
:
2334 IfrNvData
->DynamicOrderedList
,
2335 OldIfrNvData
.DynamicOrderedList
,
2336 sizeof (IfrNvData
->DynamicOrderedList
)
2338 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
2341 case KEY_SAVE_DELETE_ATTEMPT
:
2343 // Delete the Attempt Order from NVR
2345 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
2346 if (EFI_ERROR (Status
)) {
2350 IScsiConfigUpdateAttempt ();
2351 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
2354 case KEY_IGNORE_DELETE_ATTEMPT
:
2356 IfrNvData
->DeleteAttemptList
,
2357 OldIfrNvData
.DeleteAttemptList
,
2358 sizeof (IfrNvData
->DeleteAttemptList
)
2360 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
2364 switch (Value
->u8
) {
2367 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2368 Private
->Current
->AutoConfigureMode
= 0;
2376 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
2377 if (EFI_ERROR (Status
) ||
2378 ((Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
2379 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
2381 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2383 L
"Invalid IP address!",
2387 Status
= EFI_INVALID_PARAMETER
;
2389 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
2394 case KEY_SUBNET_MASK
:
2395 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
2396 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
2398 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2400 L
"Invalid Subnet Mask!",
2404 Status
= EFI_INVALID_PARAMETER
;
2406 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
2412 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
2413 if (EFI_ERROR (Status
) ||
2414 ((Gateway
.Addr
[0] != 0) &&
2415 (Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
2416 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
2418 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2420 L
"Invalid Gateway!",
2423 Status
= EFI_INVALID_PARAMETER
;
2425 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
2431 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, IpString
, sizeof (IpString
));
2432 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
2433 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
2435 // The target is expressed in URL format or an invalid Ip address, just save.
2437 Private
->Current
->SessionConfigData
.DnsMode
= TRUE
;
2438 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (Private
->Current
->SessionConfigData
.TargetIp
));
2439 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, Private
->Current
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
2441 Private
->Current
->SessionConfigData
.DnsMode
= FALSE
;
2442 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
2447 case KEY_TARGET_NAME
:
2448 UnicodeStrToAsciiStrS (IfrNvData
->TargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
2449 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
2450 if (EFI_ERROR (Status
)) {
2452 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2454 L
"Invalid iSCSI Name!",
2458 AsciiStrCpyS (Private
->Current
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
2463 case KEY_DHCP_ENABLE
:
2464 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
2465 IfrNvData
->TargetInfoFromDhcp
= 0;
2471 UnicodeStrToAsciiStrS (IfrNvData
->BootLun
, LunString
, sizeof (LunString
));
2472 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
2473 if (EFI_ERROR (Status
)) {
2475 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2477 L
"Invalid LUN string!",
2481 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
2487 switch (Value
->u8
) {
2488 case ISCSI_AUTH_TYPE_CHAP
:
2489 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
2498 UnicodeStrToAsciiStrS (
2499 IfrNvData
->CHAPName
,
2500 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
,
2501 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPName
)
2505 case KEY_CHAP_SECRET
:
2506 UnicodeStrToAsciiStrS (
2507 IfrNvData
->CHAPSecret
,
2508 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
,
2509 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
)
2513 case KEY_REVERSE_CHAP_NAME
:
2514 UnicodeStrToAsciiStrS (
2515 IfrNvData
->ReverseCHAPName
,
2516 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
,
2517 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
)
2521 case KEY_REVERSE_CHAP_SECRET
:
2522 UnicodeStrToAsciiStrS (
2523 IfrNvData
->ReverseCHAPSecret
,
2524 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
2525 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
)
2529 case KEY_CONFIG_ISID
:
2530 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2531 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2540 if (!EFI_ERROR (Status
)) {
2542 // Pass changed uncommitted data back to Form Browser.
2544 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2545 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2548 FreePool (IfrNvData
);
2549 FreePool (IScsiName
);
2556 Initialize the iSCSI configuration form.
2558 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2560 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
2561 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2565 IScsiConfigFormInit (
2566 IN EFI_HANDLE DriverBindingHandle
2570 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
2572 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
2573 if (CallbackInfo
== NULL
) {
2574 return EFI_OUT_OF_RESOURCES
;
2577 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
2578 CallbackInfo
->Current
= NULL
;
2580 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
2581 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
2582 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
2585 // Install Device Path Protocol and Config Access protocol to driver handle.
2587 Status
= gBS
->InstallMultipleProtocolInterfaces (
2588 &CallbackInfo
->DriverHandle
,
2589 &gEfiDevicePathProtocolGuid
,
2590 &mIScsiHiiVendorDevicePath
,
2591 &gEfiHiiConfigAccessProtocolGuid
,
2592 &CallbackInfo
->ConfigAccess
,
2595 ASSERT_EFI_ERROR (Status
);
2598 // Publish our HII data.
2600 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
2602 CallbackInfo
->DriverHandle
,
2607 if (CallbackInfo
->RegisteredHandle
== NULL
) {
2608 gBS
->UninstallMultipleProtocolInterfaces (
2609 &CallbackInfo
->DriverHandle
,
2610 &gEfiDevicePathProtocolGuid
,
2611 &mIScsiHiiVendorDevicePath
,
2612 &gEfiHiiConfigAccessProtocolGuid
,
2613 &CallbackInfo
->ConfigAccess
,
2616 FreePool(CallbackInfo
);
2617 return EFI_OUT_OF_RESOURCES
;
2620 mCallbackInfo
= CallbackInfo
;
2627 Unload the iSCSI configuration form, this includes: delete all the iSCSI
2628 configuration entries, uninstall the form callback protocol, and
2629 free the resources used.
2631 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2633 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
2634 @retval Others Failed to unload the form.
2638 IScsiConfigFormUnload (
2639 IN EFI_HANDLE DriverBindingHandle
2642 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2643 ISCSI_NIC_INFO
*NicInfo
;
2647 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
2648 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
2649 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2650 FreePool (AttemptConfigData
);
2651 mPrivate
->AttemptCount
--;
2654 ASSERT (mPrivate
->AttemptCount
== 0);
2656 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
2657 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
2658 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
2660 mPrivate
->NicCount
--;
2663 ASSERT (mPrivate
->NicCount
== 0);
2666 // Free attempt is created but not saved to system.
2668 if (mPrivate
->NewAttempt
!= NULL
) {
2669 FreePool (mPrivate
->NewAttempt
);
2672 FreePool (mPrivate
);
2676 // Remove HII package list.
2678 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
2681 // Uninstall Device Path Protocol and Config Access protocol.
2683 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2684 mCallbackInfo
->DriverHandle
,
2685 &gEfiDevicePathProtocolGuid
,
2686 &mIScsiHiiVendorDevicePath
,
2687 &gEfiHiiConfigAccessProtocolGuid
,
2688 &mCallbackInfo
->ConfigAccess
,
2692 FreePool (mCallbackInfo
);