2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "IScsiImpl.h"
17 EFI_GUID mVendorGuid
= ISCSI_CONFIG_GUID
;
18 CHAR16 mVendorStorageName
[] = L
"ISCSI_CONFIG_IFR_NVDATA";
19 BOOLEAN mIScsiDeviceListUpdated
= FALSE
;
20 UINTN mNumberOfIScsiDevices
= 0;
21 ISCSI_FORM_CALLBACK_INFO
*mCallbackInfo
= NULL
;
23 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath
= {
29 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
30 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
34 // {49D7B73E-143D-4716-977B-C45F1CB038CC}
36 { 0x49d7b73e, 0x143d, 0x4716, { 0x97, 0x7b, 0xc4, 0x5f, 0x1c, 0xb0, 0x38, 0xcc } }
40 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
42 (UINT8
) (END_DEVICE_PATH_LENGTH
),
43 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
50 Convert the IP address into a dotted string.
52 @param[in] Ip The IP address.
53 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.
54 @param[out] Str The formatted IP string.
59 IN EFI_IP_ADDRESS
*Ip
,
64 EFI_IPv4_ADDRESS
*Ip4
;
65 EFI_IPv6_ADDRESS
*Ip6
;
69 CHAR16 FormatString
[8];
76 (UINTN
) 2 * IP4_STR_MAX_SIZE
,
90 for (Index
= 0; Index
< 15; Index
= Index
+ 2) {
93 Ip6
->Addr
[Index
] == 0 &&
94 Ip6
->Addr
[Index
+ 1] == 0
97 // Deal with the case of ::.
108 while ((Index
< 15) && (Ip6
->Addr
[Index
] == 0) && (Ip6
->Addr
[Index
+ 1] == 0)) {
116 // :: is at the end of the address.
125 if (Ip6
->Addr
[Index
] == 0) {
126 Number
= UnicodeSPrint (Str
, 2 * IP_STR_MAX_SIZE
, L
"%x:", (UINTN
) Ip6
->Addr
[Index
+ 1]);
128 if (Ip6
->Addr
[Index
+ 1] < 0x10) {
129 CopyMem (FormatString
, L
"%x0%x:", StrSize (L
"%x0%x:"));
131 CopyMem (FormatString
, L
"%x%x:", StrSize (L
"%x%x:"));
134 Number
= UnicodeSPrint (
137 (CONST CHAR16
*) FormatString
,
138 (UINTN
) Ip6
->Addr
[Index
],
139 (UINTN
) Ip6
->Addr
[Index
+ 1]
145 if (Index
+ 2 == 16) {
147 if (*(Str
- 1) == L
':') {
155 Check whether the input IP address is valid.
157 @param[in] Ip The IP address.
158 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.
160 @retval TRUE The input IP address is valid.
161 @retval FALSE Otherwise
166 IN EFI_IP_ADDRESS
*Ip
,
170 if (IpMode
== IP_MODE_IP4
) {
171 return NetIp4IsUnicast (NTOHL (Ip
->Addr
[0]), 0);
172 } else if (IpMode
== IP_MODE_IP6
) {
173 return NetIp6IsValidUnicast (&Ip
->v6
);
175 DEBUG ((DEBUG_ERROR
, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode
));
181 Parse IsId in string format and convert it to binary.
183 @param[in] String The buffer of the string to be parsed.
184 @param[in, out] IsId The buffer to store IsId.
186 @retval EFI_SUCCESS The operation finished successfully.
187 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
191 IScsiParseIsIdFromString (
192 IN CONST CHAR16
*String
,
200 CHAR16 PortString
[ISCSI_NAME_IFR_MAX_SIZE
];
203 if ((String
== NULL
) || (IsId
== NULL
)) {
204 return EFI_INVALID_PARAMETER
;
207 IsIdStr
= (CHAR16
*) String
;
209 if (StrLen (IsIdStr
) != 6) {
212 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
213 L
"Error! Input is incorrect, please input 6 hex numbers!\n"
217 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
223 return EFI_INVALID_PARAMETER
;
226 for (Index
= 3; Index
< 6; Index
++) {
227 CopyMem (TempStr
, IsIdStr
, sizeof (TempStr
));
231 // Convert the string to IsId. StrHexToUintn stops at the first character
232 // that is not a valid hex character, '\0' here.
234 NodeVal
= StrHexToUintn (TempStr
);
236 IsId
[Index
] = (UINT8
) NodeVal
;
238 IsIdStr
= IsIdStr
+ 2;
245 Convert IsId from binary to string format.
247 @param[out] String The buffer to store the converted string.
248 @param[in] IsId The buffer to store IsId.
250 @retval EFI_SUCCESS The string converted successfully.
251 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
255 IScsiConvertIsIdToString (
263 if ((String
== NULL
) || (IsId
== NULL
)) {
264 return EFI_INVALID_PARAMETER
;
267 for (Index
= 0; Index
< 6; Index
++) {
268 if (IsId
[Index
] <= 0xF) {
269 Number
= UnicodeSPrint (
271 2 * ISID_CONFIGURABLE_STORAGE
,
276 Number
= UnicodeSPrint (
278 2 * ISID_CONFIGURABLE_STORAGE
,
285 String
= String
+ Number
;
294 Get the attempt config data from global structure by the ConfigIndex.
296 @param[in] AttemptConfigIndex The unique index indicates the attempt.
298 @return Pointer to the attempt config data.
299 @retval NULL The attempt configuration data cannot be found.
302 ISCSI_ATTEMPT_CONFIG_NVDATA
*
303 IScsiConfigGetAttemptByConfigIndex (
304 IN UINT8 AttemptConfigIndex
308 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
310 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
311 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
312 if (Attempt
->AttemptConfigIndex
== AttemptConfigIndex
) {
322 Get the existing attempt config data from global structure by the NicIndex.
324 @param[in] NewAttempt The created new attempt
325 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
328 @return Pointer to the existing attempt config data which
329 has the same NICIndex as the new created attempt.
330 @retval NULL The attempt with NicIndex does not exist.
333 ISCSI_ATTEMPT_CONFIG_NVDATA
*
334 IScsiConfigGetAttemptByNic (
335 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*NewAttempt
,
340 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
342 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
343 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
344 if (Attempt
!= NewAttempt
&& Attempt
->NicIndex
== NewAttempt
->NicIndex
&&
345 Attempt
->SessionConfigData
.Enabled
== IScsiMode
) {
355 Convert the iSCSI configuration data into the IFR data.
357 @param[in] Attempt The iSCSI attempt config data.
358 @param[in, out] IfrNvData The IFR nv data.
362 IScsiConvertAttemptConfigDataToIfrNvData (
363 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
,
364 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
367 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
368 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
372 // Normal session configuration parameters.
374 SessionConfigData
= &Attempt
->SessionConfigData
;
375 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
376 IfrNvData
->IpMode
= SessionConfigData
->IpMode
;
378 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
379 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
380 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
382 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
383 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
384 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->LocalIp
);
385 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
386 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->SubnetMask
);
387 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
388 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Gateway
);
389 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
390 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->TargetIp
);
391 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
392 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
393 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
394 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->TargetIp
);
397 AsciiStrToUnicodeStr (SessionConfigData
->TargetName
, IfrNvData
->TargetName
);
398 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
399 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
401 IfrNvData
->ConnectRetryCount
= SessionConfigData
->ConnectRetryCount
;
402 IfrNvData
->ConnectTimeout
= SessionConfigData
->ConnectTimeout
;
405 // Authentication parameters.
407 IfrNvData
->AuthenticationType
= Attempt
->AuthenticationType
;
409 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
410 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
411 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
412 AsciiStrToUnicodeStr (AuthConfigData
->CHAPName
, IfrNvData
->CHAPName
);
413 AsciiStrToUnicodeStr (AuthConfigData
->CHAPSecret
, IfrNvData
->CHAPSecret
);
414 AsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPName
, IfrNvData
->ReverseCHAPName
);
415 AsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPSecret
, IfrNvData
->ReverseCHAPSecret
);
421 AsciiStrToUnicodeStr (Attempt
->AttemptName
, IfrNvData
->AttemptName
);
426 Convert the IFR data to iSCSI configuration data.
428 @param[in] IfrNvData The IFR nv data.
429 @param[in, out] Attempt The iSCSI attempt config data.
431 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
432 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
433 @retval EFI_SUCCESS The operation is completed successfully.
437 IScsiConvertIfrNvDataToAttemptConfigData (
438 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
439 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
442 EFI_IP_ADDRESS HostIp
;
443 EFI_IP_ADDRESS SubnetMask
;
444 EFI_IP_ADDRESS Gateway
;
446 CHAR16
*AttemptName1
;
447 CHAR16
*AttemptName2
;
448 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
449 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
450 CHAR16 IScsiMode
[64];
452 ISCSI_NIC_INFO
*NicInfo
;
455 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
456 return EFI_INVALID_PARAMETER
;
460 // Update those fields which don't have INTERACTIVE attribute.
462 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
463 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
464 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
466 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
467 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
468 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
470 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
471 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
474 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
477 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
479 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
480 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
484 // Only do full parameter validation if iSCSI is enabled on this device.
486 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
487 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
489 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
491 L
"Connection Establishing Timeout is less than minimum value 100ms.",
495 return EFI_INVALID_PARAMETER
;
499 // Validate the address configuration of the Initiator if DHCP isn't
502 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
503 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
504 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
505 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
507 if ((Gateway
.Addr
[0] != 0)) {
508 if (SubnetMask
.Addr
[0] == 0) {
510 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
512 L
"Gateway address is set but subnet mask is zero.",
516 return EFI_INVALID_PARAMETER
;
517 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
519 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
521 L
"Local IP and Gateway are not in the same subnet.",
525 return EFI_INVALID_PARAMETER
;
530 // Validate target configuration if DHCP isn't deployed.
532 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
533 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
535 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
537 L
"Target IP is invalid!",
540 return EFI_INVALID_PARAMETER
;
544 // Validate the authentication info.
546 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
547 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
549 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
551 L
"CHAP Name or CHAP Secret is invalid!",
555 return EFI_INVALID_PARAMETER
;
558 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
559 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
562 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
564 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
567 return EFI_INVALID_PARAMETER
;
572 // Check whether this attempt uses NIC which is already used by existing attempt.
574 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
575 if (SameNicAttempt
!= NULL
) {
576 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
577 if (AttemptName1
== NULL
) {
578 return EFI_OUT_OF_RESOURCES
;
581 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE
* sizeof (CHAR16
));
582 if (AttemptName2
== NULL
) {
583 FreePool (AttemptName1
);
584 return EFI_OUT_OF_RESOURCES
;
587 AsciiStrToUnicodeStr (Attempt
->AttemptName
, AttemptName1
);
588 if (StrLen (AttemptName1
) > ATTEMPT_NAME_SIZE
) {
589 CopyMem (&AttemptName1
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
592 AsciiStrToUnicodeStr (SameNicAttempt
->AttemptName
, AttemptName2
);
593 if (StrLen (AttemptName2
) > ATTEMPT_NAME_SIZE
) {
594 CopyMem (&AttemptName2
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
598 mPrivate
->PortString
,
599 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
600 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
606 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
608 mPrivate
->PortString
,
612 FreePool (AttemptName1
);
613 FreePool (AttemptName2
);
618 // Check whether this attempt is an existing one.
620 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
621 if (ExistAttempt
!= NULL
) {
622 ASSERT (ExistAttempt
== Attempt
);
624 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
625 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
628 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
630 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
631 if (mPrivate
->MpioCount
< 1) {
635 if (--mPrivate
->MpioCount
== 0) {
636 mPrivate
->EnableMpio
= FALSE
;
638 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
639 if (mPrivate
->SinglePathCount
< 1) {
642 mPrivate
->SinglePathCount
--;
645 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
646 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
648 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
650 if (mPrivate
->SinglePathCount
< 1) {
654 mPrivate
->EnableMpio
= TRUE
;
655 mPrivate
->MpioCount
++;
656 mPrivate
->SinglePathCount
--;
658 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
659 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
661 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
663 if (mPrivate
->MpioCount
< 1) {
667 if (--mPrivate
->MpioCount
== 0) {
668 mPrivate
->EnableMpio
= FALSE
;
670 mPrivate
->SinglePathCount
++;
672 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
673 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
675 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
677 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
678 mPrivate
->EnableMpio
= TRUE
;
679 mPrivate
->MpioCount
++;
681 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
682 mPrivate
->SinglePathCount
++;
686 } else if (ExistAttempt
== NULL
&& IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
687 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
689 // This new Attempt is enabled for MPIO; enable the multipath mode.
691 mPrivate
->EnableMpio
= TRUE
;
692 mPrivate
->MpioCount
++;
693 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
694 mPrivate
->SinglePathCount
++;
699 // Update the iSCSI Mode data and record it in attempt help info.
701 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
702 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
703 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
704 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
705 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
706 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
707 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
710 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
711 UnicodeSPrint (IpMode
, 64, L
"IP4");
712 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
713 UnicodeSPrint (IpMode
, 64, L
"IP6");
714 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
715 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
718 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
719 if (NicInfo
== NULL
) {
720 return EFI_NOT_FOUND
;
723 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
724 if (MacString
== NULL
) {
725 return EFI_OUT_OF_RESOURCES
;
728 AsciiStrToUnicodeStr (Attempt
->MacString
, MacString
);
731 mPrivate
->PortString
,
732 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
733 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
736 NicInfo
->DeviceNumber
,
737 NicInfo
->FunctionNumber
,
742 Attempt
->AttemptTitleHelpToken
= HiiSetString (
743 mCallbackInfo
->RegisteredHandle
,
744 Attempt
->AttemptTitleHelpToken
,
745 mPrivate
->PortString
,
748 if (Attempt
->AttemptTitleHelpToken
== 0) {
749 FreePool (MacString
);
750 return EFI_OUT_OF_RESOURCES
;
754 // Record the user configuration information in NVR.
757 mPrivate
->PortString
,
758 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
761 (UINTN
) Attempt
->AttemptConfigIndex
764 FreePool (MacString
);
766 return gRT
->SetVariable (
767 mPrivate
->PortString
,
768 &gEfiIScsiInitiatorNameProtocolGuid
,
769 ISCSI_CONFIG_VAR_ATTR
,
770 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
776 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
779 @param[in] StartLabelNumber The number of start label.
780 @param[out] StartOpCodeHandle Points to the start opcode handle.
781 @param[out] StartLabel Points to the created start opcode.
782 @param[out] EndOpCodeHandle Points to the end opcode handle.
783 @param[out] EndLabel Points to the created end opcode.
785 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
787 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
788 @retval EFI_SUCCESS The operation is completed successfully.
793 IN UINT16 StartLabelNumber
,
794 OUT VOID
**StartOpCodeHandle
,
795 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
796 OUT VOID
**EndOpCodeHandle
,
797 OUT EFI_IFR_GUID_LABEL
**EndLabel
801 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
802 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
804 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
805 return EFI_INVALID_PARAMETER
;
808 *StartOpCodeHandle
= NULL
;
809 *EndOpCodeHandle
= NULL
;
810 Status
= EFI_OUT_OF_RESOURCES
;
813 // Initialize the container for dynamic opcodes.
815 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
816 if (*StartOpCodeHandle
== NULL
) {
820 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
821 if (*EndOpCodeHandle
== NULL
) {
826 // Create Hii Extend Label OpCode as the start opcode.
828 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
832 sizeof (EFI_IFR_GUID_LABEL
)
834 if (InternalStartLabel
== NULL
) {
838 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
839 InternalStartLabel
->Number
= StartLabelNumber
;
842 // Create Hii Extend Label OpCode as the end opcode.
844 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
848 sizeof (EFI_IFR_GUID_LABEL
)
850 if (InternalEndLabel
== NULL
) {
854 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
855 InternalEndLabel
->Number
= LABEL_END
;
857 *StartLabel
= InternalStartLabel
;
858 *EndLabel
= InternalEndLabel
;
864 if (*StartOpCodeHandle
!= NULL
) {
865 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
868 if (*EndOpCodeHandle
!= NULL
) {
869 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
876 Callback function when user presses "Add an Attempt".
878 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
880 @retval EFI_SUCCESS The operation is completed successfully.
884 IScsiConfigAddAttempt (
889 ISCSI_NIC_INFO
*NicInfo
;
890 EFI_STRING_ID PortTitleToken
;
891 EFI_STRING_ID PortTitleHelpToken
;
892 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
894 VOID
*StartOpCodeHandle
;
895 EFI_IFR_GUID_LABEL
*StartLabel
;
896 VOID
*EndOpCodeHandle
;
897 EFI_IFR_GUID_LABEL
*EndLabel
;
899 Status
= IScsiCreateOpCode (
906 if (EFI_ERROR (Status
)) {
911 // Ask user to select a MAC for this attempt.
913 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
914 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
916 &NicInfo
->PermanentAddress
,
917 NicInfo
->HwAddressSize
,
922 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Port %s", MacString
);
923 PortTitleToken
= HiiSetString (
924 mCallbackInfo
->RegisteredHandle
,
926 mPrivate
->PortString
,
929 if (PortTitleToken
== 0) {
930 Status
= EFI_INVALID_PARAMETER
;
935 mPrivate
->PortString
,
936 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
937 L
"PFA: Bus %d | Dev %d | Func %d",
939 NicInfo
->DeviceNumber
,
940 NicInfo
->FunctionNumber
942 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
943 if (PortTitleHelpToken
== 0) {
944 Status
= EFI_INVALID_PARAMETER
;
948 HiiCreateGotoOpCode (
949 StartOpCodeHandle
, // Container for dynamic created opcodes
953 EFI_IFR_FLAG_CALLBACK
, // Question flag
954 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
958 Status
= HiiUpdateForm (
959 mCallbackInfo
->RegisteredHandle
, // HII handle
960 &mVendorGuid
, // Formset GUID
961 FORMID_MAC_FORM
, // Form ID
962 StartOpCodeHandle
, // Label for where to insert opcodes
963 EndOpCodeHandle
// Replace data
967 HiiFreeOpCodeHandle (StartOpCodeHandle
);
968 HiiFreeOpCodeHandle (EndOpCodeHandle
);
975 Update the MAIN form to display the configured attempts.
979 IScsiConfigUpdateAttempt (
983 CHAR16 AttemptName
[ATTEMPT_NAME_MAX_SIZE
];
985 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
986 VOID
*StartOpCodeHandle
;
987 EFI_IFR_GUID_LABEL
*StartLabel
;
988 VOID
*EndOpCodeHandle
;
989 EFI_IFR_GUID_LABEL
*EndLabel
;
992 Status
= IScsiCreateOpCode (
999 if (EFI_ERROR (Status
)) {
1003 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1004 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1006 AsciiStrToUnicodeStr (AttemptConfigData
->AttemptName
, AttemptName
);
1007 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) 128, L
"Attempt %s", AttemptName
);
1008 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1009 mCallbackInfo
->RegisteredHandle
,
1011 mPrivate
->PortString
,
1014 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1018 HiiCreateGotoOpCode (
1019 StartOpCodeHandle
, // Container for dynamic created opcodes
1020 FORMID_ATTEMPT_FORM
, // Form ID
1021 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1022 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1023 EFI_IFR_FLAG_CALLBACK
, // Question flag
1024 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1029 mCallbackInfo
->RegisteredHandle
, // HII handle
1030 &mVendorGuid
, // Formset GUID
1031 FORMID_MAIN_FORM
, // Form ID
1032 StartOpCodeHandle
, // Label for where to insert opcodes
1033 EndOpCodeHandle
// Replace data
1036 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1037 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1042 Callback function when user presses "Commit Changes and Exit" in Delete Attempts.
1044 @param[in] IfrNvData The IFR NV data.
1046 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1047 @retval EFI_SUCCESS The operation is completed successfully.
1048 @retval EFI_ABOTRED This operation is aborted cause of error
1050 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
1055 IScsiConfigDeleteAttempts (
1056 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1062 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1063 UINT8
*AttemptConfigOrder
;
1064 UINTN AttemptConfigOrderSize
;
1065 UINT8
*AttemptNewOrder
;
1070 LIST_ENTRY
*NextEntry
;
1071 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1073 AttemptConfigOrder
= IScsiGetVariableAndSize (
1076 &AttemptConfigOrderSize
1078 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
1079 return EFI_NOT_FOUND
;
1082 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
1083 if (AttemptNewOrder
== NULL
) {
1084 return EFI_OUT_OF_RESOURCES
;
1087 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1091 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
1092 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
1098 // Delete the attempt.
1101 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1102 if (AttemptConfigData
== NULL
) {
1103 Status
= EFI_NOT_FOUND
;
1108 // Remove this attempt from UI configured attempt list.
1110 RemoveEntryList (&AttemptConfigData
->Link
);
1111 mPrivate
->AttemptCount
--;
1113 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1114 if (mPrivate
->MpioCount
< 1) {
1115 Status
= EFI_ABORTED
;
1120 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
1122 if (--mPrivate
->MpioCount
== 0) {
1123 mPrivate
->EnableMpio
= FALSE
;
1125 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1126 if (mPrivate
->SinglePathCount
< 1) {
1127 Status
= EFI_ABORTED
;
1131 mPrivate
->SinglePathCount
--;
1134 AsciiStrToUnicodeStr (AttemptConfigData
->MacString
, MacString
);
1137 mPrivate
->PortString
,
1141 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1145 mPrivate
->PortString
,
1146 &gEfiIScsiInitiatorNameProtocolGuid
,
1153 // Mark the attempt order in NVR to be deleted - 0.
1155 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
1156 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
1157 AttemptConfigOrder
[NewIndex
] = 0;
1163 FreePool (AttemptConfigData
);
1166 // Check next Attempt.
1172 // Construct AttemptNewOrder.
1174 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
1175 if (AttemptConfigOrder
[Index
] != 0) {
1176 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
1181 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
1182 | EFI_VARIABLE_NON_VOLATILE
;
1185 // Update AttemptOrder in NVR.
1187 Status
= gRT
->SetVariable (
1191 NewTotal
* sizeof (UINT8
),
1196 FreePool (AttemptConfigOrder
);
1197 FreePool (AttemptNewOrder
);
1204 Callback function when user presses "Delete Attempts".
1206 @param[in] IfrNvData The IFR nv data.
1208 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1209 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
1210 @retval EFI_SUCCESS The operation is completed successfully.
1214 IScsiConfigDisplayDeleteAttempts (
1215 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1219 UINT8
*AttemptConfigOrder
;
1220 UINTN AttemptConfigOrderSize
;
1222 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1224 VOID
*StartOpCodeHandle
;
1225 EFI_IFR_GUID_LABEL
*StartLabel
;
1226 VOID
*EndOpCodeHandle
;
1227 EFI_IFR_GUID_LABEL
*EndLabel
;
1230 Status
= IScsiCreateOpCode (
1237 if (EFI_ERROR (Status
)) {
1241 AttemptConfigOrder
= IScsiGetVariableAndSize (
1244 &AttemptConfigOrderSize
1246 if (AttemptConfigOrder
!= NULL
) {
1248 // Create the check box opcode to be deleted.
1252 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1253 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1254 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
1256 HiiCreateCheckBoxOpCode(
1258 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
1259 CONFIGURATION_VARSTORE_ID
,
1260 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
1261 AttemptConfigData
->AttemptTitleToken
,
1262 AttemptConfigData
->AttemptTitleHelpToken
,
1270 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
1275 FreePool (AttemptConfigOrder
);
1278 Status
= HiiUpdateForm (
1279 mCallbackInfo
->RegisteredHandle
, // HII handle
1280 &mVendorGuid
, // Formset GUID
1281 FORMID_DELETE_FORM
, // Form ID
1282 StartOpCodeHandle
, // Label for where to insert opcodes
1283 EndOpCodeHandle
// Replace data
1286 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1287 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1294 Callback function when user presses "Change Attempt Order".
1296 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1297 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1299 @retval EFI_SUCCESS The operation is completed successfully.
1303 IScsiConfigDisplayOrderAttempts (
1310 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1311 VOID
*StartOpCodeHandle
;
1312 EFI_IFR_GUID_LABEL
*StartLabel
;
1313 VOID
*EndOpCodeHandle
;
1314 EFI_IFR_GUID_LABEL
*EndLabel
;
1315 VOID
*OptionsOpCodeHandle
;
1317 Status
= IScsiCreateOpCode (
1324 if (EFI_ERROR (Status
)) {
1328 OptionsOpCodeHandle
= NULL
;
1331 // If no attempt to be ordered, update the original form and exit.
1333 if (mPrivate
->AttemptCount
== 0) {
1338 // Create Option OpCode.
1340 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
1341 if (OptionsOpCodeHandle
== NULL
) {
1342 Status
= EFI_OUT_OF_RESOURCES
;
1348 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1349 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1350 HiiCreateOneOfOptionOpCode (
1351 OptionsOpCodeHandle
,
1352 AttemptConfigData
->AttemptTitleToken
,
1354 EFI_IFR_NUMERIC_SIZE_1
,
1355 AttemptConfigData
->AttemptConfigIndex
1360 ASSERT (Index
== mPrivate
->AttemptCount
);
1362 HiiCreateOrderedListOpCode (
1363 StartOpCodeHandle
, // Container for dynamic created opcodes
1364 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
1365 CONFIGURATION_VARSTORE_ID
, // VarStore ID
1366 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
1367 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
1368 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
1370 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1371 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
1372 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
1373 OptionsOpCodeHandle
, // Option Opcode list
1374 NULL
// Default Opcode is NULL
1378 Status
= HiiUpdateForm (
1379 mCallbackInfo
->RegisteredHandle
, // HII handle
1380 &mVendorGuid
, // Formset GUID
1381 FORMID_ORDER_FORM
, // Form ID
1382 StartOpCodeHandle
, // Label for where to insert opcodes
1383 EndOpCodeHandle
// Replace data
1387 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1388 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1389 if (OptionsOpCodeHandle
!= NULL
) {
1390 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
1398 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order.
1400 @param[in] IfrNvData The IFR nv data.
1402 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1404 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1405 @retval EFI_SUCCESS The operation is completed successfully.
1409 IScsiConfigOrderAttempts (
1410 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1416 UINT8 AttemptConfigIndex
;
1417 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1418 UINT8
*AttemptConfigOrder
;
1419 UINT8
*AttemptConfigOrderTmp
;
1420 UINTN AttemptConfigOrderSize
;
1422 AttemptConfigOrder
= IScsiGetVariableAndSize (
1425 &AttemptConfigOrderSize
1427 if (AttemptConfigOrder
== NULL
) {
1428 return EFI_NOT_FOUND
;
1431 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
1432 if (AttemptConfigOrderTmp
== NULL
) {
1433 Status
= EFI_OUT_OF_RESOURCES
;
1437 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
1439 // The real content ends with 0.
1441 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
1445 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
1446 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
1447 if (AttemptConfigData
== NULL
) {
1448 Status
= EFI_NOT_FOUND
;
1453 // Reorder the Attempt List.
1455 RemoveEntryList (&AttemptConfigData
->Link
);
1456 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
1458 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
1461 // Mark it to be deleted - 0.
1463 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1464 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
1465 AttemptConfigOrder
[Indexj
] = 0;
1472 // Adjust the attempt order in NVR.
1474 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
1475 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
1476 if (AttemptConfigOrder
[Indexj
] != 0) {
1477 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
1478 AttemptConfigOrder
[Indexj
] = 0;
1484 Status
= gRT
->SetVariable (
1487 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1488 AttemptConfigOrderSize
,
1489 AttemptConfigOrderTmp
1493 if (AttemptConfigOrderTmp
!= NULL
) {
1494 FreePool (AttemptConfigOrderTmp
);
1497 FreePool (AttemptConfigOrder
);
1503 Callback function when a user presses "Attempt *" or when a user selects a NIC to
1504 create the new attempt.
1506 @param[in] KeyValue A unique value which is sent to the original
1507 exporting driver so that it can identify the type
1509 @param[in] IfrNvData The IFR nv data.
1511 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1513 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1514 @retval EFI_SUCCESS The operation is completed successfully.
1518 IScsiConfigProcessDefault (
1519 IN EFI_QUESTION_ID KeyValue
,
1520 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
1524 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1525 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
1526 UINT8 CurrentAttemptConfigIndex
;
1527 ISCSI_NIC_INFO
*NicInfo
;
1529 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1530 UINT8
*AttemptConfigOrder
;
1531 UINTN AttemptConfigOrderSize
;
1533 UINT8
*AttemptOrderTmp
;
1539 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
1540 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
1542 // User has pressed "Add an Attempt" and then selects a NIC.
1545 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
1546 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
1549 // User has pressed "Attempt *".
1554 // Don't process anything.
1561 // Determine which NIC user has selected for the new created attempt.
1563 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
1564 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
1565 if (NicInfo
== NULL
) {
1566 return EFI_NOT_FOUND
;
1570 // Create the new attempt and save to NVR.
1573 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
1574 if (AttemptConfigData
== NULL
) {
1575 return EFI_OUT_OF_RESOURCES
;
1578 ConfigData
= &AttemptConfigData
->SessionConfigData
;
1579 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1580 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1581 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
1583 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
1584 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
1587 // Get current order number for this attempt.
1589 AttemptConfigOrder
= IScsiGetVariableAndSize (
1592 &AttemptConfigOrderSize
1595 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1597 if (AttemptConfigOrder
== NULL
) {
1598 CurrentAttemptConfigIndex
= 1;
1601 // Get the max attempt config index.
1603 CurrentAttemptConfigIndex
= AttemptConfigOrder
[0];
1604 for (Index
= 1; Index
< TotalNumber
; Index
++) {
1605 if (CurrentAttemptConfigIndex
< AttemptConfigOrder
[Index
]) {
1606 CurrentAttemptConfigIndex
= AttemptConfigOrder
[Index
];
1610 CurrentAttemptConfigIndex
++;
1616 // Append the new created attempt order to the end.
1618 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
1619 if (AttemptOrderTmp
== NULL
) {
1620 FreePool (AttemptConfigData
);
1621 if (AttemptConfigOrder
!= NULL
) {
1622 FreePool (AttemptConfigOrder
);
1624 return EFI_OUT_OF_RESOURCES
;
1627 if (AttemptConfigOrder
!= NULL
) {
1628 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
1629 FreePool (AttemptConfigOrder
);
1632 AttemptOrderTmp
[TotalNumber
- 1] = CurrentAttemptConfigIndex
;
1633 AttemptConfigOrder
= AttemptOrderTmp
;
1634 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
1636 Status
= gRT
->SetVariable (
1639 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1640 AttemptConfigOrderSize
,
1643 FreePool (AttemptConfigOrder
);
1644 if (EFI_ERROR (Status
)) {
1645 FreePool (AttemptConfigData
);
1650 // Record the mapping between attempt order and attempt's configdata.
1652 AttemptConfigData
->AttemptConfigIndex
= CurrentAttemptConfigIndex
;
1653 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
1654 mPrivate
->AttemptCount
++;
1657 // Record the MAC info in Config Data.
1660 &NicInfo
->PermanentAddress
,
1661 NicInfo
->HwAddressSize
,
1666 UnicodeStrToAsciiStr (MacString
, AttemptConfigData
->MacString
);
1667 AttemptConfigData
->NicIndex
= NicIndex
;
1670 // Generate OUI-format ISID based on MAC address.
1672 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
1673 AttemptConfigData
->SessionConfigData
.IsId
[0] =
1674 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
1677 // Add the help info for the new attempt.
1680 mPrivate
->PortString
,
1681 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1682 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
1685 NicInfo
->DeviceNumber
,
1686 NicInfo
->FunctionNumber
1689 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
1690 mCallbackInfo
->RegisteredHandle
,
1692 mPrivate
->PortString
,
1695 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
1696 FreePool (AttemptConfigData
);
1697 return EFI_INVALID_PARAMETER
;
1701 // Set the attempt name to default.
1704 mPrivate
->PortString
,
1707 (UINTN
) AttemptConfigData
->AttemptConfigIndex
1709 UnicodeStrToAsciiStr (mPrivate
->PortString
, AttemptConfigData
->AttemptName
);
1713 // Determine which Attempt user has selected to configure.
1714 // Get the attempt configuration data.
1716 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
1718 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
1719 if (AttemptConfigData
== NULL
) {
1720 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
1721 return EFI_NOT_FOUND
;
1726 // Clear the old IFR data to avoid sharing it with other attempts.
1728 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1729 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
1730 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
1731 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
1732 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
1735 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
1737 mCallbackInfo
->Current
= AttemptConfigData
;
1739 IScsiConfigUpdateAttempt ();
1747 This function allows the caller to request the current
1748 configuration for one or more named elements. The resulting
1749 string is in <ConfigAltResp> format. Also, any and all alternative
1750 configuration strings shall be appended to the end of the
1751 current configuration string. If they are, they must appear
1752 after the current configuration. They must contain the same
1753 routing (GUID, NAME, PATH) as the current configuration string.
1754 They must have an additional description indicating the type of
1755 alternative configuration the string represents,
1756 "ALTCFG=<StringToken>". That <StringToken> (when
1757 converted from Hex UNICODE to binary) is a reference to a
1758 string in the associated string pack.
1760 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1762 @param[in] Request A null-terminated Unicode string in
1763 <ConfigRequest> format. Note that this
1764 includes the routing information as well as
1765 the configurable name / value pairs. It is
1766 invalid for this string to be in
1767 <MultiConfigRequest> format.
1769 @param[out] Progress On return, points to a character in the
1770 Request string. Points to the string's null
1771 terminator if request was successful. Points
1772 to the most recent "&" before the first
1773 failing name / value pair (or the beginning
1774 of the string if the failure is in the first
1775 name / value pair) if the request was not successful.
1777 @param[out] Results A null-terminated Unicode string in
1778 <ConfigAltResp> format which has all values
1779 filled in for the names in the Request string.
1780 String to be allocated by the called function.
1782 @retval EFI_SUCCESS The Results string is filled with the
1783 values corresponding to all requested
1786 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1787 parts of the results that must be
1788 stored awaiting possible future
1791 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
1792 for the Request parameter
1793 would result in this type of
1794 error. In this case, the
1795 Progress parameter would be
1798 @retval EFI_NOT_FOUND Routing data doesn't match any
1799 known driver. Progress set to the
1800 first character in the routing header.
1801 Note: There is no requirement that the
1802 driver validate the routing data. It
1803 must skip the <ConfigHdr> in order to
1806 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
1807 to most recent "&" before the
1808 error or the beginning of the
1811 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
1812 to the & before the name in
1818 IScsiFormExtractConfig (
1819 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1820 IN CONST EFI_STRING Request
,
1821 OUT EFI_STRING
*Progress
,
1822 OUT EFI_STRING
*Results
1826 CHAR8
*InitiatorName
;
1828 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
1829 ISCSI_FORM_CALLBACK_INFO
*Private
;
1830 EFI_STRING ConfigRequestHdr
;
1831 EFI_STRING ConfigRequest
;
1832 BOOLEAN AllocatedRequest
;
1835 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
1836 return EFI_INVALID_PARAMETER
;
1839 *Progress
= Request
;
1840 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &mVendorGuid
, mVendorStorageName
)) {
1841 return EFI_NOT_FOUND
;
1844 ConfigRequestHdr
= NULL
;
1845 ConfigRequest
= NULL
;
1846 AllocatedRequest
= FALSE
;
1849 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
1850 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
1851 if (IfrNvData
== NULL
) {
1852 return EFI_OUT_OF_RESOURCES
;
1855 if (Private
->Current
!= NULL
) {
1856 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
1859 BufferSize
= ISCSI_NAME_MAX_SIZE
;
1860 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
1861 if (InitiatorName
== NULL
) {
1862 FreePool (IfrNvData
);
1863 return EFI_OUT_OF_RESOURCES
;
1866 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
1867 if (EFI_ERROR (Status
)) {
1868 IfrNvData
->InitiatorName
[0] = L
'\0';
1870 AsciiStrToUnicodeStr (InitiatorName
, IfrNvData
->InitiatorName
);
1874 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
1876 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
1877 ConfigRequest
= Request
;
1878 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
1880 // Request has no request element, construct full request string.
1881 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1882 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
1884 ConfigRequestHdr
= HiiConstructConfigHdr (&mVendorGuid
, mVendorStorageName
, Private
->DriverHandle
);
1885 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
1886 ConfigRequest
= AllocateZeroPool (Size
);
1887 ASSERT (ConfigRequest
!= NULL
);
1888 AllocatedRequest
= TRUE
;
1889 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
1890 FreePool (ConfigRequestHdr
);
1893 Status
= gHiiConfigRouting
->BlockToConfig (
1896 (UINT8
*) IfrNvData
,
1901 FreePool (IfrNvData
);
1902 FreePool (InitiatorName
);
1905 // Free the allocated config request string.
1907 if (AllocatedRequest
) {
1908 FreePool (ConfigRequest
);
1909 ConfigRequest
= NULL
;
1912 // Set Progress string to the original request string.
1914 if (Request
== NULL
) {
1916 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
1917 *Progress
= Request
+ StrLen (Request
);
1926 This function applies changes in a driver's configuration.
1927 Input is a Configuration, which has the routing data for this
1928 driver followed by name / value configuration pairs. The driver
1929 must apply those pairs to its configurable storage. If the
1930 driver's configuration is stored in a linear block of data
1931 and the driver's name / value pairs are in <BlockConfig>
1932 format, it may use the ConfigToBlock helper function (above) to
1935 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1937 @param[in] Configuration A null-terminated Unicode string in
1938 <ConfigString> format.
1940 @param[out] Progress A pointer to a string filled in with the
1941 offset of the most recent '&' before the
1942 first failing name / value pair (or the
1943 beginning of the string if the failure
1944 is in the first name / value pair) or
1945 the terminating NULL if all was
1948 @retval EFI_SUCCESS The results have been distributed or are
1949 awaiting distribution.
1951 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1952 parts of the results that must be
1953 stored awaiting possible future
1956 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
1957 Results parameter would result
1958 in this type of error.
1960 @retval EFI_NOT_FOUND Target for the specified routing data
1966 IScsiFormRouteConfig (
1967 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1968 IN CONST EFI_STRING Configuration
,
1969 OUT EFI_STRING
*Progress
1972 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
1973 return EFI_INVALID_PARAMETER
;
1977 // Check routing data in <ConfigHdr>.
1978 // Note: if only one Storage is used, then this checking could be skipped.
1980 if (!HiiIsConfigHdrMatch (Configuration
, &mVendorGuid
, mVendorStorageName
)) {
1981 *Progress
= Configuration
;
1982 return EFI_NOT_FOUND
;
1985 *Progress
= Configuration
+ StrLen (Configuration
);
1992 This function is called to provide results data to the driver.
1993 This data consists of a unique key that is used to identify
1994 which data is either being passed back or being asked for.
1996 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1997 @param[in] Action Specifies the type of action taken by the browser.
1998 @param[in] QuestionId A unique value which is sent to the original
1999 exporting driver so that it can identify the type
2000 of data to expect. The format of the data tends to
2001 vary based on the opcode that generated the callback.
2002 @param[in] Type The type of value for the question.
2003 @param[in, out] Value A pointer to the data being sent to the original
2005 @param[out] ActionRequest On return, points to the action requested by the
2008 @retval EFI_SUCCESS The callback successfully handled the action.
2009 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2010 variable and its data.
2011 @retval EFI_DEVICE_ERROR The variable could not be saved.
2012 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2018 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2019 IN EFI_BROWSER_ACTION Action
,
2020 IN EFI_QUESTION_ID QuestionId
,
2022 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
2023 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2026 ISCSI_FORM_CALLBACK_INFO
*Private
;
2029 CHAR8 IpString
[IP_STR_MAX_SIZE
];
2030 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
2032 EFI_IP_ADDRESS HostIp
;
2033 EFI_IP_ADDRESS SubnetMask
;
2034 EFI_IP_ADDRESS Gateway
;
2035 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
2036 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
2038 CHAR16 AttemptName
[ATTEMPT_NAME_SIZE
+ 4];
2041 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
2043 // Do nothing for UEFI OPEN/CLOSE Action
2048 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2049 if (This
== NULL
|| Value
== NULL
|| ActionRequest
== NULL
) {
2050 return EFI_INVALID_PARAMETER
;
2053 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
2056 // Retrieve uncommitted data from Browser
2059 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2060 IfrNvData
= AllocateZeroPool (BufferSize
);
2061 if (IfrNvData
== NULL
) {
2062 return EFI_OUT_OF_RESOURCES
;
2065 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
2066 if (IScsiName
== NULL
) {
2067 FreePool (IfrNvData
);
2068 return EFI_OUT_OF_RESOURCES
;
2071 Status
= EFI_SUCCESS
;
2073 ZeroMem (&OldIfrNvData
, BufferSize
);
2075 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2077 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
2079 switch (QuestionId
) {
2080 case KEY_INITIATOR_NAME
:
2081 UnicodeStrToAsciiStr (IfrNvData
->InitiatorName
, IScsiName
);
2082 BufferSize
= AsciiStrSize (IScsiName
);
2084 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
2085 if (EFI_ERROR (Status
)) {
2087 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2089 L
"Invalid iSCSI Name!",
2094 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2097 case KEY_ADD_ATTEMPT
:
2098 Status
= IScsiConfigAddAttempt ();
2101 case KEY_DELETE_ATTEMPT
:
2103 OldIfrNvData
.DeleteAttemptList
,
2104 IfrNvData
->DeleteAttemptList
,
2105 sizeof (IfrNvData
->DeleteAttemptList
)
2107 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
2110 case KEY_SAVE_DELETE_ATTEMPT
:
2112 // Delete the Attempt Order from NVR
2114 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
2115 if (EFI_ERROR (Status
)) {
2119 IScsiConfigUpdateAttempt ();
2120 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2123 case KEY_IGNORE_DELETE_ATTEMPT
:
2125 IfrNvData
->DeleteAttemptList
,
2126 OldIfrNvData
.DeleteAttemptList
,
2127 sizeof (IfrNvData
->DeleteAttemptList
)
2129 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2132 case KEY_ORDER_ATTEMPT_CONFIG
:
2134 // Order the attempt according to user input.
2137 OldIfrNvData
.DynamicOrderedList
,
2138 IfrNvData
->DynamicOrderedList
,
2139 sizeof (IfrNvData
->DynamicOrderedList
)
2141 IScsiConfigDisplayOrderAttempts ();
2144 case KEY_SAVE_ORDER_CHANGES
:
2146 // Sync the Attempt Order to NVR.
2148 Status
= IScsiConfigOrderAttempts (IfrNvData
);
2149 if (EFI_ERROR (Status
)) {
2153 IScsiConfigUpdateAttempt ();
2154 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2157 case KEY_IGNORE_ORDER_CHANGES
:
2159 IfrNvData
->DynamicOrderedList
,
2160 OldIfrNvData
.DynamicOrderedList
,
2161 sizeof (IfrNvData
->DynamicOrderedList
)
2163 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2166 case KEY_ATTEMPT_NAME
:
2167 if (StrLen (IfrNvData
->AttemptName
) > ATTEMPT_NAME_SIZE
) {
2168 CopyMem (AttemptName
, IfrNvData
->AttemptName
, ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
2169 CopyMem (&AttemptName
[ATTEMPT_NAME_SIZE
], L
"...", 4 * sizeof (CHAR16
));
2173 IfrNvData
->AttemptName
,
2174 (StrLen (IfrNvData
->AttemptName
) + 1) * sizeof (CHAR16
)
2178 UnicodeStrToAsciiStr (IfrNvData
->AttemptName
, Private
->Current
->AttemptName
);
2180 IScsiConfigUpdateAttempt ();
2182 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2186 switch (Value
->u8
) {
2188 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2189 IScsiIpToStr (&Private
->Current
->SessionConfigData
.TargetIp
, TRUE
, IfrNvData
->TargetIp
);
2190 Private
->Current
->AutoConfigureMode
= 0;
2194 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
2195 IScsiIpToStr (&Private
->Current
->SessionConfigData
.TargetIp
, FALSE
, IfrNvData
->TargetIp
);
2196 Private
->Current
->AutoConfigureMode
= 0;
2204 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
2205 if (EFI_ERROR (Status
) || !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
2207 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2209 L
"Invalid IP address!",
2213 Status
= EFI_INVALID_PARAMETER
;
2215 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
2220 case KEY_SUBNET_MASK
:
2221 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
2222 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
2224 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2226 L
"Invalid Subnet Mask!",
2230 Status
= EFI_INVALID_PARAMETER
;
2232 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
2238 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
2239 if (EFI_ERROR (Status
) || ((Gateway
.Addr
[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), 0))) {
2241 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2243 L
"Invalid Gateway!",
2246 Status
= EFI_INVALID_PARAMETER
;
2248 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
2254 UnicodeStrToAsciiStr (IfrNvData
->TargetIp
, IpString
);
2255 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
2256 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
2258 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2260 L
"Invalid IP address!",
2263 Status
= EFI_INVALID_PARAMETER
;
2265 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
2270 case KEY_TARGET_NAME
:
2271 UnicodeStrToAsciiStr (IfrNvData
->TargetName
, IScsiName
);
2272 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
2273 if (EFI_ERROR (Status
)) {
2275 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2277 L
"Invalid iSCSI Name!",
2281 AsciiStrCpy (Private
->Current
->SessionConfigData
.TargetName
, IScsiName
);
2286 case KEY_DHCP_ENABLE
:
2287 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
2288 IfrNvData
->TargetInfoFromDhcp
= 0;
2294 UnicodeStrToAsciiStr (IfrNvData
->BootLun
, LunString
);
2295 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
2296 if (EFI_ERROR (Status
)) {
2298 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2300 L
"Invalid LUN string!",
2304 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
2310 switch (Value
->u8
) {
2311 case ISCSI_AUTH_TYPE_CHAP
:
2312 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
2321 UnicodeStrToAsciiStr (
2322 IfrNvData
->CHAPName
,
2323 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
2327 case KEY_CHAP_SECRET
:
2328 UnicodeStrToAsciiStr (
2329 IfrNvData
->CHAPSecret
,
2330 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
2334 case KEY_REVERSE_CHAP_NAME
:
2335 UnicodeStrToAsciiStr (
2336 IfrNvData
->ReverseCHAPName
,
2337 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
2341 case KEY_REVERSE_CHAP_SECRET
:
2342 UnicodeStrToAsciiStr (
2343 IfrNvData
->ReverseCHAPSecret
,
2344 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
2348 case KEY_CONFIG_ISID
:
2349 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2350 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
2354 case KEY_SAVE_ATTEMPT_CONFIG
:
2355 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
2356 if (EFI_ERROR (Status
)) {
2360 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2364 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
2368 if (!EFI_ERROR (Status
)) {
2370 // Pass changed uncommitted data back to Form Browser.
2372 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
2373 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2376 FreePool (IfrNvData
);
2377 FreePool (IScsiName
);
2383 // All other action return unsupported.
2385 return EFI_UNSUPPORTED
;
2390 Initialize the iSCSI configuration form.
2392 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2394 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
2395 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2399 IScsiConfigFormInit (
2400 IN EFI_HANDLE DriverBindingHandle
2404 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
2406 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
2407 if (CallbackInfo
== NULL
) {
2408 return EFI_OUT_OF_RESOURCES
;
2411 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
2412 CallbackInfo
->Current
= NULL
;
2414 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
2415 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
2416 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
2419 // Install Device Path Protocol and Config Access protocol to driver handle.
2421 Status
= gBS
->InstallMultipleProtocolInterfaces (
2422 &CallbackInfo
->DriverHandle
,
2423 &gEfiDevicePathProtocolGuid
,
2424 &mIScsiHiiVendorDevicePath
,
2425 &gEfiHiiConfigAccessProtocolGuid
,
2426 &CallbackInfo
->ConfigAccess
,
2429 ASSERT_EFI_ERROR (Status
);
2432 // Publish our HII data.
2434 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
2436 CallbackInfo
->DriverHandle
,
2441 if (CallbackInfo
->RegisteredHandle
== NULL
) {
2442 gBS
->UninstallMultipleProtocolInterfaces (
2443 &CallbackInfo
->DriverHandle
,
2444 &gEfiDevicePathProtocolGuid
,
2445 &mIScsiHiiVendorDevicePath
,
2446 &gEfiHiiConfigAccessProtocolGuid
,
2447 &CallbackInfo
->ConfigAccess
,
2450 FreePool(CallbackInfo
);
2451 return EFI_OUT_OF_RESOURCES
;
2454 mCallbackInfo
= CallbackInfo
;
2461 Unload the iSCSI configuration form, this includes: delete all the iSCSI
2462 configuration entries, uninstall the form callback protocol, and
2463 free the resources used.
2465 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2467 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
2468 @retval Others Failed to unload the form.
2472 IScsiConfigFormUnload (
2473 IN EFI_HANDLE DriverBindingHandle
2476 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2477 ISCSI_NIC_INFO
*NicInfo
;
2481 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
2482 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
2483 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2484 FreePool (AttemptConfigData
);
2485 mPrivate
->AttemptCount
--;
2488 ASSERT (mPrivate
->AttemptCount
== 0);
2490 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
2491 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
2492 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
2494 mPrivate
->NicCount
--;
2497 ASSERT (mPrivate
->NicCount
== 0);
2499 FreePool (mPrivate
);
2503 // Remove HII package list.
2505 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
2508 // Uninstall Device Path Protocol and Config Access protocol.
2510 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2511 mCallbackInfo
->DriverHandle
,
2512 &gEfiDevicePathProtocolGuid
,
2513 &mIScsiHiiVendorDevicePath
,
2514 &gEfiHiiConfigAccessProtocolGuid
,
2515 &mCallbackInfo
->ConfigAccess
,
2519 FreePool (mCallbackInfo
);