]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IScsiDxe/IScsiConfig.c
NetworkPkg/IScsiDxe: Remove unused global variables.
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiConfig.c
1 /** @file
2 Helper functions for configuring or getting the parameters relating to iSCSI.
3
4 Copyright (c) 2004 - 2018, 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
9
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.
12
13 **/
14
15 #include "IScsiImpl.h"
16
17 CHAR16 mVendorStorageName[] = L"ISCSI_CONFIG_IFR_NVDATA";
18 ISCSI_FORM_CALLBACK_INFO *mCallbackInfo = NULL;
19
20 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath = {
21 {
22 {
23 HARDWARE_DEVICE_PATH,
24 HW_VENDOR_DP,
25 {
26 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
27 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
28 }
29 },
30 ISCSI_CONFIG_GUID
31 },
32 {
33 END_DEVICE_PATH_TYPE,
34 END_ENTIRE_DEVICE_PATH_SUBTYPE,
35 {
36 (UINT8) (END_DEVICE_PATH_LENGTH),
37 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
38 }
39 }
40 };
41
42
43 /**
44 Convert the IP address into a dotted string.
45
46 @param[in] Ip The IP address.
47 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.
48 @param[out] Str The formatted IP string.
49
50 **/
51 VOID
52 IScsiIpToStr (
53 IN EFI_IP_ADDRESS *Ip,
54 IN BOOLEAN Ipv6Flag,
55 OUT CHAR16 *Str
56 )
57 {
58 EFI_IPv4_ADDRESS *Ip4;
59 EFI_IPv6_ADDRESS *Ip6;
60 UINTN Index;
61 BOOLEAN Short;
62 UINTN Number;
63 CHAR16 FormatString[8];
64
65 if (!Ipv6Flag) {
66 Ip4 = &Ip->v4;
67
68 UnicodeSPrint (
69 Str,
70 (UINTN) 2 * IP4_STR_MAX_SIZE,
71 L"%d.%d.%d.%d",
72 (UINTN) Ip4->Addr[0],
73 (UINTN) Ip4->Addr[1],
74 (UINTN) Ip4->Addr[2],
75 (UINTN) Ip4->Addr[3]
76 );
77
78 return ;
79 }
80
81 Ip6 = &Ip->v6;
82 Short = FALSE;
83
84 for (Index = 0; Index < 15; Index = Index + 2) {
85 if (!Short &&
86 Index % 2 == 0 &&
87 Ip6->Addr[Index] == 0 &&
88 Ip6->Addr[Index + 1] == 0
89 ) {
90 //
91 // Deal with the case of ::.
92 //
93 if (Index == 0) {
94 *Str = L':';
95 *(Str + 1) = L':';
96 Str = Str + 2;
97 } else {
98 *Str = L':';
99 Str = Str + 1;
100 }
101
102 while ((Index < 15) && (Ip6->Addr[Index] == 0) && (Ip6->Addr[Index + 1] == 0)) {
103 Index = Index + 2;
104 }
105
106 Short = TRUE;
107
108 if (Index == 16) {
109 //
110 // :: is at the end of the address.
111 //
112 *Str = L'\0';
113 break;
114 }
115 }
116
117 ASSERT (Index < 15);
118
119 if (Ip6->Addr[Index] == 0) {
120 Number = UnicodeSPrint (Str, 2 * IP_STR_MAX_SIZE, L"%x:", (UINTN) Ip6->Addr[Index + 1]);
121 } else {
122 if (Ip6->Addr[Index + 1] < 0x10) {
123 CopyMem (FormatString, L"%x0%x:", StrSize (L"%x0%x:"));
124 } else {
125 CopyMem (FormatString, L"%x%x:", StrSize (L"%x%x:"));
126 }
127
128 Number = UnicodeSPrint (
129 Str,
130 2 * IP_STR_MAX_SIZE,
131 (CONST CHAR16 *) FormatString,
132 (UINTN) Ip6->Addr[Index],
133 (UINTN) Ip6->Addr[Index + 1]
134 );
135 }
136
137 Str = Str + Number;
138
139 if (Index + 2 == 16) {
140 *Str = L'\0';
141 if (*(Str - 1) == L':') {
142 *(Str - 1) = L'\0';
143 }
144 }
145 }
146 }
147
148 /**
149 Check whether the input IP address is valid.
150
151 @param[in] Ip The IP address.
152 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.
153
154 @retval TRUE The input IP address is valid.
155 @retval FALSE Otherwise
156
157 **/
158 BOOLEAN
159 IpIsUnicast (
160 IN EFI_IP_ADDRESS *Ip,
161 IN UINT8 IpMode
162 )
163 {
164 if (IpMode == IP_MODE_IP4) {
165 if (IP4_IS_UNSPECIFIED (NTOHL (Ip->Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip->Addr[0]))) {
166 return FALSE;
167 }
168 return TRUE;
169 } else if (IpMode == IP_MODE_IP6) {
170 return NetIp6IsValidUnicast (&Ip->v6);
171 } else {
172 DEBUG ((DEBUG_ERROR, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode));
173 return FALSE;
174 }
175 }
176
177 /**
178 Parse IsId in string format and convert it to binary.
179
180 @param[in] String The buffer of the string to be parsed.
181 @param[in, out] IsId The buffer to store IsId.
182
183 @retval EFI_SUCCESS The operation finished successfully.
184 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
185
186 **/
187 EFI_STATUS
188 IScsiParseIsIdFromString (
189 IN CONST CHAR16 *String,
190 IN OUT UINT8 *IsId
191 )
192 {
193 UINT8 Index;
194 CHAR16 *IsIdStr;
195 CHAR16 TempStr[3];
196 UINTN NodeVal;
197 CHAR16 PortString[ISCSI_NAME_IFR_MAX_SIZE];
198 EFI_INPUT_KEY Key;
199
200 if ((String == NULL) || (IsId == NULL)) {
201 return EFI_INVALID_PARAMETER;
202 }
203
204 IsIdStr = (CHAR16 *) String;
205
206 if (StrLen (IsIdStr) != 6 && StrLen (IsIdStr) != 12) {
207 UnicodeSPrint (
208 PortString,
209 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
210 L"Error! Only last 3 bytes are configurable, please input 6 hex numbers for last 3 bytes only or 12 hex numbers for full SSID!\n"
211 );
212
213 CreatePopUp (
214 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
215 &Key,
216 PortString,
217 NULL
218 );
219
220 return EFI_INVALID_PARAMETER;
221 }
222
223 if (StrLen (IsIdStr) == 12) {
224 IsIdStr += 6;
225 }
226
227 for (Index = 3; Index < 6; Index++) {
228 CopyMem (TempStr, IsIdStr, sizeof (TempStr));
229 TempStr[2] = L'\0';
230
231 //
232 // Convert the string to IsId. StrHexToUintn stops at the first character
233 // that is not a valid hex character, '\0' here.
234 //
235 NodeVal = StrHexToUintn (TempStr);
236
237 IsId[Index] = (UINT8) NodeVal;
238
239 IsIdStr = IsIdStr + 2;
240 }
241
242 return EFI_SUCCESS;
243 }
244
245 /**
246 Convert IsId from binary to string format.
247
248 @param[out] String The buffer to store the converted string.
249 @param[in] IsId The buffer to store IsId.
250
251 @retval EFI_SUCCESS The string converted successfully.
252 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
253
254 **/
255 EFI_STATUS
256 IScsiConvertIsIdToString (
257 OUT CHAR16 *String,
258 IN UINT8 *IsId
259 )
260 {
261 UINT8 Index;
262 UINTN Number;
263
264 if ((String == NULL) || (IsId == NULL)) {
265 return EFI_INVALID_PARAMETER;
266 }
267
268 for (Index = 0; Index < 6; Index++) {
269 if (IsId[Index] <= 0xF) {
270 Number = UnicodeSPrint (
271 String,
272 2 * ISID_CONFIGURABLE_STORAGE,
273 L"0%X",
274 (UINTN) IsId[Index]
275 );
276 } else {
277 Number = UnicodeSPrint (
278 String,
279 2 * ISID_CONFIGURABLE_STORAGE,
280 L"%X",
281 (UINTN) IsId[Index]
282 );
283
284 }
285
286 String = String + Number;
287 }
288
289 *String = L'\0';
290
291 return EFI_SUCCESS;
292 }
293
294 /**
295 Get the Offset value specified by the input String.
296
297 @param[in] Configuration A null-terminated Unicode string in
298 <ConfigString> format.
299 @param[in] String The string is "&OFFSET=".
300 @param[out] Value The Offset value.
301
302 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
303 structures.
304 @retval EFI_SUCCESS Value of <Number> is outputted in Number
305 successfully.
306
307 **/
308 EFI_STATUS
309 IScsiGetValue (
310 IN CONST EFI_STRING Configuration,
311 IN CHAR16 *String,
312 OUT UINTN *Value
313 )
314 {
315 CHAR16 *StringPtr;
316 CHAR16 *TmpPtr;
317 CHAR16 *Str;
318 CHAR16 TmpStr[2];
319 UINTN Length;
320 UINTN Len;
321 UINTN Index;
322 UINT8 *Buf;
323 UINT8 DigitUint8;
324 EFI_STATUS Status;
325
326 //
327 // Get Value.
328 //
329 Buf = NULL;
330 StringPtr = StrStr (Configuration, String);
331 ASSERT(StringPtr != NULL);
332 StringPtr += StrLen (String);
333 TmpPtr = StringPtr;
334
335 while (*StringPtr != L'\0' && *StringPtr != L'&') {
336 StringPtr ++;
337 }
338 Length = StringPtr - TmpPtr;
339 Len = Length + 1;
340
341 Str = AllocateZeroPool (Len * sizeof (CHAR16));
342 if (Str == NULL) {
343 Status = EFI_OUT_OF_RESOURCES;
344 goto Exit;
345 }
346
347 CopyMem (Str, TmpPtr, Len * sizeof (CHAR16));
348 *(Str + Length) = L'\0';
349
350 Len = (Len + 1) / 2;
351 Buf = (UINT8 *) AllocateZeroPool (Len);
352 if (Buf == NULL) {
353 Status = EFI_OUT_OF_RESOURCES;
354 goto Exit;
355 }
356
357 ZeroMem (TmpStr, sizeof (TmpStr));
358 for (Index = 0; Index < Length; Index ++) {
359 TmpStr[0] = Str[Length - Index - 1];
360 DigitUint8 = (UINT8) StrHexToUint64 (TmpStr);
361 if ((Index & 1) == 0) {
362 Buf [Index/2] = DigitUint8;
363 } else {
364 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
365 }
366 }
367
368 *Value = 0;
369 CopyMem (
370 Value,
371 Buf,
372 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
373 );
374
375 FreePool (Buf);
376 Status = EFI_SUCCESS;
377
378 Exit:
379 if (Str != NULL) {
380 FreePool (Str);
381 }
382
383 return Status;
384 }
385
386 /**
387 Get the attempt config data from global structure by the ConfigIndex.
388
389 @param[in] AttemptConfigIndex The unique index indicates the attempt.
390
391 @return Pointer to the attempt config data.
392 @retval NULL The attempt configuration data cannot be found.
393
394 **/
395 ISCSI_ATTEMPT_CONFIG_NVDATA *
396 IScsiConfigGetAttemptByConfigIndex (
397 IN UINT8 AttemptConfigIndex
398 )
399 {
400 LIST_ENTRY *Entry;
401 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;
402
403 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
404 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
405 if (Attempt->AttemptConfigIndex == AttemptConfigIndex) {
406 return Attempt;
407 }
408 }
409
410 return NULL;
411 }
412
413
414 /**
415 Get the existing attempt config data from global structure by the NicIndex.
416
417 @param[in] NewAttempt The created new attempt
418 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
419 Enabled for MPIO.
420
421 @return Pointer to the existing attempt config data which
422 has the same NICIndex as the new created attempt.
423 @retval NULL The attempt with NicIndex does not exist.
424
425 **/
426 ISCSI_ATTEMPT_CONFIG_NVDATA *
427 IScsiConfigGetAttemptByNic (
428 IN ISCSI_ATTEMPT_CONFIG_NVDATA *NewAttempt,
429 IN UINT8 IScsiMode
430 )
431 {
432 LIST_ENTRY *Entry;
433 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;
434
435 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
436 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
437 if (Attempt != NewAttempt && Attempt->NicIndex == NewAttempt->NicIndex &&
438 Attempt->SessionConfigData.Enabled == IScsiMode) {
439 return Attempt;
440 }
441 }
442
443 return NULL;
444 }
445
446 /**
447 Extract the Index of the attempt list.
448
449 @param[in] AttemptNameList The Name list of the Attempts.
450 @param[out] AttemptIndexList The Index list of the Attempts.
451 @param[in] IsAddAttempts If TRUE, Indicates add one or more attempts.
452 If FALSE, Indicates delete attempts or change attempt order.
453
454 @retval EFI_SUCCESS The Attempt list is valid.
455 @retval EFI_INVALID_PARAMETERS The Attempt List is invalid.
456
457 **/
458 EFI_STATUS
459 IScsiGetAttemptIndexList (
460 IN CHAR16 *AttemptNameList,
461 OUT UINT8 *AttemptIndexList,
462 IN BOOLEAN IsAddAttempts
463 )
464 {
465 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
466 CHAR16 *AttemptStr;
467 UINT8 AttemptIndex;
468 UINTN Len;
469 UINTN Index;
470
471 Index = 0;
472
473 if ((AttemptNameList == NULL) || (*AttemptNameList == L'\0')) {
474 return EFI_INVALID_PARAMETER;
475 }
476
477 AttemptStr = AttemptNameList;
478 Len = StrLen (L"attempt:");
479
480 while (*AttemptStr != L'\0') {
481 AttemptStr = StrStr (AttemptStr, L"attempt:");
482 if (AttemptStr == NULL) {
483 return EFI_INVALID_PARAMETER;
484 }
485 AttemptStr += Len;
486 AttemptIndex = (UINT8)(*AttemptStr - L'0');
487 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
488 if (IsAddAttempts) {
489 if ((AttemptConfigData != NULL) || ((AttemptIndex) > PcdGet8 (PcdMaxIScsiAttemptNumber))) {
490 return EFI_INVALID_PARAMETER;
491 }
492 } else {
493 if (AttemptConfigData == NULL) {
494 return EFI_INVALID_PARAMETER;
495 }
496 }
497
498 AttemptIndexList[Index] = AttemptIndex;
499 Index ++;
500 AttemptStr += 2;
501 }
502 return EFI_SUCCESS;
503 }
504
505 /**
506 Convert the iSCSI configuration data into the IFR data.
507
508 @param[in] Attempt The iSCSI attempt config data.
509 @param[in, out] IfrNvData The IFR nv data.
510
511 **/
512 VOID
513 IScsiConvertAttemptConfigDataToIfrNvData (
514 IN ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt,
515 IN OUT ISCSI_CONFIG_IFR_NVDATA *IfrNvData
516 )
517 {
518 ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData;
519 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;
520 EFI_IP_ADDRESS Ip;
521 BOOLEAN DnsMode;
522
523 //
524 // Normal session configuration parameters.
525 //
526 SessionConfigData = &Attempt->SessionConfigData;
527 IfrNvData->Enabled = SessionConfigData->Enabled;
528 IfrNvData->IpMode = SessionConfigData->IpMode;
529 DnsMode = SessionConfigData->DnsMode;
530
531 IfrNvData->InitiatorInfoFromDhcp = SessionConfigData->InitiatorInfoFromDhcp;
532 IfrNvData->TargetInfoFromDhcp = SessionConfigData->TargetInfoFromDhcp;
533 IfrNvData->TargetPort = SessionConfigData->TargetPort;
534
535 if (IfrNvData->IpMode == IP_MODE_IP4) {
536 CopyMem (&Ip.v4, &SessionConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));
537 IScsiIpToStr (&Ip, FALSE, IfrNvData->LocalIp);
538 CopyMem (&Ip.v4, &SessionConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
539 IScsiIpToStr (&Ip, FALSE, IfrNvData->SubnetMask);
540 CopyMem (&Ip.v4, &SessionConfigData->Gateway, sizeof (EFI_IPv4_ADDRESS));
541 IScsiIpToStr (&Ip, FALSE, IfrNvData->Gateway);
542 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));
543 if (SessionConfigData->TargetIp.v4.Addr[0] != '\0') {
544 CopyMem (&Ip.v4, &SessionConfigData->TargetIp, sizeof (EFI_IPv4_ADDRESS));
545 IScsiIpToStr (&Ip, FALSE, IfrNvData->TargetIp);
546 }
547
548 } else if (IfrNvData->IpMode == IP_MODE_IP6) {
549 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));
550 if (SessionConfigData->TargetIp.v6.Addr[0] != '\0') {
551 IP6_COPY_ADDRESS (&Ip.v6, &SessionConfigData->TargetIp);
552 IScsiIpToStr (&Ip, TRUE, IfrNvData->TargetIp);
553 }
554 }
555
556 AsciiStrToUnicodeStrS (
557 SessionConfigData->TargetName,
558 IfrNvData->TargetName,
559 sizeof (IfrNvData->TargetName) / sizeof (IfrNvData->TargetName[0])
560 );
561
562 if (DnsMode) {
563 AsciiStrToUnicodeStrS (
564 SessionConfigData->TargetUrl,
565 IfrNvData->TargetIp,
566 sizeof (IfrNvData->TargetIp) / sizeof (IfrNvData->TargetIp[0])
567 );
568 }
569
570 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->BootLun);
571 IScsiConvertIsIdToString (IfrNvData->IsId, SessionConfigData->IsId);
572
573 IfrNvData->ConnectRetryCount = SessionConfigData->ConnectRetryCount;
574 IfrNvData->ConnectTimeout = SessionConfigData->ConnectTimeout;
575
576 //
577 // Authentication parameters.
578 //
579 IfrNvData->AuthenticationType = Attempt->AuthenticationType;
580
581 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
582 AuthConfigData = &Attempt->AuthConfigData.CHAP;
583 IfrNvData->CHAPType = AuthConfigData->CHAPType;
584 AsciiStrToUnicodeStrS (
585 AuthConfigData->CHAPName,
586 IfrNvData->CHAPName,
587 sizeof (IfrNvData->CHAPName) / sizeof (IfrNvData->CHAPName[0])
588 );
589 AsciiStrToUnicodeStrS (
590 AuthConfigData->CHAPSecret,
591 IfrNvData->CHAPSecret,
592 sizeof (IfrNvData->CHAPSecret) / sizeof (IfrNvData->CHAPSecret[0])
593 );
594 AsciiStrToUnicodeStrS (
595 AuthConfigData->ReverseCHAPName,
596 IfrNvData->ReverseCHAPName,
597 sizeof (IfrNvData->ReverseCHAPName) / sizeof (IfrNvData->ReverseCHAPName[0])
598 );
599 AsciiStrToUnicodeStrS (
600 AuthConfigData->ReverseCHAPSecret,
601 IfrNvData->ReverseCHAPSecret,
602 sizeof (IfrNvData->ReverseCHAPSecret) / sizeof (IfrNvData->ReverseCHAPSecret[0])
603 );
604 }
605
606 //
607 // Other parameters.
608 //
609 AsciiStrToUnicodeStrS (
610 Attempt->AttemptName,
611 IfrNvData->AttemptName,
612 sizeof (IfrNvData->AttemptName) / sizeof (IfrNvData->AttemptName[0])
613 );
614 }
615
616 /**
617 Convert the iSCSI configuration data into the IFR data Which will be used
618 to extract the iSCSI Keyword configuration in <ConfigAltResp> format.
619
620 @param[in, out] IfrNvData The IFR nv data.
621
622 **/
623 VOID
624 EFIAPI
625 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (
626 IN OUT ISCSI_CONFIG_IFR_NVDATA *IfrNvData
627 )
628 {
629 LIST_ENTRY *Entry;
630 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;
631 ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData;
632 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;
633 CHAR16 AttemptNameList[ATTEMPT_NAME_LIST_SIZE];
634 ISCSI_NIC_INFO *NicInfo;
635 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
636 EFI_IP_ADDRESS Ip;
637 UINTN Index;
638 UINTN StringLen;
639
640 NicInfo = NULL;
641 ZeroMem (AttemptNameList, sizeof (AttemptNameList));
642
643 if ((mPrivate != NULL) && (mPrivate->AttemptCount != 0)) {
644 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
645 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
646 //
647 // Normal session configuration parameters.
648 //
649 SessionConfigData = &Attempt->SessionConfigData;
650
651 ASSERT ((Attempt->AttemptConfigIndex > 0) && (Attempt->AttemptConfigIndex <= FixedPcdGet8 (PcdMaxIScsiAttemptNumber)));
652 Index = Attempt->AttemptConfigIndex - 1;
653
654 //
655 // Save the attempt to AttemptNameList as Attempt:1 Attempt:2
656 //
657 AsciiStrToUnicodeStrS (
658 Attempt->AttemptName,
659 AttemptNameList + StrLen (AttemptNameList),
660 ATTEMPT_NAME_LIST_SIZE - StrLen (AttemptNameList)
661 );
662
663 StringLen = StrLen (AttemptNameList);
664 ASSERT (StringLen > 2);
665 *(AttemptNameList + StringLen - 2) = L':';
666 *(AttemptNameList + StringLen) = L' ';
667
668 AsciiStrToUnicodeStrS (
669 Attempt->AttemptName,
670 IfrNvData->ISCSIAttemptName + ATTEMPT_NAME_SIZE * Index,
671 ATTEMPT_NAME_LIST_SIZE - ATTEMPT_NAME_SIZE * Index
672 );
673
674 IfrNvData->ISCSIBootEnableList[Index] = SessionConfigData->Enabled;
675 IfrNvData->ISCSIIpAddressTypeList[Index] = SessionConfigData->IpMode;
676
677 IfrNvData->ISCSIInitiatorInfoViaDHCP[Index] = SessionConfigData->InitiatorInfoFromDhcp;
678 IfrNvData->ISCSITargetInfoViaDHCP[Index] = SessionConfigData->TargetInfoFromDhcp;
679 IfrNvData->ISCSIConnectRetry[Index] = SessionConfigData->ConnectRetryCount;
680 IfrNvData->ISCSIConnectTimeout[Index] = SessionConfigData->ConnectTimeout;
681 IfrNvData->ISCSITargetTcpPort[Index] = SessionConfigData->TargetPort;
682
683 if (SessionConfigData->IpMode == IP_MODE_IP4) {
684 CopyMem (&Ip.v4, &SessionConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));
685 IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSIInitiatorIpAddress);
686 CopyMem (&Ip.v4, &SessionConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
687 IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSIInitiatorNetmask);
688 CopyMem (&Ip.v4, &SessionConfigData->Gateway, sizeof (EFI_IPv4_ADDRESS));
689 IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSIInitiatorGateway);
690 if (SessionConfigData->TargetIp.v4.Addr[0] != '\0') {
691 CopyMem (&Ip.v4, &SessionConfigData->TargetIp, sizeof (EFI_IPv4_ADDRESS));
692 IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSITargetIpAddress);
693 }
694 } else if (SessionConfigData->IpMode == IP_MODE_IP6) {
695 ZeroMem (IfrNvData->Keyword[Index].ISCSITargetIpAddress, sizeof (IfrNvData->TargetIp));
696 if (SessionConfigData->TargetIp.v6.Addr[0] != '\0') {
697 IP6_COPY_ADDRESS (&Ip.v6, &SessionConfigData->TargetIp);
698 IScsiIpToStr (&Ip, TRUE, IfrNvData->Keyword[Index].ISCSITargetIpAddress);
699 }
700 }
701
702 AsciiStrToUnicodeStrS (
703 SessionConfigData->TargetName,
704 IfrNvData->Keyword[Index].ISCSITargetName,
705 ISCSI_NAME_MAX_SIZE
706 );
707
708 if (SessionConfigData->DnsMode) {
709 AsciiStrToUnicodeStrS (
710 SessionConfigData->TargetUrl,
711 IfrNvData->Keyword[Index].ISCSITargetIpAddress,
712 sizeof (IfrNvData->Keyword[Index].ISCSITargetIpAddress) / sizeof (IfrNvData->Keyword[Index].ISCSITargetIpAddress[0])
713 );
714 }
715
716 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->Keyword[Index].ISCSILun);
717 IScsiConvertIsIdToString (IfrNvData->Keyword[Index].ISCSIIsId, SessionConfigData->IsId);
718
719 IfrNvData->ISCSIAuthenticationMethod[Index] = Attempt->AuthenticationType;
720
721 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
722 AuthConfigData = &Attempt->AuthConfigData.CHAP;
723 IfrNvData->ISCSIChapType[Index] = AuthConfigData->CHAPType;
724 AsciiStrToUnicodeStrS (
725 AuthConfigData->CHAPName,
726 IfrNvData->Keyword[Index].ISCSIChapUsername,
727 ISCSI_CHAP_NAME_STORAGE
728 );
729
730 AsciiStrToUnicodeStrS (
731 AuthConfigData->CHAPSecret,
732 IfrNvData->Keyword[Index].ISCSIChapSecret,
733 ISCSI_CHAP_SECRET_STORAGE
734 );
735
736 AsciiStrToUnicodeStrS (
737 AuthConfigData->ReverseCHAPName,
738 IfrNvData->Keyword[Index].ISCSIReverseChapUsername,
739 ISCSI_CHAP_NAME_STORAGE
740 );
741
742 AsciiStrToUnicodeStrS (
743 AuthConfigData->ReverseCHAPSecret,
744 IfrNvData->Keyword[Index].ISCSIReverseChapSecret,
745 ISCSI_CHAP_SECRET_STORAGE
746 );
747 }
748 }
749 CopyMem(IfrNvData->ISCSIDisplayAttemptList, AttemptNameList, ATTEMPT_NAME_LIST_SIZE);
750
751 ZeroMem (IfrNvData->ISCSIMacAddr, sizeof (IfrNvData->ISCSIMacAddr));
752 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
753 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
754 IScsiMacAddrToStr (
755 &NicInfo->PermanentAddress,
756 NicInfo->HwAddressSize,
757 NicInfo->VlanId,
758 MacString
759 );
760 CopyMem (
761 IfrNvData->ISCSIMacAddr + StrLen (IfrNvData->ISCSIMacAddr),
762 MacString,
763 StrLen (MacString) * sizeof (CHAR16)
764 );
765
766 *(IfrNvData->ISCSIMacAddr + StrLen (IfrNvData->ISCSIMacAddr)) = L'/';
767 }
768
769 StringLen = StrLen (IfrNvData->ISCSIMacAddr);
770 if (StringLen > 0) {
771 *(IfrNvData->ISCSIMacAddr + StringLen - 1) = L'\0';
772 }
773 }
774 }
775
776 /**
777 Convert the IFR data to iSCSI configuration data.
778
779 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
780 @param[in, out] Attempt The iSCSI attempt config data.
781
782 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
783 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
784 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
785 @retval EFI_ABORTED The operation is aborted.
786 @retval EFI_SUCCESS The operation is completed successfully.
787
788 **/
789 EFI_STATUS
790 IScsiConvertIfrNvDataToAttemptConfigData (
791 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData,
792 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt
793 )
794 {
795 EFI_IP_ADDRESS HostIp;
796 EFI_IP_ADDRESS SubnetMask;
797 EFI_IP_ADDRESS Gateway;
798 CHAR16 *MacString;
799 CHAR16 *AttemptName1;
800 CHAR16 *AttemptName2;
801 ISCSI_ATTEMPT_CONFIG_NVDATA *ExistAttempt;
802 ISCSI_ATTEMPT_CONFIG_NVDATA *SameNicAttempt;
803 CHAR16 IScsiMode[64];
804 CHAR16 IpMode[64];
805 ISCSI_NIC_INFO *NicInfo;
806 EFI_INPUT_KEY Key;
807 UINT8 *AttemptConfigOrder;
808 UINTN AttemptConfigOrderSize;
809 UINT8 *AttemptOrderTmp;
810 UINTN TotalNumber;
811 EFI_STATUS Status;
812
813 if (IfrNvData == NULL || Attempt == NULL) {
814 return EFI_INVALID_PARAMETER;
815 }
816
817 //
818 // Update those fields which don't have INTERACTIVE attribute.
819 //
820 Attempt->SessionConfigData.ConnectRetryCount = IfrNvData->ConnectRetryCount;
821 Attempt->SessionConfigData.ConnectTimeout = IfrNvData->ConnectTimeout;
822 Attempt->SessionConfigData.IpMode = IfrNvData->IpMode;
823
824 if (IfrNvData->IpMode < IP_MODE_AUTOCONFIG) {
825 Attempt->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp;
826 Attempt->SessionConfigData.TargetPort = IfrNvData->TargetPort;
827
828 if (Attempt->SessionConfigData.TargetPort == 0) {
829 Attempt->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;
830 }
831
832 Attempt->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp;
833 }
834
835 Attempt->AuthenticationType = IfrNvData->AuthenticationType;
836
837 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
838 Attempt->AuthConfigData.CHAP.CHAPType = IfrNvData->CHAPType;
839 }
840
841 //
842 // Only do full parameter validation if iSCSI is enabled on this device.
843 //
844 if (IfrNvData->Enabled != ISCSI_DISABLED) {
845 if (Attempt->SessionConfigData.ConnectTimeout < CONNECT_MIN_TIMEOUT) {
846 CreatePopUp (
847 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
848 &Key,
849 L"Connection Establishing Timeout is less than minimum value 100ms.",
850 NULL
851 );
852
853 return EFI_INVALID_PARAMETER;
854 }
855
856 //
857 // Validate the address configuration of the Initiator if DHCP isn't
858 // deployed.
859 //
860 if (!Attempt->SessionConfigData.InitiatorInfoFromDhcp) {
861 CopyMem (&HostIp.v4, &Attempt->SessionConfigData.LocalIp, sizeof (HostIp.v4));
862 CopyMem (&SubnetMask.v4, &Attempt->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));
863 CopyMem (&Gateway.v4, &Attempt->SessionConfigData.Gateway, sizeof (Gateway.v4));
864
865 if ((Gateway.Addr[0] != 0)) {
866 if (SubnetMask.Addr[0] == 0) {
867 CreatePopUp (
868 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
869 &Key,
870 L"Gateway address is set but subnet mask is zero.",
871 NULL
872 );
873
874 return EFI_INVALID_PARAMETER;
875 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {
876 CreatePopUp (
877 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
878 &Key,
879 L"Local IP and Gateway are not in the same subnet.",
880 NULL
881 );
882
883 return EFI_INVALID_PARAMETER;
884 }
885 }
886 }
887 //
888 // Validate target configuration if DHCP isn't deployed.
889 //
890 if (!Attempt->SessionConfigData.TargetInfoFromDhcp && Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) {
891 if (!Attempt->SessionConfigData.DnsMode) {
892 if (!IpIsUnicast (&Attempt->SessionConfigData.TargetIp, IfrNvData->IpMode)) {
893 CreatePopUp (
894 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
895 &Key,
896 L"Target IP is invalid!",
897 NULL
898 );
899 return EFI_INVALID_PARAMETER;
900 }
901 } else {
902 if (Attempt->SessionConfigData.TargetUrl[0] == '\0') {
903 CreatePopUp (
904 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
905 &Key,
906 L"iSCSI target Url should not be NULL!",
907 NULL
908 );
909 return EFI_INVALID_PARAMETER;
910 }
911 }
912
913 //
914 // Validate iSCSI target name configuration again:
915 // The format of iSCSI target name is already verified in IScsiFormCallback() when
916 // user input the name; here we only check the case user does not input the name.
917 //
918 if (Attempt->SessionConfigData.TargetName[0] == '\0') {
919 CreatePopUp (
920 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
921 &Key,
922 L"iSCSI target name is NULL!",
923 NULL
924 );
925 return EFI_INVALID_PARAMETER;
926 }
927 }
928
929 //
930 // Validate the authentication info.
931 //
932 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
933 if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) {
934 CreatePopUp (
935 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
936 &Key,
937 L"CHAP Name or CHAP Secret is invalid!",
938 NULL
939 );
940
941 return EFI_INVALID_PARAMETER;
942 }
943
944 if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) &&
945 ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0'))
946 ) {
947 CreatePopUp (
948 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
949 &Key,
950 L"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
951 NULL
952 );
953 return EFI_INVALID_PARAMETER;
954 }
955 }
956
957 //
958 // Check whether this attempt uses NIC which is already used by existing attempt.
959 //
960 SameNicAttempt = IScsiConfigGetAttemptByNic (Attempt, IfrNvData->Enabled);
961 if (SameNicAttempt != NULL) {
962 AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));
963 if (AttemptName1 == NULL) {
964 return EFI_OUT_OF_RESOURCES;
965 }
966
967 AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));
968 if (AttemptName2 == NULL) {
969 FreePool (AttemptName1);
970 return EFI_OUT_OF_RESOURCES;
971 }
972
973 AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_SIZE);
974 AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_SIZE);
975
976 UnicodeSPrint (
977 mPrivate->PortString,
978 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
979 L"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
980 AttemptName1,
981 AttemptName2
982 );
983
984 CreatePopUp (
985 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
986 &Key,
987 mPrivate->PortString,
988 NULL
989 );
990
991 FreePool (AttemptName1);
992 FreePool (AttemptName2);
993 }
994 }
995
996 //
997 // Update the iSCSI Mode data and record it in attempt help info.
998 //
999 if (IfrNvData->Enabled == ISCSI_DISABLED) {
1000 UnicodeSPrint (IScsiMode, 64, L"Disabled");
1001 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {
1002 UnicodeSPrint (IScsiMode, 64, L"Enabled");
1003 } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {
1004 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");
1005 }
1006
1007 if (IfrNvData->IpMode == IP_MODE_IP4) {
1008 UnicodeSPrint (IpMode, 64, L"IP4");
1009 } else if (IfrNvData->IpMode == IP_MODE_IP6) {
1010 UnicodeSPrint (IpMode, 64, L"IP6");
1011 } else if (IfrNvData->IpMode == IP_MODE_AUTOCONFIG) {
1012 UnicodeSPrint (IpMode, 64, L"Autoconfigure");
1013 }
1014
1015 NicInfo = IScsiGetNicInfoByIndex (Attempt->NicIndex);
1016 if (NicInfo == NULL) {
1017 return EFI_NOT_FOUND;
1018 }
1019
1020 MacString = (CHAR16 *) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN * sizeof (CHAR16));
1021 if (MacString == NULL) {
1022 return EFI_OUT_OF_RESOURCES;
1023 }
1024
1025 AsciiStrToUnicodeStrS (Attempt->MacString, MacString, ISCSI_MAX_MAC_STRING_LEN);
1026
1027 UnicodeSPrint (
1028 mPrivate->PortString,
1029 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
1030 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
1031 MacString,
1032 NicInfo->BusNumber,
1033 NicInfo->DeviceNumber,
1034 NicInfo->FunctionNumber,
1035 IScsiMode,
1036 IpMode
1037 );
1038
1039 Attempt->AttemptTitleHelpToken = HiiSetString (
1040 mCallbackInfo->RegisteredHandle,
1041 Attempt->AttemptTitleHelpToken,
1042 mPrivate->PortString,
1043 NULL
1044 );
1045 if (Attempt->AttemptTitleHelpToken == 0) {
1046 FreePool (MacString);
1047 return EFI_OUT_OF_RESOURCES;
1048 }
1049
1050 //
1051 // Check whether this attempt is an existing one.
1052 //
1053 ExistAttempt = IScsiConfigGetAttemptByConfigIndex (Attempt->AttemptConfigIndex);
1054 if (ExistAttempt != NULL) {
1055 ASSERT (ExistAttempt == Attempt);
1056
1057 if (IfrNvData->Enabled == ISCSI_DISABLED &&
1058 Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
1059
1060 //
1061 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1062 //
1063 if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
1064 if (mPrivate->MpioCount < 1) {
1065 return EFI_ABORTED;
1066 }
1067
1068 if (--mPrivate->MpioCount == 0) {
1069 mPrivate->EnableMpio = FALSE;
1070 }
1071 } else if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {
1072 if (mPrivate->SinglePathCount < 1) {
1073 return EFI_ABORTED;
1074 }
1075 mPrivate->SinglePathCount--;
1076 }
1077
1078 } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO &&
1079 Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {
1080 //
1081 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1082 //
1083 if (mPrivate->SinglePathCount < 1) {
1084 return EFI_ABORTED;
1085 }
1086
1087 mPrivate->EnableMpio = TRUE;
1088 mPrivate->MpioCount++;
1089 mPrivate->SinglePathCount--;
1090
1091 } else if (IfrNvData->Enabled == ISCSI_ENABLED &&
1092 Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
1093 //
1094 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1095 //
1096 if (mPrivate->MpioCount < 1) {
1097 return EFI_ABORTED;
1098 }
1099
1100 if (--mPrivate->MpioCount == 0) {
1101 mPrivate->EnableMpio = FALSE;
1102 }
1103 mPrivate->SinglePathCount++;
1104
1105 } else if (IfrNvData->Enabled != ISCSI_DISABLED &&
1106 Attempt->SessionConfigData.Enabled == ISCSI_DISABLED) {
1107 //
1108 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1109 //
1110 if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {
1111 mPrivate->EnableMpio = TRUE;
1112 mPrivate->MpioCount++;
1113
1114 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {
1115 mPrivate->SinglePathCount++;
1116 }
1117 }
1118
1119 } else if (ExistAttempt == NULL) {
1120 //
1121 // When a new attempt is created, pointer of the attempt is saved to
1122 // mCallbackInfo->Current in IScsiConfigProcessDefault. If input Attempt
1123 // does not match any existing attempt, it should be a new created attempt.
1124 // Save it to system now.
1125 //
1126
1127 //
1128 // Save current order number for this attempt.
1129 //
1130 AttemptConfigOrder = IScsiGetVariableAndSize (
1131 L"AttemptOrder",
1132 &gIScsiConfigGuid,
1133 &AttemptConfigOrderSize
1134 );
1135
1136 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);
1137 TotalNumber++;
1138
1139 //
1140 // Append the new created attempt order to the end.
1141 //
1142 AttemptOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));
1143 if (AttemptOrderTmp == NULL) {
1144 if (AttemptConfigOrder != NULL) {
1145 FreePool (AttemptConfigOrder);
1146 }
1147 return EFI_OUT_OF_RESOURCES;
1148 }
1149
1150 if (AttemptConfigOrder != NULL) {
1151 CopyMem (AttemptOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);
1152 FreePool (AttemptConfigOrder);
1153 }
1154
1155 AttemptOrderTmp[TotalNumber - 1] = Attempt->AttemptConfigIndex;
1156 AttemptConfigOrder = AttemptOrderTmp;
1157 AttemptConfigOrderSize = TotalNumber * sizeof (UINT8);
1158
1159 Status = gRT->SetVariable (
1160 L"AttemptOrder",
1161 &gIScsiConfigGuid,
1162 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
1163 AttemptConfigOrderSize,
1164 AttemptConfigOrder
1165 );
1166 FreePool (AttemptConfigOrder);
1167 if (EFI_ERROR (Status)) {
1168 return Status;
1169 }
1170
1171 //
1172 // Insert new created attempt to array.
1173 //
1174 InsertTailList (&mPrivate->AttemptConfigs, &Attempt->Link);
1175 mPrivate->AttemptCount++;
1176
1177 if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {
1178 //
1179 // This new Attempt is enabled for MPIO; enable the multipath mode.
1180 //
1181 mPrivate->EnableMpio = TRUE;
1182 mPrivate->MpioCount++;
1183 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {
1184 mPrivate->SinglePathCount++;
1185 }
1186
1187 IScsiConfigUpdateAttempt ();
1188 }
1189 Attempt->SessionConfigData.Enabled = IfrNvData->Enabled;
1190
1191 //
1192 // Record the user configuration information in NVR.
1193 //
1194 UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", Attempt->AttemptConfigIndex);
1195
1196 FreePool (MacString);
1197
1198 return gRT->SetVariable (
1199 mPrivate->PortString,
1200 &gEfiIScsiInitiatorNameProtocolGuid,
1201 ISCSI_CONFIG_VAR_ATTR,
1202 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
1203 Attempt
1204 );
1205 }
1206
1207 /**
1208 Convert the IFR data configured by keyword to iSCSI configuration data.
1209
1210 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
1211 @param[in] OffSet The offset of the variable to the configuration structure.
1212
1213 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
1214 @retval EFI_SUCCESS The operation is completed successfully.
1215
1216 **/
1217 EFI_STATUS
1218 IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (
1219 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData,
1220 IN UINTN OffSet
1221 )
1222 {
1223 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;
1224 UINT8 AttemptIndex;
1225 UINT8 Index;
1226 UINT8 ChapSecretLen;
1227 UINT8 ReverseChapSecretLen;
1228 CHAR16 *AttemptName1;
1229 CHAR16 *AttemptName2;
1230 ISCSI_ATTEMPT_CONFIG_NVDATA *SameNicAttempt;
1231 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];
1232 CHAR8 IScsiName[ISCSI_NAME_MAX_SIZE];
1233 CHAR8 IpString[IP_STR_MAX_SIZE];
1234 EFI_IP_ADDRESS HostIp;
1235 EFI_IP_ADDRESS SubnetMask;
1236 EFI_IP_ADDRESS Gateway;
1237 EFI_INPUT_KEY Key;
1238 UINT64 Lun;
1239 EFI_STATUS Status;
1240
1241 Attempt = NULL;
1242 ZeroMem (IScsiName, sizeof (IScsiName));
1243
1244 if (OffSet < ATTEMPT_BOOTENABLE_VAR_OFFSET) {
1245 return EFI_SUCCESS;
1246
1247 } else if ((OffSet >= ATTEMPT_BOOTENABLE_VAR_OFFSET) && (OffSet < ATTEMPT_ADDRESS_TYPE_VAR_OFFSET)) {
1248 AttemptIndex = (UINT8) ((OffSet - ATTEMPT_BOOTENABLE_VAR_OFFSET) + 1);
1249 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
1250 if (Attempt == NULL) {
1251 return EFI_INVALID_PARAMETER;
1252 }
1253 IfrNvData->Enabled = IfrNvData->ISCSIBootEnableList[AttemptIndex - 1];
1254 //
1255 // Validate the configuration of attempt.
1256 //
1257 if (IfrNvData->Enabled != ISCSI_DISABLED) {
1258 //
1259 // Check whether this attempt uses NIC which is already used by existing attempt.
1260 //
1261 SameNicAttempt = IScsiConfigGetAttemptByNic (Attempt, IfrNvData->Enabled);
1262 if (SameNicAttempt != NULL) {
1263 AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));
1264 if (AttemptName1 == NULL) {
1265 return EFI_OUT_OF_RESOURCES;
1266 }
1267
1268 AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));
1269 if (AttemptName2 == NULL) {
1270 FreePool (AttemptName1);
1271 return EFI_OUT_OF_RESOURCES;
1272 }
1273
1274 AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_SIZE);
1275 AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_SIZE);
1276
1277 UnicodeSPrint (
1278 mPrivate->PortString,
1279 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
1280 L"Warning! \"%s\" uses same NIC as Attempt \"%s\".",
1281 AttemptName1,
1282 AttemptName2
1283 );
1284
1285 CreatePopUp (
1286 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1287 &Key,
1288 mPrivate->PortString,
1289 NULL
1290 );
1291
1292 FreePool (AttemptName1);
1293 FreePool (AttemptName2);
1294 }
1295 }
1296
1297 if (IfrNvData->Enabled == ISCSI_DISABLED &&
1298 Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
1299
1300 //
1301 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1302 //
1303 if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
1304 if (mPrivate->MpioCount < 1) {
1305 return EFI_ABORTED;
1306 }
1307
1308 if (--mPrivate->MpioCount == 0) {
1309 mPrivate->EnableMpio = FALSE;
1310 }
1311 } else if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {
1312 if (mPrivate->SinglePathCount < 1) {
1313 return EFI_ABORTED;
1314 }
1315 mPrivate->SinglePathCount--;
1316 }
1317
1318 } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO &&
1319 Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {
1320 //
1321 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1322 //
1323 if (mPrivate->SinglePathCount < 1) {
1324 return EFI_ABORTED;
1325 }
1326
1327 mPrivate->EnableMpio = TRUE;
1328 mPrivate->MpioCount++;
1329 mPrivate->SinglePathCount--;
1330
1331 } else if (IfrNvData->Enabled == ISCSI_ENABLED &&
1332 Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
1333 //
1334 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1335 //
1336 if (mPrivate->MpioCount < 1) {
1337 return EFI_ABORTED;
1338 }
1339
1340 if (--mPrivate->MpioCount == 0) {
1341 mPrivate->EnableMpio = FALSE;
1342 }
1343 mPrivate->SinglePathCount++;
1344
1345 } else if (IfrNvData->Enabled != ISCSI_DISABLED &&
1346 Attempt->SessionConfigData.Enabled == ISCSI_DISABLED) {
1347 //
1348 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1349 //
1350 if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {
1351 mPrivate->EnableMpio = TRUE;
1352 mPrivate->MpioCount++;
1353
1354 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {
1355 mPrivate->SinglePathCount++;
1356 }
1357 }
1358 Attempt->SessionConfigData.Enabled = IfrNvData->Enabled;
1359
1360 } else if ((OffSet >= ATTEMPT_ADDRESS_TYPE_VAR_OFFSET) && (OffSet < ATTEMPT_CONNECT_RETRY_VAR_OFFSET)) {
1361 AttemptIndex = (UINT8) ((OffSet - ATTEMPT_ADDRESS_TYPE_VAR_OFFSET) + 1);
1362 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
1363 if (Attempt == NULL) {
1364 return EFI_INVALID_PARAMETER;
1365 }
1366 Attempt->SessionConfigData.IpMode = IfrNvData->ISCSIIpAddressTypeList[AttemptIndex - 1];
1367 if (Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) {
1368 Attempt->AutoConfigureMode = 0;
1369 }
1370
1371 } else if ((OffSet >= ATTEMPT_CONNECT_RETRY_VAR_OFFSET) && (OffSet < ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET)) {
1372 AttemptIndex = (UINT8) ((OffSet - ATTEMPT_CONNECT_RETRY_VAR_OFFSET) + 1);
1373 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
1374 if (Attempt == NULL) {
1375 return EFI_INVALID_PARAMETER;
1376 }
1377
1378 if (IfrNvData->ISCSIConnectRetry[AttemptIndex - 1] > CONNECT_MAX_RETRY) {
1379 CreatePopUp (
1380 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1381 &Key,
1382 L"The minimum value is 0 and the maximum is 16. 0 means no retry.",
1383 NULL
1384 );
1385 return EFI_INVALID_PARAMETER;
1386 }
1387 Attempt->SessionConfigData.ConnectRetryCount = IfrNvData->ISCSIConnectRetry[AttemptIndex - 1];
1388
1389 } else if ((OffSet >= ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET)) {
1390 AttemptIndex = (UINT8) ((OffSet - ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET) / 2 + 1);
1391 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
1392 if (Attempt == NULL) {
1393 return EFI_INVALID_PARAMETER;
1394 }
1395
1396 if ((IfrNvData->ISCSIConnectTimeout[AttemptIndex - 1] < CONNECT_MIN_TIMEOUT) ||
1397 (IfrNvData->ISCSIConnectTimeout[AttemptIndex - 1] > CONNECT_MAX_TIMEOUT)) {
1398 CreatePopUp (
1399 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1400 &Key,
1401 L"The minimum value is 100 milliseconds and the maximum is 20 seconds.",
1402 NULL
1403 );
1404 return EFI_INVALID_PARAMETER;
1405 }
1406
1407 Attempt->SessionConfigData.ConnectTimeout = IfrNvData->ISCSIConnectTimeout[AttemptIndex - 1];
1408 if (Attempt->SessionConfigData.ConnectTimeout == 0) {
1409 Attempt->SessionConfigData.ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;
1410 }
1411
1412 } else if ((OffSet >= ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET)) {
1413 AttemptIndex = (UINT8) ((OffSet - ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET) + 1);
1414 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
1415 if (Attempt == NULL) {
1416 return EFI_INVALID_PARAMETER;
1417 }
1418 Attempt->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->ISCSIInitiatorInfoViaDHCP[AttemptIndex - 1];
1419
1420 } else if ((OffSet >= ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET)) {
1421 AttemptIndex = (UINT8) ((OffSet - ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET) + 1);
1422 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
1423 if (Attempt == NULL) {
1424 return EFI_INVALID_PARAMETER;
1425 }
1426
1427 if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {
1428 Attempt->SessionConfigData.TargetInfoFromDhcp = IfrNvData->ISCSITargetInfoViaDHCP[AttemptIndex - 1];
1429 } else {
1430 CreatePopUp (
1431 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1432 &Key,
1433 L"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1434 NULL
1435 );
1436 return EFI_INVALID_PARAMETER;
1437 }
1438
1439 } else if ((OffSet >= ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET) && (OffSet < ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET)) {
1440 AttemptIndex = (UINT8) ((OffSet - ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET) / 2 + 1);
1441 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
1442 if (Attempt == NULL) {
1443 return EFI_INVALID_PARAMETER;
1444 }
1445 if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (!Attempt->SessionConfigData.TargetInfoFromDhcp)) {
1446 Attempt->SessionConfigData.TargetPort = IfrNvData->ISCSITargetTcpPort[AttemptIndex - 1];
1447 if (Attempt->SessionConfigData.TargetPort == 0) {
1448 Attempt->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;
1449 }
1450 } else {
1451 CreatePopUp (
1452 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1453 &Key,
1454 L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1455 NULL
1456 );
1457 return EFI_INVALID_PARAMETER;
1458 }
1459
1460 } else if ((OffSet >= ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET) && (OffSet < ATTEMPT_CHARTYPE_VAR_OFFSET)) {
1461 AttemptIndex = (UINT8) ((OffSet - ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET) + 1);
1462 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
1463 if (Attempt == NULL) {
1464 return EFI_INVALID_PARAMETER;
1465 }
1466
1467 Attempt->AuthenticationType = IfrNvData->ISCSIAuthenticationMethod[AttemptIndex - 1];
1468
1469 } else if ((OffSet >= ATTEMPT_CHARTYPE_VAR_OFFSET) && (OffSet < ATTEMPT_ISID_VAR_OFFSET)) {
1470 AttemptIndex = (UINT8) ((OffSet - ATTEMPT_CHARTYPE_VAR_OFFSET) + 1);
1471 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
1472 if (Attempt == NULL) {
1473 return EFI_INVALID_PARAMETER;
1474 }
1475 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
1476 Attempt->AuthConfigData.CHAP.CHAPType = IfrNvData->ISCSIChapType[AttemptIndex - 1];
1477 }
1478
1479 } else if (OffSet >= ATTEMPT_ISID_VAR_OFFSET) {
1480 Index = (UINT8) ((OffSet - ATTEMPT_ISID_VAR_OFFSET) / sizeof (KEYWORD_STR));
1481 AttemptIndex = Index + 1;
1482 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
1483 if (Attempt == NULL) {
1484 return EFI_INVALID_PARAMETER;
1485 }
1486
1487 OffSet = OffSet - Index * sizeof (KEYWORD_STR);
1488
1489 if ((OffSet >= ATTEMPT_ISID_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET)) {
1490 IScsiParseIsIdFromString (IfrNvData->Keyword[Index].ISCSIIsId, Attempt->SessionConfigData.IsId);
1491
1492 } else if ((OffSet >= ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET)) {
1493 if ((Attempt->SessionConfigData.IpMode == IP_MODE_IP4) && (!Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {
1494 //
1495 // Config Local ip
1496 //
1497 Status = NetLibStrToIp4 (IfrNvData->Keyword[Index].ISCSIInitiatorIpAddress, &HostIp.v4);
1498 if (EFI_ERROR (Status) || ((Attempt->SessionConfigData.SubnetMask.Addr[0] != 0) &&
1499 !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), NTOHL(*(UINT32*)Attempt->SessionConfigData.SubnetMask.Addr)))) {
1500 CreatePopUp (
1501 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1502 &Key,
1503 L"Invalid IP address!",
1504 NULL
1505 );
1506 return EFI_INVALID_PARAMETER;
1507 } else {
1508 CopyMem (&Attempt->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
1509 }
1510 } else {
1511 CreatePopUp (
1512 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1513 &Key,
1514 L"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1515 NULL
1516 );
1517 return EFI_INVALID_PARAMETER;
1518 }
1519
1520 } else if ((OffSet >= ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET)) {
1521 if ((Attempt->SessionConfigData.IpMode == IP_MODE_IP4) && (!Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {
1522 Status = NetLibStrToIp4 (IfrNvData->Keyword[Index].ISCSIInitiatorNetmask, &SubnetMask.v4);
1523 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
1524 CreatePopUp (
1525 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1526 &Key,
1527 L"Invalid Subnet Mask!",
1528 NULL
1529 );
1530 return EFI_INVALID_PARAMETER;
1531 } else {
1532 CopyMem (&Attempt->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
1533 }
1534 } else {
1535 CreatePopUp (
1536 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1537 &Key,
1538 L"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1539 NULL
1540 );
1541 return EFI_INVALID_PARAMETER;
1542 }
1543
1544 } else if ((OffSet >= ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_NAME_VAR_OFFSET)) {
1545 if ((Attempt->SessionConfigData.IpMode == IP_MODE_IP4) && (!Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {
1546 Status = NetLibStrToIp4 (IfrNvData->Keyword[Index].ISCSIInitiatorGateway, &Gateway.v4);
1547 if (EFI_ERROR (Status) ||
1548 ((Gateway.Addr[0] != 0) && (Attempt->SessionConfigData.SubnetMask.Addr[0] != 0) &&
1549 !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL(*(UINT32*)Attempt->SessionConfigData.SubnetMask.Addr)))) {
1550 CreatePopUp (
1551 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1552 &Key,
1553 L"Invalid Gateway!",
1554 NULL
1555 );
1556 return EFI_INVALID_PARAMETER;
1557 } else {
1558 CopyMem (&Attempt->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));
1559 }
1560 } else {
1561 CreatePopUp (
1562 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1563 &Key,
1564 L"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1565 NULL
1566 );
1567 return EFI_INVALID_PARAMETER;
1568 }
1569
1570 } else if ((OffSet >= ATTEMPT_TARGET_NAME_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET)) {
1571 if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (!Attempt->SessionConfigData.TargetInfoFromDhcp)) {
1572 UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSITargetName, IScsiName, ISCSI_NAME_MAX_SIZE);
1573 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));
1574 if (EFI_ERROR (Status)) {
1575 CreatePopUp (
1576 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1577 &Key,
1578 L"Invalid iSCSI Name!",
1579 NULL
1580 );
1581 } else {
1582 AsciiStrCpyS (Attempt->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName);
1583 }
1584 if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
1585 if (Attempt->SessionConfigData.TargetName[0] == L'\0') {
1586 CreatePopUp (
1587 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1588 &Key,
1589 L"iSCSI target name is NULL!",
1590 NULL
1591 );
1592 return EFI_INVALID_PARAMETER;
1593 }
1594 }
1595 } else {
1596 CreatePopUp (
1597 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1598 &Key,
1599 L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1600 NULL
1601 );
1602 return EFI_INVALID_PARAMETER;
1603 }
1604
1605 } else if ((OffSet >= ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET) && (OffSet < ATTEMPT_LUN_VAR_OFFSET)) {
1606 if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (!Attempt->SessionConfigData.TargetInfoFromDhcp)) {
1607 UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSITargetIpAddress, IpString, sizeof (IpString));
1608 Status = IScsiAsciiStrToIp (IpString, Attempt->SessionConfigData.IpMode, &HostIp);
1609 if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, Attempt->SessionConfigData.IpMode)) {
1610 Attempt->SessionConfigData.DnsMode = TRUE;
1611 ZeroMem (&Attempt->SessionConfigData.TargetIp, sizeof (Attempt->SessionConfigData.TargetIp));
1612 UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSITargetIpAddress, Attempt->SessionConfigData.TargetUrl, ISCSI_NAME_MAX_SIZE);
1613 } else {
1614 Attempt->SessionConfigData.DnsMode = FALSE;
1615 CopyMem (&Attempt->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp));
1616 }
1617 } else {
1618 CreatePopUp (
1619 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1620 &Key,
1621 L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1622 NULL
1623 );
1624 return EFI_INVALID_PARAMETER;
1625 }
1626
1627 } else if ((OffSet >= ATTEMPT_LUN_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_USER_NAME_VAR_OFFSET)) {
1628 if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (Attempt->SessionConfigData.TargetInfoFromDhcp == 0)) {
1629 //
1630 // Config LUN.
1631 //
1632 UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSILun, LunString, ISCSI_LUN_STR_MAX_LEN);
1633 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);
1634 if (EFI_ERROR (Status)) {
1635 CreatePopUp (
1636 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1637 &Key,
1638 L"Invalid LUN string, Examples are: 4752-3A4F-6b7e-2F99, 6734-9-156f-127, 4186-9!",
1639 NULL
1640 );
1641 } else {
1642 CopyMem (&Attempt->SessionConfigData.BootLun, &Lun, sizeof (Lun));
1643 }
1644 } else {
1645 CreatePopUp (
1646 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1647 &Key,
1648 L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1649 NULL
1650 );
1651 return EFI_INVALID_PARAMETER;
1652 }
1653
1654 } else if ((OffSet >= ATTEMPT_CHAR_USER_NAME_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_SECRET_VAR_OFFSET)) {
1655 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
1656 UnicodeStrToAsciiStrS (
1657 IfrNvData->Keyword[Index].ISCSIChapUsername,
1658 Attempt->AuthConfigData.CHAP.CHAPName,
1659 ISCSI_CHAP_NAME_STORAGE
1660 );
1661
1662 if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
1663 if (IfrNvData->Keyword[Index].ISCSIChapUsername[0] == L'\0') {
1664 CreatePopUp (
1665 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1666 &Key,
1667 L"CHAP Name is invalid!",
1668 NULL
1669 );
1670 return EFI_INVALID_PARAMETER;
1671 }
1672 }
1673 } else {
1674 CreatePopUp (
1675 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1676 &Key,
1677 L"Invalid Configuration, Check value of AuthenticationType!",
1678 NULL
1679 );
1680 return EFI_INVALID_PARAMETER;
1681 }
1682
1683 } else if ((OffSet >= ATTEMPT_CHAR_SECRET_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET)) {
1684 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
1685 ChapSecretLen = (UINT8)StrLen (IfrNvData->Keyword[Index].ISCSIChapSecret);
1686 UnicodeStrToAsciiStrS (
1687 IfrNvData->Keyword[Index].ISCSIChapSecret,
1688 Attempt->AuthConfigData.CHAP.CHAPSecret,
1689 ISCSI_CHAP_SECRET_STORAGE
1690 );
1691
1692 if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
1693 if ((ChapSecretLen < ISCSI_CHAP_SECRET_MIN_LEN) || (ChapSecretLen > ISCSI_CHAP_SECRET_MAX_LEN)) {
1694 CreatePopUp (
1695 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1696 &Key,
1697 L"The Chap Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1698 NULL
1699 );
1700 return EFI_INVALID_PARAMETER;
1701 }
1702 }
1703 } else {
1704 CreatePopUp (
1705 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1706 &Key,
1707 L"Invalid Configuration, Check value of AuthenticationType!",
1708 NULL
1709 );
1710 return EFI_INVALID_PARAMETER;
1711 }
1712
1713 } else if ((OffSet >= ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET)) {
1714 if (Attempt->AuthConfigData.CHAP.CHAPType == ISCSI_CHAP_MUTUAL) {
1715 UnicodeStrToAsciiStrS (
1716 IfrNvData->Keyword[Index].ISCSIReverseChapUsername,
1717 Attempt->AuthConfigData.CHAP.ReverseCHAPName,
1718 ISCSI_CHAP_NAME_STORAGE
1719 );
1720 if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
1721 if (IfrNvData->Keyword[Index].ISCSIReverseChapUsername[0] == L'\0') {
1722 CreatePopUp (
1723 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1724 &Key,
1725 L"Reverse CHAP Name is invalid!",
1726 NULL
1727 );
1728 return EFI_INVALID_PARAMETER;
1729 }
1730 }
1731 } else {
1732 CreatePopUp (
1733 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1734 &Key,
1735 L"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1736 NULL
1737 );
1738 return EFI_INVALID_PARAMETER;
1739 }
1740
1741 } else if (OffSet >= ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET) {
1742 if (Attempt->AuthConfigData.CHAP.CHAPType == ISCSI_CHAP_MUTUAL) {
1743 ReverseChapSecretLen = (UINT8)StrLen (IfrNvData->Keyword[Index].ISCSIReverseChapSecret);
1744 UnicodeStrToAsciiStrS (
1745 IfrNvData->Keyword[Index].ISCSIReverseChapSecret,
1746 Attempt->AuthConfigData.CHAP.ReverseCHAPSecret,
1747 ISCSI_CHAP_SECRET_STORAGE
1748 );
1749
1750 if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
1751 if ((ReverseChapSecretLen < ISCSI_CHAP_SECRET_MIN_LEN) || (ReverseChapSecretLen > ISCSI_CHAP_SECRET_MAX_LEN)) {
1752 CreatePopUp (
1753 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1754 &Key,
1755 L"The Reverse CHAP Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1756 NULL
1757 );
1758 return EFI_INVALID_PARAMETER;
1759 }
1760 }
1761 } else {
1762 CreatePopUp (
1763 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1764 &Key,
1765 L"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1766 NULL
1767 );
1768 return EFI_INVALID_PARAMETER;
1769 }
1770 }
1771 }
1772
1773
1774
1775 //
1776 // Record the user configuration information in NVR.
1777 //
1778 ASSERT (Attempt != NULL);
1779 UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", Attempt->AttemptConfigIndex);
1780 return gRT->SetVariable (
1781 mPrivate->PortString,
1782 &gEfiIScsiInitiatorNameProtocolGuid,
1783 ISCSI_CONFIG_VAR_ATTR,
1784 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
1785 Attempt
1786 );
1787
1788 }
1789
1790 /**
1791 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
1792 a help function.
1793
1794 @param[in] StartLabelNumber The number of start label.
1795 @param[out] StartOpCodeHandle Points to the start opcode handle.
1796 @param[out] StartLabel Points to the created start opcode.
1797 @param[out] EndOpCodeHandle Points to the end opcode handle.
1798 @param[out] EndLabel Points to the created end opcode.
1799
1800 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
1801 operation.
1802 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1803 @retval EFI_SUCCESS The operation is completed successfully.
1804
1805 **/
1806 EFI_STATUS
1807 IScsiCreateOpCode (
1808 IN UINT16 StartLabelNumber,
1809 OUT VOID **StartOpCodeHandle,
1810 OUT EFI_IFR_GUID_LABEL **StartLabel,
1811 OUT VOID **EndOpCodeHandle,
1812 OUT EFI_IFR_GUID_LABEL **EndLabel
1813 )
1814 {
1815 EFI_STATUS Status;
1816 EFI_IFR_GUID_LABEL *InternalStartLabel;
1817 EFI_IFR_GUID_LABEL *InternalEndLabel;
1818
1819 if (StartOpCodeHandle == NULL || StartLabel == NULL || EndOpCodeHandle == NULL || EndLabel == NULL) {
1820 return EFI_INVALID_PARAMETER;
1821 }
1822
1823 *StartOpCodeHandle = NULL;
1824 *EndOpCodeHandle = NULL;
1825 Status = EFI_OUT_OF_RESOURCES;
1826
1827 //
1828 // Initialize the container for dynamic opcodes.
1829 //
1830 *StartOpCodeHandle = HiiAllocateOpCodeHandle ();
1831 if (*StartOpCodeHandle == NULL) {
1832 return Status;
1833 }
1834
1835 *EndOpCodeHandle = HiiAllocateOpCodeHandle ();
1836 if (*EndOpCodeHandle == NULL) {
1837 goto Exit;
1838 }
1839
1840 //
1841 // Create Hii Extend Label OpCode as the start opcode.
1842 //
1843 InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
1844 *StartOpCodeHandle,
1845 &gEfiIfrTianoGuid,
1846 NULL,
1847 sizeof (EFI_IFR_GUID_LABEL)
1848 );
1849 if (InternalStartLabel == NULL) {
1850 goto Exit;
1851 }
1852
1853 InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1854 InternalStartLabel->Number = StartLabelNumber;
1855
1856 //
1857 // Create Hii Extend Label OpCode as the end opcode.
1858 //
1859 InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
1860 *EndOpCodeHandle,
1861 &gEfiIfrTianoGuid,
1862 NULL,
1863 sizeof (EFI_IFR_GUID_LABEL)
1864 );
1865 if (InternalEndLabel == NULL) {
1866 goto Exit;
1867 }
1868
1869 InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1870 InternalEndLabel->Number = LABEL_END;
1871
1872 *StartLabel = InternalStartLabel;
1873 *EndLabel = InternalEndLabel;
1874
1875 return EFI_SUCCESS;
1876
1877 Exit:
1878
1879 if (*StartOpCodeHandle != NULL) {
1880 HiiFreeOpCodeHandle (*StartOpCodeHandle);
1881 }
1882
1883 if (*EndOpCodeHandle != NULL) {
1884 HiiFreeOpCodeHandle (*EndOpCodeHandle);
1885 }
1886 return Status;
1887 }
1888
1889 /**
1890 Update the MAIN form to display the configured attempts.
1891
1892 **/
1893 VOID
1894 IScsiConfigUpdateAttempt (
1895 VOID
1896 )
1897 {
1898 LIST_ENTRY *Entry;
1899 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
1900 VOID *StartOpCodeHandle;
1901 EFI_IFR_GUID_LABEL *StartLabel;
1902 VOID *EndOpCodeHandle;
1903 EFI_IFR_GUID_LABEL *EndLabel;
1904 EFI_STATUS Status;
1905
1906 Status = IScsiCreateOpCode (
1907 ATTEMPT_ENTRY_LABEL,
1908 &StartOpCodeHandle,
1909 &StartLabel,
1910 &EndOpCodeHandle,
1911 &EndLabel
1912 );
1913 if (EFI_ERROR (Status)) {
1914 return ;
1915 }
1916
1917 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
1918 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
1919 if (AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED) {
1920 //
1921 // Update Attempt Help Info.
1922 //
1923 UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", (UINTN) AttemptConfigData->AttemptConfigIndex);
1924 AttemptConfigData->AttemptTitleToken = HiiSetString (
1925 mCallbackInfo->RegisteredHandle,
1926 0,
1927 mPrivate->PortString,
1928 NULL
1929 );
1930 if (AttemptConfigData->AttemptTitleToken == 0) {
1931 return ;
1932 }
1933
1934 HiiCreateGotoOpCode (
1935 StartOpCodeHandle, // Container for dynamic created opcodes
1936 FORMID_ATTEMPT_FORM, // Form ID
1937 AttemptConfigData->AttemptTitleToken, // Prompt text
1938 AttemptConfigData->AttemptTitleHelpToken, // Help text
1939 EFI_IFR_FLAG_CALLBACK, // Question flag
1940 (UINT16) (KEY_ATTEMPT_ENTRY_BASE + AttemptConfigData->AttemptConfigIndex) // Question ID
1941 );
1942 }
1943 }
1944
1945 HiiUpdateForm (
1946 mCallbackInfo->RegisteredHandle, // HII handle
1947 &gIScsiConfigGuid, // Formset GUID
1948 FORMID_MAIN_FORM, // Form ID
1949 StartOpCodeHandle, // Label for where to insert opcodes
1950 EndOpCodeHandle // Replace data
1951 );
1952
1953 HiiFreeOpCodeHandle (StartOpCodeHandle);
1954 HiiFreeOpCodeHandle (EndOpCodeHandle);
1955 }
1956
1957 /**
1958 Callback function when user presses "Add an Attempt".
1959
1960 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1961 operation.
1962 @retval EFI_SUCCESS The operation is completed successfully.
1963
1964 **/
1965 EFI_STATUS
1966 IScsiConfigAddAttempt (
1967 VOID
1968 )
1969 {
1970 LIST_ENTRY *Entry;
1971 ISCSI_NIC_INFO *NicInfo;
1972 EFI_STRING_ID PortTitleToken;
1973 EFI_STRING_ID PortTitleHelpToken;
1974 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
1975 EFI_STATUS Status;
1976 VOID *StartOpCodeHandle;
1977 EFI_IFR_GUID_LABEL *StartLabel;
1978 VOID *EndOpCodeHandle;
1979 EFI_IFR_GUID_LABEL *EndLabel;
1980
1981 Status = IScsiCreateOpCode (
1982 MAC_ENTRY_LABEL,
1983 &StartOpCodeHandle,
1984 &StartLabel,
1985 &EndOpCodeHandle,
1986 &EndLabel
1987 );
1988 if (EFI_ERROR (Status)) {
1989 return Status;
1990 }
1991
1992 //
1993 // Ask user to select a MAC for this attempt.
1994 //
1995 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
1996 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
1997 IScsiMacAddrToStr (
1998 &NicInfo->PermanentAddress,
1999 NicInfo->HwAddressSize,
2000 NicInfo->VlanId,
2001 MacString
2002 );
2003
2004 UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"MAC %s", MacString);
2005 PortTitleToken = HiiSetString (
2006 mCallbackInfo->RegisteredHandle,
2007 0,
2008 mPrivate->PortString,
2009 NULL
2010 );
2011 if (PortTitleToken == 0) {
2012 Status = EFI_INVALID_PARAMETER;
2013 goto Exit;
2014 }
2015
2016 UnicodeSPrint (
2017 mPrivate->PortString,
2018 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2019 L"PFA: Bus %d | Dev %d | Func %d",
2020 NicInfo->BusNumber,
2021 NicInfo->DeviceNumber,
2022 NicInfo->FunctionNumber
2023 );
2024 PortTitleHelpToken = HiiSetString (mCallbackInfo->RegisteredHandle, 0, mPrivate->PortString, NULL);
2025 if (PortTitleHelpToken == 0) {
2026 Status = EFI_INVALID_PARAMETER;
2027 goto Exit;
2028 }
2029
2030 HiiCreateGotoOpCode (
2031 StartOpCodeHandle, // Container for dynamic created opcodes
2032 FORMID_ATTEMPT_FORM,
2033 PortTitleToken,
2034 PortTitleHelpToken,
2035 EFI_IFR_FLAG_CALLBACK, // Question flag
2036 (UINT16) (KEY_MAC_ENTRY_BASE + NicInfo->NicIndex)
2037 );
2038 }
2039
2040 Status = HiiUpdateForm (
2041 mCallbackInfo->RegisteredHandle, // HII handle
2042 &gIScsiConfigGuid, // Formset GUID
2043 FORMID_MAC_FORM, // Form ID
2044 StartOpCodeHandle, // Label for where to insert opcodes
2045 EndOpCodeHandle // Replace data
2046 );
2047
2048 Exit:
2049 HiiFreeOpCodeHandle (StartOpCodeHandle);
2050 HiiFreeOpCodeHandle (EndOpCodeHandle);
2051
2052 return Status;
2053 }
2054
2055 /**
2056 Add the attempts by keyword 'iSCSIAddAttempts', you can use this keyword with
2057 value 'attempt:1 attempt:2' etc to add one or more attempts once. This is different
2058 with IScsiConfigAddAttempt function which is used to add attempt by UI configuration.
2059
2060 @param[in] AttemptList The new attempt List will be added.
2061
2062 @retval EFI_SUCCESS The operation to add attempt list successfully.
2063 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2064 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2065 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2066 resources.
2067
2068 **/
2069 EFI_STATUS
2070 IScsiConfigAddAttemptsByKeywords (
2071 IN UINT8 *AttemptList
2072 )
2073 {
2074 UINT8 Index;
2075 UINT8 Number;
2076 UINTN TotalNumber;
2077 UINT8 Nic;
2078 UINT8 *AttemptConfigOrder;
2079 UINTN AttemptConfigOrderSize;
2080 UINT8 *AttemptConfigOrderTmp;
2081 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2082 ISCSI_NIC_INFO *NicInfo;
2083 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
2084 CHAR16 IScsiMode[64];
2085 CHAR16 IpMode[64];
2086 EFI_STATUS Status;
2087
2088 Nic = mPrivate->CurrentNic;
2089 NicInfo = IScsiGetNicInfoByIndex (Nic);
2090 if (NicInfo == NULL) {
2091 return EFI_NOT_FOUND;
2092 }
2093
2094 //
2095 // The MAC info will be recorded in Config Data.
2096 //
2097 IScsiMacAddrToStr (
2098 &NicInfo->PermanentAddress,
2099 NicInfo->HwAddressSize,
2100 NicInfo->VlanId,
2101 MacString
2102 );
2103
2104 for (Index = 0; Index < PcdGet8 (PcdMaxIScsiAttemptNumber); Index++) {
2105 if (AttemptList[Index] == 0) {
2106 continue;
2107 }
2108
2109 //
2110 // Add the attempt.
2111 //
2112 Number = AttemptList[Index];
2113
2114 UnicodeSPrint (
2115 mPrivate->PortString,
2116 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2117 L"Attempt %d",
2118 Number
2119 );
2120
2121 GetVariable2 (
2122 mPrivate->PortString,
2123 &gEfiIScsiInitiatorNameProtocolGuid,
2124 (VOID**)&AttemptConfigData,
2125 NULL
2126 );
2127 if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED) {
2128 return EFI_INVALID_PARAMETER;
2129 }
2130
2131 AttemptConfigData->Actived = ISCSI_ACTIVE_ENABLED;
2132 AttemptConfigData->NicIndex = NicInfo->NicIndex;
2133 UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, ISCSI_MAX_MAC_STRING_LEN);
2134
2135 //
2136 // Generate OUI-format ISID based on MAC address.
2137 //
2138 CopyMem (AttemptConfigData->SessionConfigData.IsId, &NicInfo->PermanentAddress, 6);
2139 AttemptConfigData->SessionConfigData.IsId[0] =
2140 (UINT8) (AttemptConfigData->SessionConfigData.IsId[0] & 0x3F);
2141
2142 //
2143 // Configure the iSCSI Mode and IpMode to default.
2144 // Add Attempt Help Info.
2145 //
2146 UnicodeSPrint (IScsiMode, 64, L"Disabled");
2147 UnicodeSPrint (IpMode, 64, L"IP4");
2148 UnicodeSPrint (
2149 mPrivate->PortString,
2150 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2151 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
2152 MacString,
2153 NicInfo->BusNumber,
2154 NicInfo->DeviceNumber,
2155 NicInfo->FunctionNumber,
2156 IScsiMode,
2157 IpMode
2158 );
2159
2160 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (
2161 mCallbackInfo->RegisteredHandle,
2162 0,
2163 mPrivate->PortString,
2164 NULL
2165 );
2166 if (AttemptConfigData->AttemptTitleHelpToken == 0) {
2167 return EFI_OUT_OF_RESOURCES;
2168 }
2169
2170 //
2171 // Get current Attempt order and number.
2172 //
2173 AttemptConfigOrder = IScsiGetVariableAndSize (
2174 L"AttemptOrder",
2175 &gIScsiConfigGuid,
2176 &AttemptConfigOrderSize
2177 );
2178 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);
2179 TotalNumber++;
2180
2181 //
2182 // Append the new created attempt order to the end.
2183 //
2184 AttemptConfigOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));
2185 if (AttemptConfigOrderTmp == NULL) {
2186 if (AttemptConfigOrder != NULL) {
2187 FreePool (AttemptConfigOrder);
2188 }
2189 return EFI_OUT_OF_RESOURCES;
2190 }
2191 if (AttemptConfigOrder != NULL) {
2192 CopyMem (AttemptConfigOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);
2193 FreePool (AttemptConfigOrder);
2194 }
2195
2196 AttemptConfigOrderTmp[TotalNumber - 1] = Number;
2197 AttemptConfigOrder = AttemptConfigOrderTmp;
2198 AttemptConfigOrderSize = TotalNumber * sizeof (UINT8);
2199
2200 Status = gRT->SetVariable (
2201 L"AttemptOrder",
2202 &gIScsiConfigGuid,
2203 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
2204 AttemptConfigOrderSize,
2205 AttemptConfigOrder
2206 );
2207 FreePool (AttemptConfigOrder);
2208 if (EFI_ERROR (Status)) {
2209 return Status;
2210 }
2211
2212 //
2213 // Record the attempt in global link list.
2214 //
2215 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
2216 mPrivate->AttemptCount++;
2217 UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", AttemptConfigData->AttemptConfigIndex);
2218 gRT->SetVariable (
2219 mPrivate->PortString,
2220 &gEfiIScsiInitiatorNameProtocolGuid,
2221 ISCSI_CONFIG_VAR_ATTR,
2222 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
2223 AttemptConfigData
2224 );
2225
2226 }
2227
2228 return EFI_SUCCESS;
2229 }
2230
2231 /**
2232 Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword.
2233
2234 @param[in] IfrNvData The IFR NV data.
2235
2236 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2237 @retval EFI_SUCCESS The operation is completed successfully.
2238 @retval EFI_ABOTRED This operation is aborted cause of error
2239 configuration.
2240 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2241 resources.
2242
2243 **/
2244 EFI_STATUS
2245 IScsiConfigDeleteAttempts (
2246 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData
2247 )
2248 {
2249 EFI_STATUS Status;
2250 UINTN Index;
2251 UINTN NewIndex;
2252 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2253 UINT8 *AttemptConfigOrder;
2254 UINTN AttemptConfigOrderSize;
2255 UINT8 *AttemptNewOrder;
2256 UINT8 AttemptConfigIndex;
2257 UINT32 Attribute;
2258 UINTN Total;
2259 UINTN NewTotal;
2260 LIST_ENTRY *Entry;
2261 LIST_ENTRY *NextEntry;
2262 ISCSI_SESSION_CONFIG_NVDATA *ConfigData;
2263
2264 Index = 0;
2265
2266 AttemptConfigOrder = IScsiGetVariableAndSize (
2267 L"AttemptOrder",
2268 &gIScsiConfigGuid,
2269 &AttemptConfigOrderSize
2270 );
2271 if ((AttemptConfigOrder == NULL) || (AttemptConfigOrderSize == 0)) {
2272 return EFI_NOT_FOUND;
2273 }
2274
2275 AttemptNewOrder = AllocateZeroPool (AttemptConfigOrderSize);
2276 if (AttemptNewOrder == NULL) {
2277 Status = EFI_OUT_OF_RESOURCES;
2278 goto Error;
2279 }
2280
2281 Total = AttemptConfigOrderSize / sizeof (UINT8);
2282 NewTotal = Total;
2283
2284 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
2285 if (IfrNvData->DeleteAttemptList[Index] == 0) {
2286 Index++;
2287 continue;
2288 }
2289
2290 //
2291 // Delete the attempt.
2292 //
2293
2294 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
2295 if (AttemptConfigData == NULL) {
2296 Status = EFI_NOT_FOUND;
2297 goto Error;
2298 }
2299
2300 //
2301 // Remove this attempt from UI configured attempt list.
2302 //
2303 RemoveEntryList (&AttemptConfigData->Link);
2304 mPrivate->AttemptCount--;
2305
2306 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
2307 if (mPrivate->MpioCount < 1) {
2308 Status = EFI_ABORTED;
2309 goto Error;
2310 }
2311
2312 //
2313 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
2314 //
2315 if (--mPrivate->MpioCount == 0) {
2316 mPrivate->EnableMpio = FALSE;
2317 }
2318 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
2319 if (mPrivate->SinglePathCount < 1) {
2320 Status = EFI_ABORTED;
2321 goto Error;
2322 }
2323
2324 mPrivate->SinglePathCount--;
2325 }
2326
2327 AttemptConfigIndex = AttemptConfigData->AttemptConfigIndex;
2328 FreePool (AttemptConfigData);
2329
2330 //
2331 // Create a new Attempt
2332 //
2333 AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA));
2334 if (AttemptConfigData == NULL) {
2335 return EFI_OUT_OF_RESOURCES;
2336 }
2337 ConfigData = &AttemptConfigData->SessionConfigData;
2338 ConfigData->TargetPort = ISCSI_WELL_KNOWN_PORT;
2339 ConfigData->ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;
2340 ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY;
2341
2342 AttemptConfigData->AuthenticationType = ISCSI_AUTH_TYPE_CHAP;
2343 AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI;
2344 //
2345 // Configure the Attempt index and set variable.
2346 //
2347 AttemptConfigData->AttemptConfigIndex = AttemptConfigIndex;
2348
2349 //
2350 // Set the attempt name to default.
2351 //
2352 UnicodeSPrint (
2353 mPrivate->PortString,
2354 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2355 L"Attempt %d",
2356 (UINTN) AttemptConfigData->AttemptConfigIndex
2357 );
2358 UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, ATTEMPT_NAME_SIZE);
2359 gRT->SetVariable (
2360 mPrivate->PortString,
2361 &gEfiIScsiInitiatorNameProtocolGuid,
2362 ISCSI_CONFIG_VAR_ATTR,
2363 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
2364 AttemptConfigData
2365 );
2366
2367 //
2368 // Mark the attempt order in NVR to be deleted - 0.
2369 //
2370 for (NewIndex = 0; NewIndex < Total; NewIndex++) {
2371 if (AttemptConfigOrder[NewIndex] == AttemptConfigData->AttemptConfigIndex) {
2372 AttemptConfigOrder[NewIndex] = 0;
2373 break;
2374 }
2375 }
2376
2377 NewTotal--;
2378 if (mCallbackInfo->Current == AttemptConfigData) {
2379 mCallbackInfo->Current = NULL;
2380 }
2381 FreePool (AttemptConfigData);
2382
2383 //
2384 // Check next Attempt.
2385 //
2386 Index++;
2387 }
2388
2389 //
2390 // Construct AttemptNewOrder.
2391 //
2392 for (Index = 0, NewIndex = 0; Index < Total; Index++) {
2393 if (AttemptConfigOrder[Index] != 0) {
2394 AttemptNewOrder[NewIndex] = AttemptConfigOrder[Index];
2395 NewIndex++;
2396 }
2397 }
2398
2399 Attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE;
2400
2401 //
2402 // Update AttemptOrder in NVR.
2403 //
2404 Status = gRT->SetVariable (
2405 L"AttemptOrder",
2406 &gIScsiConfigGuid,
2407 Attribute,
2408 NewTotal * sizeof (UINT8),
2409 AttemptNewOrder
2410 );
2411
2412 Error:
2413 if (AttemptConfigOrder != NULL) {
2414 FreePool (AttemptConfigOrder);
2415 }
2416
2417 if (AttemptNewOrder != NULL) {
2418 FreePool (AttemptNewOrder);
2419 }
2420
2421 return Status;
2422 }
2423
2424
2425 /**
2426 Callback function when user presses "Delete Attempts".
2427
2428 @param[in] IfrNvData The IFR nv data.
2429
2430 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2431 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
2432 @retval EFI_SUCCESS The operation is completed successfully.
2433
2434 **/
2435 EFI_STATUS
2436 IScsiConfigDisplayDeleteAttempts (
2437 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData
2438 )
2439 {
2440
2441 UINT8 *AttemptConfigOrder;
2442 UINTN AttemptConfigOrderSize;
2443 LIST_ENTRY *Entry;
2444 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2445 UINT8 Index;
2446 VOID *StartOpCodeHandle;
2447 EFI_IFR_GUID_LABEL *StartLabel;
2448 VOID *EndOpCodeHandle;
2449 EFI_IFR_GUID_LABEL *EndLabel;
2450 EFI_STATUS Status;
2451
2452 Status = IScsiCreateOpCode (
2453 DELETE_ENTRY_LABEL,
2454 &StartOpCodeHandle,
2455 &StartLabel,
2456 &EndOpCodeHandle,
2457 &EndLabel
2458 );
2459 if (EFI_ERROR (Status)) {
2460 return Status;
2461 }
2462
2463 AttemptConfigOrder = IScsiGetVariableAndSize (
2464 L"AttemptOrder",
2465 &gIScsiConfigGuid,
2466 &AttemptConfigOrderSize
2467 );
2468 if (AttemptConfigOrder != NULL) {
2469 //
2470 // Create the check box opcode to be deleted.
2471 //
2472 Index = 0;
2473
2474 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
2475 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
2476 IfrNvData->DeleteAttemptList[Index] = 0x00;
2477
2478 HiiCreateCheckBoxOpCode(
2479 StartOpCodeHandle,
2480 (EFI_QUESTION_ID) (ATTEMPT_DEL_QUESTION_ID + Index),
2481 CONFIGURATION_VARSTORE_ID,
2482 (UINT16) (ATTEMPT_DEL_VAR_OFFSET + Index),
2483 AttemptConfigData->AttemptTitleToken,
2484 AttemptConfigData->AttemptTitleHelpToken,
2485 0,
2486 0,
2487 NULL
2488 );
2489
2490 Index++;
2491
2492 if (Index == ISCSI_MAX_ATTEMPTS_NUM) {
2493 break;
2494 }
2495 }
2496
2497 FreePool (AttemptConfigOrder);
2498 }
2499
2500 Status = HiiUpdateForm (
2501 mCallbackInfo->RegisteredHandle, // HII handle
2502 &gIScsiConfigGuid, // Formset GUID
2503 FORMID_DELETE_FORM, // Form ID
2504 StartOpCodeHandle, // Label for where to insert opcodes
2505 EndOpCodeHandle // Replace data
2506 );
2507
2508 HiiFreeOpCodeHandle (StartOpCodeHandle);
2509 HiiFreeOpCodeHandle (EndOpCodeHandle);
2510
2511 return Status;
2512 }
2513
2514
2515 /**
2516 Callback function when user presses "Change Attempt Order".
2517
2518 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2519 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2520 operation.
2521 @retval EFI_SUCCESS The operation is completed successfully.
2522
2523 **/
2524 EFI_STATUS
2525 IScsiConfigDisplayOrderAttempts (
2526 VOID
2527 )
2528 {
2529 EFI_STATUS Status;
2530 UINT8 Index;
2531 LIST_ENTRY *Entry;
2532 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2533 VOID *StartOpCodeHandle;
2534 EFI_IFR_GUID_LABEL *StartLabel;
2535 VOID *EndOpCodeHandle;
2536 EFI_IFR_GUID_LABEL *EndLabel;
2537 VOID *OptionsOpCodeHandle;
2538
2539 Status = IScsiCreateOpCode (
2540 ORDER_ENTRY_LABEL,
2541 &StartOpCodeHandle,
2542 &StartLabel,
2543 &EndOpCodeHandle,
2544 &EndLabel
2545 );
2546 if (EFI_ERROR (Status)) {
2547 return Status;
2548 }
2549 ASSERT (StartOpCodeHandle != NULL);
2550
2551 OptionsOpCodeHandle = NULL;
2552
2553 //
2554 // If no attempt to be ordered, update the original form and exit.
2555 //
2556 if (mPrivate->AttemptCount == 0) {
2557 goto Exit;
2558 }
2559
2560 //
2561 // Create Option OpCode.
2562 //
2563 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
2564 if (OptionsOpCodeHandle == NULL) {
2565 Status = EFI_OUT_OF_RESOURCES;
2566 goto Error;
2567 }
2568
2569 Index = 0;
2570
2571 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
2572 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
2573 HiiCreateOneOfOptionOpCode (
2574 OptionsOpCodeHandle,
2575 AttemptConfigData->AttemptTitleToken,
2576 0,
2577 EFI_IFR_NUMERIC_SIZE_1,
2578 AttemptConfigData->AttemptConfigIndex
2579 );
2580 Index++;
2581 }
2582
2583 ASSERT (Index == mPrivate->AttemptCount);
2584
2585 HiiCreateOrderedListOpCode (
2586 StartOpCodeHandle, // Container for dynamic created opcodes
2587 DYNAMIC_ORDERED_LIST_QUESTION_ID, // Question ID
2588 CONFIGURATION_VARSTORE_ID, // VarStore ID
2589 DYNAMIC_ORDERED_LIST_VAR_OFFSET, // Offset in Buffer Storage
2590 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY), // Question prompt text
2591 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY), // Question help text
2592 0, // Question flag
2593 EFI_IFR_UNIQUE_SET, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
2594 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question value
2595 ISCSI_MAX_ATTEMPTS_NUM, // Maximum container
2596 OptionsOpCodeHandle, // Option Opcode list
2597 NULL // Default Opcode is NULL
2598 );
2599
2600 Exit:
2601 Status = HiiUpdateForm (
2602 mCallbackInfo->RegisteredHandle, // HII handle
2603 &gIScsiConfigGuid, // Formset GUID
2604 FORMID_ORDER_FORM, // Form ID
2605 StartOpCodeHandle, // Label for where to insert opcodes
2606 EndOpCodeHandle // Replace data
2607 );
2608
2609 Error:
2610 HiiFreeOpCodeHandle (StartOpCodeHandle);
2611 HiiFreeOpCodeHandle (EndOpCodeHandle);
2612 if (OptionsOpCodeHandle != NULL) {
2613 HiiFreeOpCodeHandle (OptionsOpCodeHandle);
2614 }
2615
2616 return Status;
2617 }
2618
2619 /**
2620 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.
2621
2622 @param[in] IfrNvData The IFR nv data.
2623
2624 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2625 operation.
2626 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2627 @retval EFI_SUCCESS The operation is completed successfully.
2628
2629 **/
2630 EFI_STATUS
2631 IScsiConfigOrderAttempts (
2632 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData
2633 )
2634 {
2635 EFI_STATUS Status;
2636 UINTN Index;
2637 UINTN Indexj;
2638 UINT8 AttemptConfigIndex;
2639 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2640 UINT8 *AttemptConfigOrder;
2641 UINT8 *AttemptConfigOrderTmp;
2642 UINTN AttemptConfigOrderSize;
2643
2644 AttemptConfigOrder = IScsiGetVariableAndSize (
2645 L"AttemptOrder",
2646 &gIScsiConfigGuid,
2647 &AttemptConfigOrderSize
2648 );
2649 if (AttemptConfigOrder == NULL) {
2650 return EFI_NOT_FOUND;
2651 }
2652
2653 AttemptConfigOrderTmp = AllocateZeroPool (AttemptConfigOrderSize);
2654 if (AttemptConfigOrderTmp == NULL) {
2655 Status = EFI_OUT_OF_RESOURCES;
2656 goto Exit;
2657 }
2658
2659 for (Index = 0; Index < ISCSI_MAX_ATTEMPTS_NUM; Index++) {
2660 //
2661 // The real content ends with 0.
2662 //
2663 if (IfrNvData->DynamicOrderedList[Index] == 0) {
2664 break;
2665 }
2666
2667 AttemptConfigIndex = IfrNvData->DynamicOrderedList[Index];
2668 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex);
2669 if (AttemptConfigData == NULL) {
2670 Status = EFI_NOT_FOUND;
2671 goto Exit;
2672 }
2673
2674 //
2675 // Reorder the Attempt List.
2676 //
2677 RemoveEntryList (&AttemptConfigData->Link);
2678 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
2679
2680 AttemptConfigOrderTmp[Index] = AttemptConfigIndex;
2681
2682 //
2683 // Mark it to be deleted - 0.
2684 //
2685 for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) {
2686 if (AttemptConfigOrder[Indexj] == AttemptConfigIndex) {
2687 AttemptConfigOrder[Indexj] = 0;
2688 break;
2689 }
2690 }
2691 }
2692
2693 //
2694 // Adjust the attempt order in NVR.
2695 //
2696 for (; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
2697 for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) {
2698 if (AttemptConfigOrder[Indexj] != 0) {
2699 AttemptConfigOrderTmp[Index] = AttemptConfigOrder[Indexj];
2700 AttemptConfigOrder[Indexj] = 0;
2701 continue;
2702 }
2703 }
2704 }
2705
2706 Status = gRT->SetVariable (
2707 L"AttemptOrder",
2708 &gIScsiConfigGuid,
2709 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
2710 AttemptConfigOrderSize,
2711 AttemptConfigOrderTmp
2712 );
2713
2714 Exit:
2715 if (AttemptConfigOrderTmp != NULL) {
2716 FreePool (AttemptConfigOrderTmp);
2717 }
2718
2719 FreePool (AttemptConfigOrder);
2720 return Status;
2721 }
2722
2723
2724 /**
2725 Callback function when a user presses "Attempt *" or when a user selects a NIC to
2726 create the new attempt.
2727
2728 @param[in] KeyValue A unique value which is sent to the original
2729 exporting driver so that it can identify the type
2730 of data to expect.
2731 @param[in] IfrNvData The IFR nv data.
2732
2733 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2734 operation.
2735 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2736 @retval EFI_UNSUPPORTED Can not create more attempts.
2737 @retval EFI_SUCCESS The operation is completed successfully.
2738
2739 **/
2740 EFI_STATUS
2741 IScsiConfigProcessDefault (
2742 IN EFI_QUESTION_ID KeyValue,
2743 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData
2744 )
2745 {
2746 BOOLEAN NewAttempt;
2747 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2748 UINT8 CurrentAttemptConfigIndex;
2749 ISCSI_NIC_INFO *NicInfo;
2750 UINT8 NicIndex;
2751 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
2752 UINT8 *AttemptConfigOrder;
2753 UINTN AttemptConfigOrderSize;
2754 UINTN Index;
2755 EFI_INPUT_KEY Key;
2756
2757 AttemptConfigData = NULL;
2758 //
2759 // Is User creating a new attempt?
2760 //
2761 NewAttempt = FALSE;
2762
2763 if ((KeyValue >= KEY_MAC_ENTRY_BASE) &&
2764 (KeyValue <= (UINT16) (mPrivate->MaxNic + KEY_MAC_ENTRY_BASE))) {
2765 //
2766 // User has pressed "Add an Attempt" and then selects a NIC.
2767 //
2768 NewAttempt = TRUE;
2769 } else if ((KeyValue >= KEY_ATTEMPT_ENTRY_BASE) &&
2770 (KeyValue < (ISCSI_MAX_ATTEMPTS_NUM + KEY_ATTEMPT_ENTRY_BASE))) {
2771
2772 //
2773 // User has pressed "Attempt *".
2774 //
2775 NewAttempt = FALSE;
2776 } else {
2777 //
2778 // Don't process anything.
2779 //
2780 return EFI_SUCCESS;
2781 }
2782
2783 if (NewAttempt) {
2784 //
2785 // Determine which NIC user has selected for the new created attempt.
2786 //
2787 NicIndex = (UINT8) (KeyValue - KEY_MAC_ENTRY_BASE);
2788 NicInfo = IScsiGetNicInfoByIndex (NicIndex);
2789 if (NicInfo == NULL) {
2790 return EFI_NOT_FOUND;
2791 }
2792
2793 //
2794 // Create an attempt following the initialized attempt order.
2795 //
2796 AttemptConfigOrder = IScsiGetVariableAndSize (
2797 L"InitialAttemptOrder",
2798 &gIScsiConfigGuid,
2799 &AttemptConfigOrderSize
2800 );
2801
2802 if (AttemptConfigOrder == NULL) {
2803 return EFI_NOT_FOUND;
2804 }
2805
2806 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
2807 UnicodeSPrint (
2808 mPrivate->PortString,
2809 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2810 L"Attempt %d",
2811 (UINTN) AttemptConfigOrder[Index]
2812 );
2813 GetVariable2 (
2814 mPrivate->PortString,
2815 &gEfiIScsiInitiatorNameProtocolGuid,
2816 (VOID**)&AttemptConfigData,
2817 NULL
2818 );
2819 if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED) {
2820 continue;
2821 }
2822
2823 break;
2824 }
2825
2826 if (Index > PcdGet8 (PcdMaxIScsiAttemptNumber)) {
2827 CreatePopUp (
2828 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2829 &Key,
2830 L"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",
2831 NULL
2832 );
2833 return EFI_UNSUPPORTED;
2834 }
2835
2836 if (AttemptConfigOrder != NULL) {
2837 FreePool (AttemptConfigOrder);
2838 }
2839
2840 //
2841 // Record the MAC info in Config Data.
2842 //
2843 IScsiMacAddrToStr (
2844 &NicInfo->PermanentAddress,
2845 NicInfo->HwAddressSize,
2846 NicInfo->VlanId,
2847 MacString
2848 );
2849
2850 ASSERT (AttemptConfigData != NULL);
2851 UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, sizeof (AttemptConfigData->MacString));
2852 AttemptConfigData->NicIndex = NicIndex;
2853 AttemptConfigData->Actived = ISCSI_ACTIVE_ENABLED;
2854
2855 //
2856 // Generate OUI-format ISID based on MAC address.
2857 //
2858 CopyMem (AttemptConfigData->SessionConfigData.IsId, &NicInfo->PermanentAddress, 6);
2859 AttemptConfigData->SessionConfigData.IsId[0] =
2860 (UINT8) (AttemptConfigData->SessionConfigData.IsId[0] & 0x3F);
2861
2862 //
2863 // Add the help info for the new attempt.
2864 //
2865 UnicodeSPrint (
2866 mPrivate->PortString,
2867 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2868 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
2869 MacString,
2870 NicInfo->BusNumber,
2871 NicInfo->DeviceNumber,
2872 NicInfo->FunctionNumber
2873 );
2874
2875 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (
2876 mCallbackInfo->RegisteredHandle,
2877 0,
2878 mPrivate->PortString,
2879 NULL
2880 );
2881 if (AttemptConfigData->AttemptTitleHelpToken == 0) {
2882 FreePool (AttemptConfigData);
2883 return EFI_OUT_OF_RESOURCES;
2884 }
2885
2886 } else {
2887 //
2888 // Determine which Attempt user has selected to configure.
2889 // Get the attempt configuration data.
2890 //
2891 CurrentAttemptConfigIndex = (UINT8) (KeyValue - KEY_ATTEMPT_ENTRY_BASE);
2892
2893 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex);
2894 if (AttemptConfigData == NULL) {
2895 DEBUG ((DEBUG_ERROR, "Corresponding configuration data can not be retrieved!\n"));
2896 return EFI_NOT_FOUND;
2897 }
2898 }
2899
2900 //
2901 // Clear the old IFR data to avoid sharing it with other attempts.
2902 //
2903 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
2904 ZeroMem (IfrNvData->CHAPName, sizeof (IfrNvData->CHAPName));
2905 ZeroMem (IfrNvData->CHAPSecret, sizeof (IfrNvData->CHAPSecret));
2906 ZeroMem (IfrNvData->ReverseCHAPName, sizeof (IfrNvData->ReverseCHAPName));
2907 ZeroMem (IfrNvData->ReverseCHAPSecret, sizeof (IfrNvData->ReverseCHAPSecret));
2908 }
2909
2910 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData, IfrNvData);
2911
2912 //
2913 // Update current attempt to be a new created attempt or an existing attempt.
2914 //
2915 mCallbackInfo->Current = AttemptConfigData;
2916
2917 return EFI_SUCCESS;
2918 }
2919
2920
2921 /**
2922
2923 This function allows the caller to request the current
2924 configuration for one or more named elements. The resulting
2925 string is in <ConfigAltResp> format. Also, any and all alternative
2926 configuration strings shall be appended to the end of the
2927 current configuration string. If they are, they must appear
2928 after the current configuration. They must contain the same
2929 routing (GUID, NAME, PATH) as the current configuration string.
2930 They must have an additional description indicating the type of
2931 alternative configuration the string represents,
2932 "ALTCFG=<StringToken>". That <StringToken> (when
2933 converted from Hex UNICODE to binary) is a reference to a
2934 string in the associated string pack.
2935
2936 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2937
2938 @param[in] Request A null-terminated Unicode string in
2939 <ConfigRequest> format. Note that this
2940 includes the routing information as well as
2941 the configurable name / value pairs. It is
2942 invalid for this string to be in
2943 <MultiConfigRequest> format.
2944
2945 @param[out] Progress On return, points to a character in the
2946 Request string. Points to the string's null
2947 terminator if request was successful. Points
2948 to the most recent "&" before the first
2949 failing name / value pair (or the beginning
2950 of the string if the failure is in the first
2951 name / value pair) if the request was not successful.
2952
2953 @param[out] Results A null-terminated Unicode string in
2954 <ConfigAltResp> format which has all values
2955 filled in for the names in the Request string.
2956 String to be allocated by the called function.
2957
2958 @retval EFI_SUCCESS The Results string is filled with the
2959 values corresponding to all requested
2960 names.
2961
2962 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2963 parts of the results that must be
2964 stored awaiting possible future
2965 protocols.
2966
2967 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
2968 for the Request parameter
2969 would result in this type of
2970 error. In this case, the
2971 Progress parameter would be
2972 set to NULL.
2973
2974 @retval EFI_NOT_FOUND Routing data doesn't match any
2975 known driver. Progress set to the
2976 first character in the routing header.
2977 Note: There is no requirement that the
2978 driver validate the routing data. It
2979 must skip the <ConfigHdr> in order to
2980 process the names.
2981
2982 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
2983 to most recent "&" before the
2984 error or the beginning of the
2985 string.
2986
2987 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
2988 to the & before the name in
2989 question.
2990
2991 **/
2992 EFI_STATUS
2993 EFIAPI
2994 IScsiFormExtractConfig (
2995 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
2996 IN CONST EFI_STRING Request,
2997 OUT EFI_STRING *Progress,
2998 OUT EFI_STRING *Results
2999 )
3000 {
3001 EFI_STATUS Status;
3002 CHAR8 *InitiatorName;
3003 UINTN BufferSize;
3004 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
3005 ISCSI_FORM_CALLBACK_INFO *Private;
3006 EFI_STRING ConfigRequestHdr;
3007 EFI_STRING ConfigRequest;
3008 BOOLEAN AllocatedRequest;
3009 UINTN Size;
3010
3011 if (This == NULL || Progress == NULL || Results == NULL) {
3012 return EFI_INVALID_PARAMETER;
3013 }
3014
3015 *Progress = Request;
3016 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gIScsiConfigGuid, mVendorStorageName)) {
3017 return EFI_NOT_FOUND;
3018 }
3019
3020 ConfigRequestHdr = NULL;
3021 ConfigRequest = NULL;
3022 AllocatedRequest = FALSE;
3023 Size = 0;
3024
3025 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
3026 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));
3027 if (IfrNvData == NULL) {
3028 return EFI_OUT_OF_RESOURCES;
3029 }
3030
3031
3032 if (Private->Current!= NULL) {
3033 IScsiConvertAttemptConfigDataToIfrNvData (Private->Current, IfrNvData);
3034 }
3035
3036 //
3037 // Extract all AttemptConfigData to Keyword stroage of IfrNvData.
3038 //
3039 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData);
3040
3041 BufferSize = ISCSI_NAME_MAX_SIZE;
3042 InitiatorName = (CHAR8 *) AllocateZeroPool (BufferSize);
3043 if (InitiatorName == NULL) {
3044 FreePool (IfrNvData);
3045 return EFI_OUT_OF_RESOURCES;
3046 }
3047
3048 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);
3049 if (EFI_ERROR (Status)) {
3050 IfrNvData->InitiatorName[0] = L'\0';
3051 } else {
3052 AsciiStrToUnicodeStrS (
3053 InitiatorName,
3054 IfrNvData->InitiatorName,
3055 sizeof (IfrNvData->InitiatorName) / sizeof (IfrNvData->InitiatorName[0])
3056 );
3057 }
3058
3059 //
3060 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
3061 //
3062 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
3063 ConfigRequest = Request;
3064 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
3065 //
3066 // Request has no request element, construct full request string.
3067 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3068 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3069 //
3070 ConfigRequestHdr = HiiConstructConfigHdr (&gIScsiConfigGuid, mVendorStorageName, Private->DriverHandle);
3071 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
3072 ConfigRequest = AllocateZeroPool (Size);
3073 if (ConfigRequest == NULL) {
3074 FreePool (IfrNvData);
3075 FreePool (InitiatorName);
3076 return EFI_OUT_OF_RESOURCES;
3077 }
3078 AllocatedRequest = TRUE;
3079 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
3080 FreePool (ConfigRequestHdr);
3081 }
3082
3083 Status = gHiiConfigRouting->BlockToConfig (
3084 gHiiConfigRouting,
3085 ConfigRequest,
3086 (UINT8 *) IfrNvData,
3087 BufferSize,
3088 Results,
3089 Progress
3090 );
3091 FreePool (IfrNvData);
3092 FreePool (InitiatorName);
3093
3094 //
3095 // Free the allocated config request string.
3096 //
3097 if (AllocatedRequest) {
3098 FreePool (ConfigRequest);
3099 ConfigRequest = NULL;
3100 }
3101 //
3102 // Set Progress string to the original request string.
3103 //
3104 if (Request == NULL) {
3105 *Progress = NULL;
3106 } else if (StrStr (Request, L"OFFSET") == NULL) {
3107 *Progress = Request + StrLen (Request);
3108 }
3109
3110 return Status;
3111 }
3112
3113
3114 /**
3115
3116 This function applies changes in a driver's configuration.
3117 Input is a Configuration, which has the routing data for this
3118 driver followed by name / value configuration pairs. The driver
3119 must apply those pairs to its configurable storage. If the
3120 driver's configuration is stored in a linear block of data
3121 and the driver's name / value pairs are in <BlockConfig>
3122 format, it may use the ConfigToBlock helper function (above) to
3123 simplify the job.
3124
3125 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3126
3127 @param[in] Configuration A null-terminated Unicode string in
3128 <ConfigString> format.
3129
3130 @param[out] Progress A pointer to a string filled in with the
3131 offset of the most recent '&' before the
3132 first failing name / value pair (or the
3133 beginning of the string if the failure
3134 is in the first name / value pair) or
3135 the terminating NULL if all was
3136 successful.
3137
3138 @retval EFI_SUCCESS The results have been distributed or are
3139 awaiting distribution.
3140
3141 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
3142 parts of the results that must be
3143 stored awaiting possible future
3144 protocols.
3145
3146 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
3147 Results parameter would result
3148 in this type of error.
3149
3150 @retval EFI_NOT_FOUND Target for the specified routing data
3151 was not found.
3152
3153 **/
3154 EFI_STATUS
3155 EFIAPI
3156 IScsiFormRouteConfig (
3157 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
3158 IN CONST EFI_STRING Configuration,
3159 OUT EFI_STRING *Progress
3160 )
3161 {
3162 EFI_STATUS Status;
3163 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
3164 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
3165 LIST_ENTRY *Entry;
3166 LIST_ENTRY *NextEntry;
3167 ISCSI_NIC_INFO *NicInfo;
3168 EFI_INPUT_KEY Key;
3169 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
3170 CHAR8 *InitiatorName;
3171 UINT8 *AttemptList;
3172 UINTN BufferSize;
3173 UINTN OffSet;
3174 UINTN Index;
3175 UINTN Index2;
3176
3177 Index = 0;
3178 Index2 = 0;
3179 NicInfo = NULL;
3180 AttemptList = NULL;
3181 Status = EFI_SUCCESS;
3182
3183 if (This == NULL || Configuration == NULL || Progress == NULL) {
3184 return EFI_INVALID_PARAMETER;
3185 }
3186
3187 //
3188 // Check routing data in <ConfigHdr>.
3189 // Note: if only one Storage is used, then this checking could be skipped.
3190 //
3191 if (!HiiIsConfigHdrMatch (Configuration, &gIScsiConfigGuid, mVendorStorageName)) {
3192 *Progress = Configuration;
3193 return EFI_NOT_FOUND;
3194 }
3195
3196 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));
3197 if (IfrNvData == NULL) {
3198 return EFI_OUT_OF_RESOURCES;
3199 }
3200
3201 BufferSize = ISCSI_NAME_MAX_SIZE;
3202 InitiatorName = (CHAR8 *) AllocateZeroPool (BufferSize);
3203 if (InitiatorName == NULL) {
3204 Status = EFI_OUT_OF_RESOURCES;
3205 goto Exit;
3206 }
3207
3208 //
3209 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
3210 //
3211 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
3212 Status = gHiiConfigRouting->ConfigToBlock (
3213 gHiiConfigRouting,
3214 Configuration,
3215 (UINT8 *) IfrNvData,
3216 &BufferSize,
3217 Progress
3218 );
3219 if (EFI_ERROR (Status)) {
3220 goto Exit;
3221 }
3222
3223 if (IfrNvData->InitiatorName[0] != L'\0') {
3224 UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, InitiatorName, ISCSI_NAME_MAX_SIZE);
3225 BufferSize = AsciiStrSize (InitiatorName);
3226
3227 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, InitiatorName);
3228 if (EFI_ERROR (Status)) {
3229 CreatePopUp (
3230 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3231 &Key,
3232 L"Invalid iSCSI Name!",
3233 NULL
3234 );
3235 goto Exit;
3236 }
3237 } else {
3238 Status = IScsiGetValue (Configuration, L"&OFFSET=", &OffSet);
3239 if (EFI_ERROR (Status)) {
3240 goto Exit;
3241 }
3242
3243 if (OffSet >= ATTEMPT_MAC_ADDR_VAR_OFFSET) {
3244 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);
3245 if (EFI_ERROR (Status)) {
3246 CreatePopUp (
3247 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3248 &Key,
3249 L"Error: please configure iSCSI initiator name first!",
3250 NULL
3251 );
3252 goto Exit;
3253 }
3254 } else {
3255 goto Exit;
3256 }
3257
3258 if (IfrNvData->ISCSIAddAttemptList[0] != L'\0') {
3259 Status =IScsiGetAttemptIndexList (IfrNvData->ISCSIAddAttemptList, IfrNvData->AddAttemptList, TRUE);
3260 if (EFI_ERROR (Status)) {
3261 CreatePopUp (
3262 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3263 &Key,
3264 L"Error: The add attempt list is invalid",
3265 NULL
3266 );
3267 goto Exit;
3268 }
3269
3270 Status = IScsiConfigAddAttemptsByKeywords (IfrNvData->AddAttemptList);
3271 if (EFI_ERROR (Status)) {
3272 goto Exit;
3273 }
3274
3275 } else if (IfrNvData->ISCSIDeleteAttemptList[0] != L'\0') {
3276 AttemptList =(UINT8 *) AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM + 1) * sizeof (UINT8));
3277 if (AttemptList == NULL) {
3278 Status = EFI_OUT_OF_RESOURCES;
3279 goto Exit;
3280 }
3281 Status = IScsiGetAttemptIndexList (IfrNvData->ISCSIDeleteAttemptList, AttemptList, FALSE);
3282 if (EFI_ERROR (Status)) {
3283 CreatePopUp (
3284 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3285 &Key,
3286 L"Error: The delete attempt list is invalid",
3287 NULL
3288 );
3289 goto Exit;
3290 }
3291
3292 //
3293 // Mark the attempt which will be delete in the global list.
3294 //
3295 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
3296 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
3297 while (AttemptList[Index] != 0) {
3298 if (AttemptConfigData->AttemptConfigIndex == AttemptList[Index]) {
3299 IfrNvData->DeleteAttemptList[Index2] = 1;
3300 break;
3301 }
3302 Index ++;
3303 }
3304 Index2 ++;
3305 Index = 0;
3306 }
3307
3308 Status = IScsiConfigDeleteAttempts (IfrNvData);
3309 if (EFI_ERROR (Status)) {
3310 goto Exit;
3311 }
3312
3313 FreePool (AttemptList);
3314
3315 } else if (IfrNvData->ISCSIAttemptOrder[0] != L'\0') {
3316 Status = IScsiGetAttemptIndexList (IfrNvData->ISCSIAttemptOrder, IfrNvData->DynamicOrderedList, FALSE);
3317 if (EFI_ERROR (Status)) {
3318 CreatePopUp (
3319 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3320 &Key,
3321 L"Error: The new attempt order list is invalid",
3322 NULL
3323 );
3324 goto Exit;
3325 }
3326
3327 Status = IScsiConfigOrderAttempts (IfrNvData);
3328 if (EFI_ERROR (Status)) {
3329 goto Exit;
3330 }
3331
3332 } else if (IfrNvData->ISCSIMacAddr[0] != L'\0') {
3333 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
3334 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
3335 IScsiMacAddrToStr (
3336 &NicInfo->PermanentAddress,
3337 NicInfo->HwAddressSize,
3338 NicInfo->VlanId,
3339 MacString
3340 );
3341 if (!StrCmp(MacString, IfrNvData->ISCSIMacAddr)) {
3342 mPrivate->CurrentNic = NicInfo->NicIndex;
3343 break;
3344 }
3345 }
3346
3347 if ((NicInfo == NULL) || (NicInfo->NicIndex == 0)) {
3348 Status = EFI_NOT_FOUND;
3349 goto Exit;
3350 }
3351
3352 } else {
3353 Status = IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData, OffSet);
3354 if (EFI_ERROR (Status)) {
3355 goto Exit;
3356 }
3357 }
3358 }
3359
3360 IScsiConfigUpdateAttempt ();
3361
3362 Exit:
3363 if (InitiatorName != NULL) {
3364 FreePool (InitiatorName);
3365 }
3366
3367 if (IfrNvData != NULL) {
3368 FreePool (IfrNvData);
3369 }
3370
3371 return Status;
3372 }
3373
3374 /**
3375
3376 This function is called to provide results data to the driver.
3377 This data consists of a unique key that is used to identify
3378 which data is either being passed back or being asked for.
3379
3380 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3381 @param[in] Action Specifies the type of action taken by the browser.
3382 @param[in] QuestionId A unique value which is sent to the original
3383 exporting driver so that it can identify the type
3384 of data to expect. The format of the data tends to
3385 vary based on the opcode that generated the callback.
3386 @param[in] Type The type of value for the question.
3387 @param[in, out] Value A pointer to the data being sent to the original
3388 exporting driver.
3389 @param[out] ActionRequest On return, points to the action requested by the
3390 callback function.
3391
3392 @retval EFI_SUCCESS The callback successfully handled the action.
3393 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3394 variable and its data.
3395 @retval EFI_DEVICE_ERROR The variable could not be saved.
3396 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3397 callback.
3398 **/
3399 EFI_STATUS
3400 EFIAPI
3401 IScsiFormCallback (
3402 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
3403 IN EFI_BROWSER_ACTION Action,
3404 IN EFI_QUESTION_ID QuestionId,
3405 IN UINT8 Type,
3406 IN OUT EFI_IFR_TYPE_VALUE *Value,
3407 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
3408 )
3409 {
3410 ISCSI_FORM_CALLBACK_INFO *Private;
3411 UINTN BufferSize;
3412 CHAR8 *IScsiName;
3413 CHAR8 IpString[ISCSI_NAME_MAX_SIZE];
3414 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];
3415 UINT64 Lun;
3416 EFI_IP_ADDRESS HostIp;
3417 EFI_IP_ADDRESS SubnetMask;
3418 EFI_IP_ADDRESS Gateway;
3419 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
3420 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData;
3421 EFI_STATUS Status;
3422 EFI_INPUT_KEY Key;
3423 ISCSI_NIC_INFO *NicInfo;
3424
3425 NicInfo = NULL;
3426
3427 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
3428 //
3429 // Do nothing for UEFI OPEN/CLOSE Action
3430 //
3431 return EFI_SUCCESS;
3432 }
3433
3434 if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {
3435 //
3436 // All other type return unsupported.
3437 //
3438 return EFI_UNSUPPORTED;
3439 }
3440
3441 if ((Value == NULL) || (ActionRequest == NULL)) {
3442 return EFI_INVALID_PARAMETER;
3443 }
3444
3445 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
3446
3447 //
3448 // Retrieve uncommitted data from Browser
3449 //
3450
3451 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
3452 IfrNvData = AllocateZeroPool (BufferSize);
3453 if (IfrNvData == NULL) {
3454 return EFI_OUT_OF_RESOURCES;
3455 }
3456
3457 IScsiName = (CHAR8 *) AllocateZeroPool (ISCSI_NAME_MAX_SIZE);
3458 if (IScsiName == NULL) {
3459 FreePool (IfrNvData);
3460 return EFI_OUT_OF_RESOURCES;
3461 }
3462
3463 Status = EFI_SUCCESS;
3464
3465 ZeroMem (&OldIfrNvData, BufferSize);
3466
3467 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);
3468
3469 CopyMem (&OldIfrNvData, IfrNvData, BufferSize);
3470
3471 if (Action == EFI_BROWSER_ACTION_CHANGING) {
3472 switch (QuestionId) {
3473 case KEY_ADD_ATTEMPT:
3474 //
3475 // Check whether iSCSI initiator name is configured already.
3476 //
3477 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
3478 Status = gIScsiInitiatorName.Get (
3479 &gIScsiInitiatorName,
3480 &mPrivate->InitiatorNameLength,
3481 mPrivate->InitiatorName
3482 );
3483 if (EFI_ERROR (Status)) {
3484 CreatePopUp (
3485 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3486 &Key,
3487 L"Error: please configure iSCSI initiator name first!",
3488 NULL
3489 );
3490 break;
3491 }
3492
3493 Status = IScsiConfigAddAttempt ();
3494 break;
3495
3496 case KEY_DELETE_ATTEMPT:
3497 CopyMem (
3498 OldIfrNvData.DeleteAttemptList,
3499 IfrNvData->DeleteAttemptList,
3500 sizeof (IfrNvData->DeleteAttemptList)
3501 );
3502 Status = IScsiConfigDisplayDeleteAttempts (IfrNvData);
3503 break;
3504
3505 case KEY_ORDER_ATTEMPT_CONFIG:
3506 //
3507 // Order the attempt according to user input.
3508 //
3509 CopyMem (
3510 OldIfrNvData.DynamicOrderedList,
3511 IfrNvData->DynamicOrderedList,
3512 sizeof (IfrNvData->DynamicOrderedList)
3513 );
3514 IScsiConfigDisplayOrderAttempts ();
3515 break;
3516
3517 default:
3518 Status = IScsiConfigProcessDefault (QuestionId, IfrNvData);
3519 break;
3520 }
3521 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
3522 switch (QuestionId) {
3523 case KEY_INITIATOR_NAME:
3524 UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, IScsiName, ISCSI_NAME_MAX_SIZE);
3525 BufferSize = AsciiStrSize (IScsiName);
3526
3527 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);
3528 if (EFI_ERROR (Status)) {
3529 CreatePopUp (
3530 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3531 &Key,
3532 L"Invalid iSCSI Name!",
3533 NULL
3534 );
3535 }
3536
3537 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
3538 break;
3539
3540 case KEY_SAVE_ATTEMPT_CONFIG:
3541 Status = IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData, Private->Current);
3542 if (EFI_ERROR (Status)) {
3543 break;
3544 }
3545
3546 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
3547 break;
3548
3549 case KEY_SAVE_ORDER_CHANGES:
3550 //
3551 // Sync the Attempt Order to NVR.
3552 //
3553 Status = IScsiConfigOrderAttempts (IfrNvData);
3554 if (EFI_ERROR (Status)) {
3555 break;
3556 }
3557
3558 IScsiConfigUpdateAttempt ();
3559 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
3560 break;
3561
3562 case KEY_IGNORE_ORDER_CHANGES:
3563 CopyMem (
3564 IfrNvData->DynamicOrderedList,
3565 OldIfrNvData.DynamicOrderedList,
3566 sizeof (IfrNvData->DynamicOrderedList)
3567 );
3568 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
3569 break;
3570
3571 case KEY_SAVE_DELETE_ATTEMPT:
3572 //
3573 // Delete the Attempt Order from NVR
3574 //
3575 Status = IScsiConfigDeleteAttempts (IfrNvData);
3576 if (EFI_ERROR (Status)) {
3577 break;
3578 }
3579
3580 IScsiConfigUpdateAttempt ();
3581 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
3582 break;
3583
3584 case KEY_IGNORE_DELETE_ATTEMPT:
3585 CopyMem (
3586 IfrNvData->DeleteAttemptList,
3587 OldIfrNvData.DeleteAttemptList,
3588 sizeof (IfrNvData->DeleteAttemptList)
3589 );
3590 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
3591 break;
3592
3593 case KEY_IP_MODE:
3594 switch (Value->u8) {
3595 case IP_MODE_IP6:
3596 NicInfo = IScsiGetNicInfoByIndex (Private->Current->NicIndex);
3597 if(NicInfo == NULL) {
3598 break;
3599 }
3600
3601 if(!NicInfo->Ipv6Available) {
3602 //
3603 // Current NIC doesn't Support IPv6, hence use IPv4.
3604 //
3605 IfrNvData->IpMode = IP_MODE_IP4;
3606
3607 CreatePopUp (
3608 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3609 &Key,
3610 L"Current NIC doesn't Support IPv6!",
3611 NULL
3612 );
3613 }
3614
3615 case IP_MODE_IP4:
3616 ZeroMem (IfrNvData->LocalIp, sizeof (IfrNvData->LocalIp));
3617 ZeroMem (IfrNvData->SubnetMask, sizeof (IfrNvData->SubnetMask));
3618 ZeroMem (IfrNvData->Gateway, sizeof (IfrNvData->Gateway));
3619 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));
3620 Private->Current->AutoConfigureMode = 0;
3621 ZeroMem (&Private->Current->SessionConfigData.LocalIp, sizeof (EFI_IP_ADDRESS));
3622 ZeroMem (&Private->Current->SessionConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
3623 ZeroMem (&Private->Current->SessionConfigData.Gateway, sizeof (EFI_IP_ADDRESS));
3624 ZeroMem (&Private->Current->SessionConfigData.TargetIp, sizeof (EFI_IP_ADDRESS));
3625
3626 break;
3627 }
3628
3629 break;
3630
3631 case KEY_LOCAL_IP:
3632 Status = NetLibStrToIp4 (IfrNvData->LocalIp, &HostIp.v4);
3633 if (EFI_ERROR (Status) ||
3634 ((Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) &&
3635 !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), NTOHL(*(UINT32*)Private->Current->SessionConfigData.SubnetMask.Addr)))) {
3636 CreatePopUp (
3637 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3638 &Key,
3639 L"Invalid IP address!",
3640 NULL
3641 );
3642
3643 Status = EFI_INVALID_PARAMETER;
3644 } else {
3645 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
3646 }
3647
3648 break;
3649
3650 case KEY_SUBNET_MASK:
3651 Status = NetLibStrToIp4 (IfrNvData->SubnetMask, &SubnetMask.v4);
3652 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
3653 CreatePopUp (
3654 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3655 &Key,
3656 L"Invalid Subnet Mask!",
3657 NULL
3658 );
3659
3660 Status = EFI_INVALID_PARAMETER;
3661 } else {
3662 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
3663 }
3664
3665 break;
3666
3667 case KEY_GATE_WAY:
3668 Status = NetLibStrToIp4 (IfrNvData->Gateway, &Gateway.v4);
3669 if (EFI_ERROR (Status) ||
3670 ((Gateway.Addr[0] != 0) &&
3671 (Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) &&
3672 !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL(*(UINT32*)Private->Current->SessionConfigData.SubnetMask.Addr)))) {
3673 CreatePopUp (
3674 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3675 &Key,
3676 L"Invalid Gateway!",
3677 NULL
3678 );
3679 Status = EFI_INVALID_PARAMETER;
3680 } else {
3681 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));
3682 }
3683
3684 break;
3685
3686 case KEY_TARGET_IP:
3687 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, IpString, sizeof (IpString));
3688 Status = IScsiAsciiStrToIp (IpString, IfrNvData->IpMode, &HostIp);
3689 if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, IfrNvData->IpMode)) {
3690 //
3691 // The target is expressed in URL format or an invalid Ip address, just save.
3692 //
3693 Private->Current->SessionConfigData.DnsMode = TRUE;
3694 ZeroMem (&Private->Current->SessionConfigData.TargetIp, sizeof (Private->Current->SessionConfigData.TargetIp));
3695 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, Private->Current->SessionConfigData.TargetUrl, ISCSI_NAME_MAX_SIZE);
3696 } else {
3697 Private->Current->SessionConfigData.DnsMode = FALSE;
3698 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp));
3699 }
3700
3701 break;
3702
3703 case KEY_TARGET_NAME:
3704 UnicodeStrToAsciiStrS (IfrNvData->TargetName, IScsiName, ISCSI_NAME_MAX_SIZE);
3705 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));
3706 if (EFI_ERROR (Status)) {
3707 CreatePopUp (
3708 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3709 &Key,
3710 L"Invalid iSCSI Name!",
3711 NULL
3712 );
3713 } else {
3714 AsciiStrCpyS (Private->Current->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName);
3715 }
3716
3717 break;
3718
3719 case KEY_DHCP_ENABLE:
3720 if (IfrNvData->InitiatorInfoFromDhcp == 0) {
3721 IfrNvData->TargetInfoFromDhcp = 0;
3722 }
3723
3724 break;
3725
3726 case KEY_BOOT_LUN:
3727 UnicodeStrToAsciiStrS (IfrNvData->BootLun, LunString, sizeof (LunString));
3728 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);
3729 if (EFI_ERROR (Status)) {
3730 CreatePopUp (
3731 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3732 &Key,
3733 L"Invalid LUN string!",
3734 NULL
3735 );
3736 } else {
3737 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));
3738 }
3739
3740 break;
3741
3742 case KEY_AUTH_TYPE:
3743 switch (Value->u8) {
3744 case ISCSI_AUTH_TYPE_CHAP:
3745 IfrNvData->CHAPType = ISCSI_CHAP_UNI;
3746 break;
3747 default:
3748 break;
3749 }
3750
3751 break;
3752
3753 case KEY_CHAP_NAME:
3754 UnicodeStrToAsciiStrS (
3755 IfrNvData->CHAPName,
3756 Private->Current->AuthConfigData.CHAP.CHAPName,
3757 sizeof (Private->Current->AuthConfigData.CHAP.CHAPName)
3758 );
3759 break;
3760
3761 case KEY_CHAP_SECRET:
3762 UnicodeStrToAsciiStrS (
3763 IfrNvData->CHAPSecret,
3764 Private->Current->AuthConfigData.CHAP.CHAPSecret,
3765 sizeof (Private->Current->AuthConfigData.CHAP.CHAPSecret)
3766 );
3767 break;
3768
3769 case KEY_REVERSE_CHAP_NAME:
3770 UnicodeStrToAsciiStrS (
3771 IfrNvData->ReverseCHAPName,
3772 Private->Current->AuthConfigData.CHAP.ReverseCHAPName,
3773 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPName)
3774 );
3775 break;
3776
3777 case KEY_REVERSE_CHAP_SECRET:
3778 UnicodeStrToAsciiStrS (
3779 IfrNvData->ReverseCHAPSecret,
3780 Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret,
3781 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret)
3782 );
3783 break;
3784
3785 case KEY_CONFIG_ISID:
3786 IScsiParseIsIdFromString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);
3787 IScsiConvertIsIdToString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);
3788
3789 break;
3790
3791 default:
3792 break;
3793 }
3794 }
3795
3796 if (!EFI_ERROR (Status)) {
3797 //
3798 // Pass changed uncommitted data back to Form Browser.
3799 //
3800 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
3801 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);
3802 }
3803
3804 FreePool (IfrNvData);
3805 FreePool (IScsiName);
3806
3807 return Status;
3808 }
3809
3810
3811 /**
3812 Initialize the iSCSI configuration form.
3813
3814 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3815
3816 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
3817 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
3818
3819 **/
3820 EFI_STATUS
3821 IScsiConfigFormInit (
3822 IN EFI_HANDLE DriverBindingHandle
3823 )
3824 {
3825 EFI_STATUS Status;
3826 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;
3827
3828 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO));
3829 if (CallbackInfo == NULL) {
3830 return EFI_OUT_OF_RESOURCES;
3831 }
3832
3833 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;
3834 CallbackInfo->Current = NULL;
3835
3836 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;
3837 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;
3838 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;
3839
3840 //
3841 // Install Device Path Protocol and Config Access protocol to driver handle.
3842 //
3843 Status = gBS->InstallMultipleProtocolInterfaces (
3844 &CallbackInfo->DriverHandle,
3845 &gEfiDevicePathProtocolGuid,
3846 &mIScsiHiiVendorDevicePath,
3847 &gEfiHiiConfigAccessProtocolGuid,
3848 &CallbackInfo->ConfigAccess,
3849 NULL
3850 );
3851 ASSERT_EFI_ERROR (Status);
3852
3853 //
3854 // Publish our HII data.
3855 //
3856 CallbackInfo->RegisteredHandle = HiiAddPackages (
3857 &gIScsiConfigGuid,
3858 CallbackInfo->DriverHandle,
3859 IScsiDxeStrings,
3860 IScsiConfigVfrBin,
3861 NULL
3862 );
3863 if (CallbackInfo->RegisteredHandle == NULL) {
3864 gBS->UninstallMultipleProtocolInterfaces (
3865 &CallbackInfo->DriverHandle,
3866 &gEfiDevicePathProtocolGuid,
3867 &mIScsiHiiVendorDevicePath,
3868 &gEfiHiiConfigAccessProtocolGuid,
3869 &CallbackInfo->ConfigAccess,
3870 NULL
3871 );
3872 FreePool(CallbackInfo);
3873 return EFI_OUT_OF_RESOURCES;
3874 }
3875
3876 mCallbackInfo = CallbackInfo;
3877
3878 return EFI_SUCCESS;
3879 }
3880
3881
3882 /**
3883 Unload the iSCSI configuration form, this includes: delete all the iSCSI
3884 configuration entries, uninstall the form callback protocol, and
3885 free the resources used.
3886
3887 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3888
3889 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
3890 @retval Others Failed to unload the form.
3891
3892 **/
3893 EFI_STATUS
3894 IScsiConfigFormUnload (
3895 IN EFI_HANDLE DriverBindingHandle
3896 )
3897 {
3898 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
3899 ISCSI_NIC_INFO *NicInfo;
3900 LIST_ENTRY *Entry;
3901 EFI_STATUS Status;
3902
3903 while (!IsListEmpty (&mPrivate->AttemptConfigs)) {
3904 Entry = NetListRemoveHead (&mPrivate->AttemptConfigs);
3905 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
3906 FreePool (AttemptConfigData);
3907 mPrivate->AttemptCount--;
3908 }
3909
3910 ASSERT (mPrivate->AttemptCount == 0);
3911
3912 while (!IsListEmpty (&mPrivate->NicInfoList)) {
3913 Entry = NetListRemoveHead (&mPrivate->NicInfoList);
3914 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
3915 FreePool (NicInfo);
3916 mPrivate->NicCount--;
3917 }
3918
3919 ASSERT (mPrivate->NicCount == 0);
3920
3921 FreePool (mPrivate);
3922 mPrivate = NULL;
3923
3924 //
3925 // Remove HII package list.
3926 //
3927 HiiRemovePackages (mCallbackInfo->RegisteredHandle);
3928
3929 //
3930 // Uninstall Device Path Protocol and Config Access protocol.
3931 //
3932 Status = gBS->UninstallMultipleProtocolInterfaces (
3933 mCallbackInfo->DriverHandle,
3934 &gEfiDevicePathProtocolGuid,
3935 &mIScsiHiiVendorDevicePath,
3936 &gEfiHiiConfigAccessProtocolGuid,
3937 &mCallbackInfo->ConfigAccess,
3938 NULL
3939 );
3940
3941 FreePool (mCallbackInfo);
3942
3943 return Status;
3944 }