]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IScsiDxe/IScsiConfig.c
78135b411c6973a7eedc9b3c4d585298a47ecfec
[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 - 2019, 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
2296 //
2297 // Remove this attempt from UI configured attempt list.
2298 //
2299 RemoveEntryList (&AttemptConfigData->Link);
2300 mPrivate->AttemptCount--;
2301
2302 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
2303 if (mPrivate->MpioCount < 1) {
2304 Status = EFI_ABORTED;
2305 goto Error;
2306 }
2307
2308 //
2309 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
2310 //
2311 if (--mPrivate->MpioCount == 0) {
2312 mPrivate->EnableMpio = FALSE;
2313 }
2314 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
2315 if (mPrivate->SinglePathCount < 1) {
2316 Status = EFI_ABORTED;
2317 goto Error;
2318 }
2319
2320 mPrivate->SinglePathCount--;
2321 }
2322
2323 AttemptConfigIndex = AttemptConfigData->AttemptConfigIndex;
2324 FreePool (AttemptConfigData);
2325
2326 //
2327 // Create a new Attempt
2328 //
2329 AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA));
2330 if (AttemptConfigData == NULL) {
2331 return EFI_OUT_OF_RESOURCES;
2332 }
2333 ConfigData = &AttemptConfigData->SessionConfigData;
2334 ConfigData->TargetPort = ISCSI_WELL_KNOWN_PORT;
2335 ConfigData->ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;
2336 ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY;
2337
2338 AttemptConfigData->AuthenticationType = ISCSI_AUTH_TYPE_CHAP;
2339 AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI;
2340 //
2341 // Configure the Attempt index and set variable.
2342 //
2343 AttemptConfigData->AttemptConfigIndex = AttemptConfigIndex;
2344
2345 //
2346 // Set the attempt name to default.
2347 //
2348 UnicodeSPrint (
2349 mPrivate->PortString,
2350 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2351 L"Attempt %d",
2352 (UINTN) AttemptConfigData->AttemptConfigIndex
2353 );
2354 UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, ATTEMPT_NAME_SIZE);
2355 gRT->SetVariable (
2356 mPrivate->PortString,
2357 &gEfiIScsiInitiatorNameProtocolGuid,
2358 ISCSI_CONFIG_VAR_ATTR,
2359 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
2360 AttemptConfigData
2361 );
2362
2363 //
2364 // Mark the attempt order in NVR to be deleted - 0.
2365 //
2366 for (NewIndex = 0; NewIndex < Total; NewIndex++) {
2367 if (AttemptConfigOrder[NewIndex] == AttemptConfigData->AttemptConfigIndex) {
2368 AttemptConfigOrder[NewIndex] = 0;
2369 break;
2370 }
2371 }
2372
2373 NewTotal--;
2374 if (mCallbackInfo->Current == AttemptConfigData) {
2375 mCallbackInfo->Current = NULL;
2376 }
2377 FreePool (AttemptConfigData);
2378
2379 //
2380 // Check next Attempt.
2381 //
2382 Index++;
2383 }
2384
2385 //
2386 // Construct AttemptNewOrder.
2387 //
2388 for (Index = 0, NewIndex = 0; Index < Total; Index++) {
2389 if (AttemptConfigOrder[Index] != 0) {
2390 AttemptNewOrder[NewIndex] = AttemptConfigOrder[Index];
2391 NewIndex++;
2392 }
2393 }
2394
2395 Attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE;
2396
2397 //
2398 // Update AttemptOrder in NVR.
2399 //
2400 Status = gRT->SetVariable (
2401 L"AttemptOrder",
2402 &gIScsiConfigGuid,
2403 Attribute,
2404 NewTotal * sizeof (UINT8),
2405 AttemptNewOrder
2406 );
2407
2408 Error:
2409 if (AttemptConfigOrder != NULL) {
2410 FreePool (AttemptConfigOrder);
2411 }
2412
2413 if (AttemptNewOrder != NULL) {
2414 FreePool (AttemptNewOrder);
2415 }
2416
2417 return Status;
2418 }
2419
2420
2421 /**
2422 Callback function when user presses "Delete Attempts".
2423
2424 @param[in] IfrNvData The IFR nv data.
2425
2426 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2427 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
2428 @retval EFI_SUCCESS The operation is completed successfully.
2429
2430 **/
2431 EFI_STATUS
2432 IScsiConfigDisplayDeleteAttempts (
2433 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData
2434 )
2435 {
2436
2437 UINT8 *AttemptConfigOrder;
2438 UINTN AttemptConfigOrderSize;
2439 LIST_ENTRY *Entry;
2440 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2441 UINT8 Index;
2442 VOID *StartOpCodeHandle;
2443 EFI_IFR_GUID_LABEL *StartLabel;
2444 VOID *EndOpCodeHandle;
2445 EFI_IFR_GUID_LABEL *EndLabel;
2446 EFI_STATUS Status;
2447
2448 Status = IScsiCreateOpCode (
2449 DELETE_ENTRY_LABEL,
2450 &StartOpCodeHandle,
2451 &StartLabel,
2452 &EndOpCodeHandle,
2453 &EndLabel
2454 );
2455 if (EFI_ERROR (Status)) {
2456 return Status;
2457 }
2458
2459 AttemptConfigOrder = IScsiGetVariableAndSize (
2460 L"AttemptOrder",
2461 &gIScsiConfigGuid,
2462 &AttemptConfigOrderSize
2463 );
2464 if (AttemptConfigOrder != NULL) {
2465 //
2466 // Create the check box opcode to be deleted.
2467 //
2468 Index = 0;
2469
2470 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
2471 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
2472 IfrNvData->DeleteAttemptList[Index] = 0x00;
2473
2474 HiiCreateCheckBoxOpCode(
2475 StartOpCodeHandle,
2476 (EFI_QUESTION_ID) (ATTEMPT_DEL_QUESTION_ID + Index),
2477 CONFIGURATION_VARSTORE_ID,
2478 (UINT16) (ATTEMPT_DEL_VAR_OFFSET + Index),
2479 AttemptConfigData->AttemptTitleToken,
2480 AttemptConfigData->AttemptTitleHelpToken,
2481 0,
2482 0,
2483 NULL
2484 );
2485
2486 Index++;
2487
2488 if (Index == ISCSI_MAX_ATTEMPTS_NUM) {
2489 break;
2490 }
2491 }
2492
2493 FreePool (AttemptConfigOrder);
2494 }
2495
2496 Status = HiiUpdateForm (
2497 mCallbackInfo->RegisteredHandle, // HII handle
2498 &gIScsiConfigGuid, // Formset GUID
2499 FORMID_DELETE_FORM, // Form ID
2500 StartOpCodeHandle, // Label for where to insert opcodes
2501 EndOpCodeHandle // Replace data
2502 );
2503
2504 HiiFreeOpCodeHandle (StartOpCodeHandle);
2505 HiiFreeOpCodeHandle (EndOpCodeHandle);
2506
2507 return Status;
2508 }
2509
2510
2511 /**
2512 Callback function when user presses "Change Attempt Order".
2513
2514 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2515 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2516 operation.
2517 @retval EFI_SUCCESS The operation is completed successfully.
2518
2519 **/
2520 EFI_STATUS
2521 IScsiConfigDisplayOrderAttempts (
2522 VOID
2523 )
2524 {
2525 EFI_STATUS Status;
2526 UINT8 Index;
2527 LIST_ENTRY *Entry;
2528 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2529 VOID *StartOpCodeHandle;
2530 EFI_IFR_GUID_LABEL *StartLabel;
2531 VOID *EndOpCodeHandle;
2532 EFI_IFR_GUID_LABEL *EndLabel;
2533 VOID *OptionsOpCodeHandle;
2534
2535 Status = IScsiCreateOpCode (
2536 ORDER_ENTRY_LABEL,
2537 &StartOpCodeHandle,
2538 &StartLabel,
2539 &EndOpCodeHandle,
2540 &EndLabel
2541 );
2542 if (EFI_ERROR (Status)) {
2543 return Status;
2544 }
2545 ASSERT (StartOpCodeHandle != NULL);
2546
2547 OptionsOpCodeHandle = NULL;
2548
2549 //
2550 // If no attempt to be ordered, update the original form and exit.
2551 //
2552 if (mPrivate->AttemptCount == 0) {
2553 goto Exit;
2554 }
2555
2556 //
2557 // Create Option OpCode.
2558 //
2559 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
2560 if (OptionsOpCodeHandle == NULL) {
2561 Status = EFI_OUT_OF_RESOURCES;
2562 goto Error;
2563 }
2564
2565 Index = 0;
2566
2567 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
2568 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
2569 HiiCreateOneOfOptionOpCode (
2570 OptionsOpCodeHandle,
2571 AttemptConfigData->AttemptTitleToken,
2572 0,
2573 EFI_IFR_NUMERIC_SIZE_1,
2574 AttemptConfigData->AttemptConfigIndex
2575 );
2576 Index++;
2577 }
2578
2579 ASSERT (Index == mPrivate->AttemptCount);
2580
2581 HiiCreateOrderedListOpCode (
2582 StartOpCodeHandle, // Container for dynamic created opcodes
2583 DYNAMIC_ORDERED_LIST_QUESTION_ID, // Question ID
2584 CONFIGURATION_VARSTORE_ID, // VarStore ID
2585 DYNAMIC_ORDERED_LIST_VAR_OFFSET, // Offset in Buffer Storage
2586 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY), // Question prompt text
2587 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY), // Question help text
2588 0, // Question flag
2589 EFI_IFR_UNIQUE_SET, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
2590 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question value
2591 ISCSI_MAX_ATTEMPTS_NUM, // Maximum container
2592 OptionsOpCodeHandle, // Option Opcode list
2593 NULL // Default Opcode is NULL
2594 );
2595
2596 Exit:
2597 Status = HiiUpdateForm (
2598 mCallbackInfo->RegisteredHandle, // HII handle
2599 &gIScsiConfigGuid, // Formset GUID
2600 FORMID_ORDER_FORM, // Form ID
2601 StartOpCodeHandle, // Label for where to insert opcodes
2602 EndOpCodeHandle // Replace data
2603 );
2604
2605 Error:
2606 HiiFreeOpCodeHandle (StartOpCodeHandle);
2607 HiiFreeOpCodeHandle (EndOpCodeHandle);
2608 if (OptionsOpCodeHandle != NULL) {
2609 HiiFreeOpCodeHandle (OptionsOpCodeHandle);
2610 }
2611
2612 return Status;
2613 }
2614
2615 /**
2616 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.
2617
2618 @param[in] IfrNvData The IFR nv data.
2619
2620 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2621 operation.
2622 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2623 @retval EFI_SUCCESS The operation is completed successfully.
2624
2625 **/
2626 EFI_STATUS
2627 IScsiConfigOrderAttempts (
2628 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData
2629 )
2630 {
2631 EFI_STATUS Status;
2632 UINTN Index;
2633 UINTN Indexj;
2634 UINT8 AttemptConfigIndex;
2635 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2636 UINT8 *AttemptConfigOrder;
2637 UINT8 *AttemptConfigOrderTmp;
2638 UINTN AttemptConfigOrderSize;
2639
2640 AttemptConfigOrder = IScsiGetVariableAndSize (
2641 L"AttemptOrder",
2642 &gIScsiConfigGuid,
2643 &AttemptConfigOrderSize
2644 );
2645 if (AttemptConfigOrder == NULL) {
2646 return EFI_NOT_FOUND;
2647 }
2648
2649 AttemptConfigOrderTmp = AllocateZeroPool (AttemptConfigOrderSize);
2650 if (AttemptConfigOrderTmp == NULL) {
2651 Status = EFI_OUT_OF_RESOURCES;
2652 goto Exit;
2653 }
2654
2655 for (Index = 0; Index < ISCSI_MAX_ATTEMPTS_NUM; Index++) {
2656 //
2657 // The real content ends with 0.
2658 //
2659 if (IfrNvData->DynamicOrderedList[Index] == 0) {
2660 break;
2661 }
2662
2663 AttemptConfigIndex = IfrNvData->DynamicOrderedList[Index];
2664 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex);
2665 if (AttemptConfigData == NULL) {
2666 Status = EFI_NOT_FOUND;
2667 goto Exit;
2668 }
2669
2670 //
2671 // Reorder the Attempt List.
2672 //
2673 RemoveEntryList (&AttemptConfigData->Link);
2674 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
2675
2676 AttemptConfigOrderTmp[Index] = AttemptConfigIndex;
2677
2678 //
2679 // Mark it to be deleted - 0.
2680 //
2681 for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) {
2682 if (AttemptConfigOrder[Indexj] == AttemptConfigIndex) {
2683 AttemptConfigOrder[Indexj] = 0;
2684 break;
2685 }
2686 }
2687 }
2688
2689 //
2690 // Adjust the attempt order in NVR.
2691 //
2692 for (; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
2693 for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) {
2694 if (AttemptConfigOrder[Indexj] != 0) {
2695 AttemptConfigOrderTmp[Index] = AttemptConfigOrder[Indexj];
2696 AttemptConfigOrder[Indexj] = 0;
2697 continue;
2698 }
2699 }
2700 }
2701
2702 Status = gRT->SetVariable (
2703 L"AttemptOrder",
2704 &gIScsiConfigGuid,
2705 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
2706 AttemptConfigOrderSize,
2707 AttemptConfigOrderTmp
2708 );
2709
2710 Exit:
2711 if (AttemptConfigOrderTmp != NULL) {
2712 FreePool (AttemptConfigOrderTmp);
2713 }
2714
2715 FreePool (AttemptConfigOrder);
2716 return Status;
2717 }
2718
2719
2720 /**
2721 Callback function when a user presses "Attempt *" or when a user selects a NIC to
2722 create the new attempt.
2723
2724 @param[in] KeyValue A unique value which is sent to the original
2725 exporting driver so that it can identify the type
2726 of data to expect.
2727 @param[in] IfrNvData The IFR nv data.
2728
2729 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2730 operation.
2731 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2732 @retval EFI_UNSUPPORTED Can not create more attempts.
2733 @retval EFI_SUCCESS The operation is completed successfully.
2734
2735 **/
2736 EFI_STATUS
2737 IScsiConfigProcessDefault (
2738 IN EFI_QUESTION_ID KeyValue,
2739 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData
2740 )
2741 {
2742 BOOLEAN NewAttempt;
2743 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2744 UINT8 CurrentAttemptConfigIndex;
2745 ISCSI_NIC_INFO *NicInfo;
2746 UINT8 NicIndex;
2747 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
2748 UINT8 *AttemptConfigOrder;
2749 UINTN AttemptConfigOrderSize;
2750 UINTN Index;
2751 EFI_INPUT_KEY Key;
2752
2753 AttemptConfigData = NULL;
2754 //
2755 // Is User creating a new attempt?
2756 //
2757 NewAttempt = FALSE;
2758
2759 if ((KeyValue >= KEY_MAC_ENTRY_BASE) &&
2760 (KeyValue <= (UINT16) (mPrivate->MaxNic + KEY_MAC_ENTRY_BASE))) {
2761 //
2762 // User has pressed "Add an Attempt" and then selects a NIC.
2763 //
2764 NewAttempt = TRUE;
2765 } else if ((KeyValue >= KEY_ATTEMPT_ENTRY_BASE) &&
2766 (KeyValue < (ISCSI_MAX_ATTEMPTS_NUM + KEY_ATTEMPT_ENTRY_BASE))) {
2767
2768 //
2769 // User has pressed "Attempt *".
2770 //
2771 NewAttempt = FALSE;
2772 } else {
2773 //
2774 // Don't process anything.
2775 //
2776 return EFI_SUCCESS;
2777 }
2778
2779 if (NewAttempt) {
2780 //
2781 // Determine which NIC user has selected for the new created attempt.
2782 //
2783 NicIndex = (UINT8) (KeyValue - KEY_MAC_ENTRY_BASE);
2784 NicInfo = IScsiGetNicInfoByIndex (NicIndex);
2785 if (NicInfo == NULL) {
2786 return EFI_NOT_FOUND;
2787 }
2788
2789 //
2790 // Create an attempt following the initialized attempt order.
2791 //
2792 AttemptConfigOrder = IScsiGetVariableAndSize (
2793 L"InitialAttemptOrder",
2794 &gIScsiConfigGuid,
2795 &AttemptConfigOrderSize
2796 );
2797
2798 if (AttemptConfigOrder == NULL) {
2799 return EFI_NOT_FOUND;
2800 }
2801
2802 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
2803 UnicodeSPrint (
2804 mPrivate->PortString,
2805 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2806 L"Attempt %d",
2807 (UINTN) AttemptConfigOrder[Index]
2808 );
2809 GetVariable2 (
2810 mPrivate->PortString,
2811 &gEfiIScsiInitiatorNameProtocolGuid,
2812 (VOID**)&AttemptConfigData,
2813 NULL
2814 );
2815 if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED) {
2816 continue;
2817 }
2818
2819 break;
2820 }
2821
2822 if (Index > PcdGet8 (PcdMaxIScsiAttemptNumber)) {
2823 CreatePopUp (
2824 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2825 &Key,
2826 L"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",
2827 NULL
2828 );
2829 return EFI_UNSUPPORTED;
2830 }
2831
2832 if (AttemptConfigOrder != NULL) {
2833 FreePool (AttemptConfigOrder);
2834 }
2835
2836 //
2837 // Record the MAC info in Config Data.
2838 //
2839 IScsiMacAddrToStr (
2840 &NicInfo->PermanentAddress,
2841 NicInfo->HwAddressSize,
2842 NicInfo->VlanId,
2843 MacString
2844 );
2845
2846 ASSERT (AttemptConfigData != NULL);
2847 UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, sizeof (AttemptConfigData->MacString));
2848 AttemptConfigData->NicIndex = NicIndex;
2849 AttemptConfigData->Actived = ISCSI_ACTIVE_ENABLED;
2850
2851 //
2852 // Generate OUI-format ISID based on MAC address.
2853 //
2854 CopyMem (AttemptConfigData->SessionConfigData.IsId, &NicInfo->PermanentAddress, 6);
2855 AttemptConfigData->SessionConfigData.IsId[0] =
2856 (UINT8) (AttemptConfigData->SessionConfigData.IsId[0] & 0x3F);
2857
2858 //
2859 // Add the help info for the new attempt.
2860 //
2861 UnicodeSPrint (
2862 mPrivate->PortString,
2863 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2864 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
2865 MacString,
2866 NicInfo->BusNumber,
2867 NicInfo->DeviceNumber,
2868 NicInfo->FunctionNumber
2869 );
2870
2871 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (
2872 mCallbackInfo->RegisteredHandle,
2873 0,
2874 mPrivate->PortString,
2875 NULL
2876 );
2877 if (AttemptConfigData->AttemptTitleHelpToken == 0) {
2878 FreePool (AttemptConfigData);
2879 return EFI_OUT_OF_RESOURCES;
2880 }
2881
2882 } else {
2883 //
2884 // Determine which Attempt user has selected to configure.
2885 // Get the attempt configuration data.
2886 //
2887 CurrentAttemptConfigIndex = (UINT8) (KeyValue - KEY_ATTEMPT_ENTRY_BASE);
2888
2889 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex);
2890 if (AttemptConfigData == NULL) {
2891 DEBUG ((DEBUG_ERROR, "Corresponding configuration data can not be retrieved!\n"));
2892 return EFI_NOT_FOUND;
2893 }
2894 }
2895
2896 //
2897 // Clear the old IFR data to avoid sharing it with other attempts.
2898 //
2899 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
2900 ZeroMem (IfrNvData->CHAPName, sizeof (IfrNvData->CHAPName));
2901 ZeroMem (IfrNvData->CHAPSecret, sizeof (IfrNvData->CHAPSecret));
2902 ZeroMem (IfrNvData->ReverseCHAPName, sizeof (IfrNvData->ReverseCHAPName));
2903 ZeroMem (IfrNvData->ReverseCHAPSecret, sizeof (IfrNvData->ReverseCHAPSecret));
2904 }
2905
2906 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData, IfrNvData);
2907
2908 //
2909 // Update current attempt to be a new created attempt or an existing attempt.
2910 //
2911 mCallbackInfo->Current = AttemptConfigData;
2912
2913 return EFI_SUCCESS;
2914 }
2915
2916
2917 /**
2918
2919 This function allows the caller to request the current
2920 configuration for one or more named elements. The resulting
2921 string is in <ConfigAltResp> format. Also, any and all alternative
2922 configuration strings shall be appended to the end of the
2923 current configuration string. If they are, they must appear
2924 after the current configuration. They must contain the same
2925 routing (GUID, NAME, PATH) as the current configuration string.
2926 They must have an additional description indicating the type of
2927 alternative configuration the string represents,
2928 "ALTCFG=<StringToken>". That <StringToken> (when
2929 converted from Hex UNICODE to binary) is a reference to a
2930 string in the associated string pack.
2931
2932 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2933
2934 @param[in] Request A null-terminated Unicode string in
2935 <ConfigRequest> format. Note that this
2936 includes the routing information as well as
2937 the configurable name / value pairs. It is
2938 invalid for this string to be in
2939 <MultiConfigRequest> format.
2940
2941 @param[out] Progress On return, points to a character in the
2942 Request string. Points to the string's null
2943 terminator if request was successful. Points
2944 to the most recent "&" before the first
2945 failing name / value pair (or the beginning
2946 of the string if the failure is in the first
2947 name / value pair) if the request was not successful.
2948
2949 @param[out] Results A null-terminated Unicode string in
2950 <ConfigAltResp> format which has all values
2951 filled in for the names in the Request string.
2952 String to be allocated by the called function.
2953
2954 @retval EFI_SUCCESS The Results string is filled with the
2955 values corresponding to all requested
2956 names.
2957
2958 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2959 parts of the results that must be
2960 stored awaiting possible future
2961 protocols.
2962
2963 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
2964 for the Request parameter
2965 would result in this type of
2966 error. In this case, the
2967 Progress parameter would be
2968 set to NULL.
2969
2970 @retval EFI_NOT_FOUND Routing data doesn't match any
2971 known driver. Progress set to the
2972 first character in the routing header.
2973 Note: There is no requirement that the
2974 driver validate the routing data. It
2975 must skip the <ConfigHdr> in order to
2976 process the names.
2977
2978 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
2979 to most recent "&" before the
2980 error or the beginning of the
2981 string.
2982
2983 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
2984 to the & before the name in
2985 question.
2986
2987 **/
2988 EFI_STATUS
2989 EFIAPI
2990 IScsiFormExtractConfig (
2991 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
2992 IN CONST EFI_STRING Request,
2993 OUT EFI_STRING *Progress,
2994 OUT EFI_STRING *Results
2995 )
2996 {
2997 EFI_STATUS Status;
2998 CHAR8 *InitiatorName;
2999 UINTN BufferSize;
3000 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
3001 ISCSI_FORM_CALLBACK_INFO *Private;
3002 EFI_STRING ConfigRequestHdr;
3003 EFI_STRING ConfigRequest;
3004 BOOLEAN AllocatedRequest;
3005 UINTN Size;
3006
3007 if (This == NULL || Progress == NULL || Results == NULL) {
3008 return EFI_INVALID_PARAMETER;
3009 }
3010
3011 *Progress = Request;
3012 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gIScsiConfigGuid, mVendorStorageName)) {
3013 return EFI_NOT_FOUND;
3014 }
3015
3016 ConfigRequestHdr = NULL;
3017 ConfigRequest = NULL;
3018 AllocatedRequest = FALSE;
3019 Size = 0;
3020
3021 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
3022 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));
3023 if (IfrNvData == NULL) {
3024 return EFI_OUT_OF_RESOURCES;
3025 }
3026
3027
3028 if (Private->Current!= NULL) {
3029 IScsiConvertAttemptConfigDataToIfrNvData (Private->Current, IfrNvData);
3030 }
3031
3032 //
3033 // Extract all AttemptConfigData to Keyword stroage of IfrNvData.
3034 //
3035 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData);
3036
3037 BufferSize = ISCSI_NAME_MAX_SIZE;
3038 InitiatorName = (CHAR8 *) AllocateZeroPool (BufferSize);
3039 if (InitiatorName == NULL) {
3040 FreePool (IfrNvData);
3041 return EFI_OUT_OF_RESOURCES;
3042 }
3043
3044 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);
3045 if (EFI_ERROR (Status)) {
3046 IfrNvData->InitiatorName[0] = L'\0';
3047 } else {
3048 AsciiStrToUnicodeStrS (
3049 InitiatorName,
3050 IfrNvData->InitiatorName,
3051 sizeof (IfrNvData->InitiatorName) / sizeof (IfrNvData->InitiatorName[0])
3052 );
3053 }
3054
3055 //
3056 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
3057 //
3058 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
3059 ConfigRequest = Request;
3060 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
3061 //
3062 // Request has no request element, construct full request string.
3063 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3064 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3065 //
3066 ConfigRequestHdr = HiiConstructConfigHdr (&gIScsiConfigGuid, mVendorStorageName, Private->DriverHandle);
3067 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
3068 ConfigRequest = AllocateZeroPool (Size);
3069 if (ConfigRequest == NULL) {
3070 FreePool (IfrNvData);
3071 FreePool (InitiatorName);
3072 return EFI_OUT_OF_RESOURCES;
3073 }
3074 AllocatedRequest = TRUE;
3075 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
3076 FreePool (ConfigRequestHdr);
3077 }
3078
3079 Status = gHiiConfigRouting->BlockToConfig (
3080 gHiiConfigRouting,
3081 ConfigRequest,
3082 (UINT8 *) IfrNvData,
3083 BufferSize,
3084 Results,
3085 Progress
3086 );
3087 FreePool (IfrNvData);
3088 FreePool (InitiatorName);
3089
3090 //
3091 // Free the allocated config request string.
3092 //
3093 if (AllocatedRequest) {
3094 FreePool (ConfigRequest);
3095 ConfigRequest = NULL;
3096 }
3097 //
3098 // Set Progress string to the original request string.
3099 //
3100 if (Request == NULL) {
3101 *Progress = NULL;
3102 } else if (StrStr (Request, L"OFFSET") == NULL) {
3103 *Progress = Request + StrLen (Request);
3104 }
3105
3106 return Status;
3107 }
3108
3109
3110 /**
3111
3112 This function applies changes in a driver's configuration.
3113 Input is a Configuration, which has the routing data for this
3114 driver followed by name / value configuration pairs. The driver
3115 must apply those pairs to its configurable storage. If the
3116 driver's configuration is stored in a linear block of data
3117 and the driver's name / value pairs are in <BlockConfig>
3118 format, it may use the ConfigToBlock helper function (above) to
3119 simplify the job.
3120
3121 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3122
3123 @param[in] Configuration A null-terminated Unicode string in
3124 <ConfigString> format.
3125
3126 @param[out] Progress A pointer to a string filled in with the
3127 offset of the most recent '&' before the
3128 first failing name / value pair (or the
3129 beginning of the string if the failure
3130 is in the first name / value pair) or
3131 the terminating NULL if all was
3132 successful.
3133
3134 @retval EFI_SUCCESS The results have been distributed or are
3135 awaiting distribution.
3136
3137 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
3138 parts of the results that must be
3139 stored awaiting possible future
3140 protocols.
3141
3142 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
3143 Results parameter would result
3144 in this type of error.
3145
3146 @retval EFI_NOT_FOUND Target for the specified routing data
3147 was not found.
3148
3149 **/
3150 EFI_STATUS
3151 EFIAPI
3152 IScsiFormRouteConfig (
3153 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
3154 IN CONST EFI_STRING Configuration,
3155 OUT EFI_STRING *Progress
3156 )
3157 {
3158 EFI_STATUS Status;
3159 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
3160 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
3161 LIST_ENTRY *Entry;
3162 LIST_ENTRY *NextEntry;
3163 ISCSI_NIC_INFO *NicInfo;
3164 EFI_INPUT_KEY Key;
3165 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
3166 CHAR8 *InitiatorName;
3167 UINT8 *AttemptList;
3168 UINTN BufferSize;
3169 UINTN OffSet;
3170 UINTN Index;
3171 UINTN Index2;
3172
3173 Index = 0;
3174 Index2 = 0;
3175 NicInfo = NULL;
3176 AttemptList = NULL;
3177 Status = EFI_SUCCESS;
3178
3179 if (This == NULL || Configuration == NULL || Progress == NULL) {
3180 return EFI_INVALID_PARAMETER;
3181 }
3182
3183 //
3184 // Check routing data in <ConfigHdr>.
3185 // Note: if only one Storage is used, then this checking could be skipped.
3186 //
3187 if (!HiiIsConfigHdrMatch (Configuration, &gIScsiConfigGuid, mVendorStorageName)) {
3188 *Progress = Configuration;
3189 return EFI_NOT_FOUND;
3190 }
3191
3192 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));
3193 if (IfrNvData == NULL) {
3194 return EFI_OUT_OF_RESOURCES;
3195 }
3196
3197 BufferSize = ISCSI_NAME_MAX_SIZE;
3198 InitiatorName = (CHAR8 *) AllocateZeroPool (BufferSize);
3199 if (InitiatorName == NULL) {
3200 Status = EFI_OUT_OF_RESOURCES;
3201 goto Exit;
3202 }
3203
3204 //
3205 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
3206 //
3207 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
3208 Status = gHiiConfigRouting->ConfigToBlock (
3209 gHiiConfigRouting,
3210 Configuration,
3211 (UINT8 *) IfrNvData,
3212 &BufferSize,
3213 Progress
3214 );
3215 if (EFI_ERROR (Status)) {
3216 goto Exit;
3217 }
3218
3219 if (IfrNvData->InitiatorName[0] != L'\0') {
3220 UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, InitiatorName, ISCSI_NAME_MAX_SIZE);
3221 BufferSize = AsciiStrSize (InitiatorName);
3222
3223 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, InitiatorName);
3224 if (EFI_ERROR (Status)) {
3225 CreatePopUp (
3226 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3227 &Key,
3228 L"Invalid iSCSI Name!",
3229 NULL
3230 );
3231 goto Exit;
3232 }
3233 } else {
3234 Status = IScsiGetValue (Configuration, L"&OFFSET=", &OffSet);
3235 if (EFI_ERROR (Status)) {
3236 goto Exit;
3237 }
3238
3239 if (OffSet >= ATTEMPT_MAC_ADDR_VAR_OFFSET) {
3240 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);
3241 if (EFI_ERROR (Status)) {
3242 CreatePopUp (
3243 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3244 &Key,
3245 L"Error: please configure iSCSI initiator name first!",
3246 NULL
3247 );
3248 goto Exit;
3249 }
3250 } else {
3251 goto Exit;
3252 }
3253
3254 if (IfrNvData->ISCSIAddAttemptList[0] != L'\0') {
3255 Status =IScsiGetAttemptIndexList (IfrNvData->ISCSIAddAttemptList, IfrNvData->AddAttemptList, TRUE);
3256 if (EFI_ERROR (Status)) {
3257 CreatePopUp (
3258 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3259 &Key,
3260 L"Error: The add attempt list is invalid",
3261 NULL
3262 );
3263 goto Exit;
3264 }
3265
3266 Status = IScsiConfigAddAttemptsByKeywords (IfrNvData->AddAttemptList);
3267 if (EFI_ERROR (Status)) {
3268 goto Exit;
3269 }
3270
3271 } else if (IfrNvData->ISCSIDeleteAttemptList[0] != L'\0') {
3272 AttemptList =(UINT8 *) AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM + 1) * sizeof (UINT8));
3273 if (AttemptList == NULL) {
3274 Status = EFI_OUT_OF_RESOURCES;
3275 goto Exit;
3276 }
3277 Status = IScsiGetAttemptIndexList (IfrNvData->ISCSIDeleteAttemptList, AttemptList, FALSE);
3278 if (EFI_ERROR (Status)) {
3279 CreatePopUp (
3280 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3281 &Key,
3282 L"Error: The delete attempt list is invalid",
3283 NULL
3284 );
3285 goto Exit;
3286 }
3287
3288 //
3289 // Mark the attempt which will be delete in the global list.
3290 //
3291 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
3292 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
3293 while (AttemptList[Index] != 0) {
3294 if (AttemptConfigData->AttemptConfigIndex == AttemptList[Index]) {
3295 IfrNvData->DeleteAttemptList[Index2] = 1;
3296 break;
3297 }
3298 Index ++;
3299 }
3300 Index2 ++;
3301 Index = 0;
3302 }
3303
3304 Status = IScsiConfigDeleteAttempts (IfrNvData);
3305 if (EFI_ERROR (Status)) {
3306 goto Exit;
3307 }
3308
3309 FreePool (AttemptList);
3310
3311 } else if (IfrNvData->ISCSIAttemptOrder[0] != L'\0') {
3312 Status = IScsiGetAttemptIndexList (IfrNvData->ISCSIAttemptOrder, IfrNvData->DynamicOrderedList, FALSE);
3313 if (EFI_ERROR (Status)) {
3314 CreatePopUp (
3315 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3316 &Key,
3317 L"Error: The new attempt order list is invalid",
3318 NULL
3319 );
3320 goto Exit;
3321 }
3322
3323 Status = IScsiConfigOrderAttempts (IfrNvData);
3324 if (EFI_ERROR (Status)) {
3325 goto Exit;
3326 }
3327
3328 } else if (IfrNvData->ISCSIMacAddr[0] != L'\0') {
3329 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
3330 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
3331 IScsiMacAddrToStr (
3332 &NicInfo->PermanentAddress,
3333 NicInfo->HwAddressSize,
3334 NicInfo->VlanId,
3335 MacString
3336 );
3337 if (!StrCmp(MacString, IfrNvData->ISCSIMacAddr)) {
3338 mPrivate->CurrentNic = NicInfo->NicIndex;
3339 break;
3340 }
3341 }
3342
3343 if ((NicInfo == NULL) || (NicInfo->NicIndex == 0)) {
3344 Status = EFI_NOT_FOUND;
3345 goto Exit;
3346 }
3347
3348 } else {
3349 Status = IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData, OffSet);
3350 if (EFI_ERROR (Status)) {
3351 goto Exit;
3352 }
3353 }
3354 }
3355
3356 IScsiConfigUpdateAttempt ();
3357
3358 Exit:
3359 if (InitiatorName != NULL) {
3360 FreePool (InitiatorName);
3361 }
3362
3363 if (IfrNvData != NULL) {
3364 FreePool (IfrNvData);
3365 }
3366
3367 return Status;
3368 }
3369
3370 /**
3371
3372 This function is called to provide results data to the driver.
3373 This data consists of a unique key that is used to identify
3374 which data is either being passed back or being asked for.
3375
3376 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3377 @param[in] Action Specifies the type of action taken by the browser.
3378 @param[in] QuestionId A unique value which is sent to the original
3379 exporting driver so that it can identify the type
3380 of data to expect. The format of the data tends to
3381 vary based on the opcode that generated the callback.
3382 @param[in] Type The type of value for the question.
3383 @param[in, out] Value A pointer to the data being sent to the original
3384 exporting driver.
3385 @param[out] ActionRequest On return, points to the action requested by the
3386 callback function.
3387
3388 @retval EFI_SUCCESS The callback successfully handled the action.
3389 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3390 variable and its data.
3391 @retval EFI_DEVICE_ERROR The variable could not be saved.
3392 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3393 callback.
3394 **/
3395 EFI_STATUS
3396 EFIAPI
3397 IScsiFormCallback (
3398 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
3399 IN EFI_BROWSER_ACTION Action,
3400 IN EFI_QUESTION_ID QuestionId,
3401 IN UINT8 Type,
3402 IN OUT EFI_IFR_TYPE_VALUE *Value,
3403 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
3404 )
3405 {
3406 ISCSI_FORM_CALLBACK_INFO *Private;
3407 UINTN BufferSize;
3408 CHAR8 *IScsiName;
3409 CHAR8 IpString[ISCSI_NAME_MAX_SIZE];
3410 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];
3411 UINT64 Lun;
3412 EFI_IP_ADDRESS HostIp;
3413 EFI_IP_ADDRESS SubnetMask;
3414 EFI_IP_ADDRESS Gateway;
3415 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
3416 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData;
3417 EFI_STATUS Status;
3418 EFI_INPUT_KEY Key;
3419 ISCSI_NIC_INFO *NicInfo;
3420
3421 NicInfo = NULL;
3422
3423 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
3424 //
3425 // Do nothing for UEFI OPEN/CLOSE Action
3426 //
3427 return EFI_SUCCESS;
3428 }
3429
3430 if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {
3431 //
3432 // All other type return unsupported.
3433 //
3434 return EFI_UNSUPPORTED;
3435 }
3436
3437 if ((Value == NULL) || (ActionRequest == NULL)) {
3438 return EFI_INVALID_PARAMETER;
3439 }
3440
3441 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
3442
3443 //
3444 // Retrieve uncommitted data from Browser
3445 //
3446
3447 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
3448 IfrNvData = AllocateZeroPool (BufferSize);
3449 if (IfrNvData == NULL) {
3450 return EFI_OUT_OF_RESOURCES;
3451 }
3452
3453 IScsiName = (CHAR8 *) AllocateZeroPool (ISCSI_NAME_MAX_SIZE);
3454 if (IScsiName == NULL) {
3455 FreePool (IfrNvData);
3456 return EFI_OUT_OF_RESOURCES;
3457 }
3458
3459 Status = EFI_SUCCESS;
3460
3461 ZeroMem (&OldIfrNvData, BufferSize);
3462
3463 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);
3464
3465 CopyMem (&OldIfrNvData, IfrNvData, BufferSize);
3466
3467 if (Action == EFI_BROWSER_ACTION_CHANGING) {
3468 switch (QuestionId) {
3469 case KEY_ADD_ATTEMPT:
3470 //
3471 // Check whether iSCSI initiator name is configured already.
3472 //
3473 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
3474 Status = gIScsiInitiatorName.Get (
3475 &gIScsiInitiatorName,
3476 &mPrivate->InitiatorNameLength,
3477 mPrivate->InitiatorName
3478 );
3479 if (EFI_ERROR (Status)) {
3480 CreatePopUp (
3481 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3482 &Key,
3483 L"Error: please configure iSCSI initiator name first!",
3484 NULL
3485 );
3486 break;
3487 }
3488
3489 Status = IScsiConfigAddAttempt ();
3490 break;
3491
3492 case KEY_DELETE_ATTEMPT:
3493 CopyMem (
3494 OldIfrNvData.DeleteAttemptList,
3495 IfrNvData->DeleteAttemptList,
3496 sizeof (IfrNvData->DeleteAttemptList)
3497 );
3498 Status = IScsiConfigDisplayDeleteAttempts (IfrNvData);
3499 break;
3500
3501 case KEY_ORDER_ATTEMPT_CONFIG:
3502 //
3503 // Order the attempt according to user input.
3504 //
3505 CopyMem (
3506 OldIfrNvData.DynamicOrderedList,
3507 IfrNvData->DynamicOrderedList,
3508 sizeof (IfrNvData->DynamicOrderedList)
3509 );
3510 IScsiConfigDisplayOrderAttempts ();
3511 break;
3512
3513 default:
3514 Status = IScsiConfigProcessDefault (QuestionId, IfrNvData);
3515 break;
3516 }
3517 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
3518 switch (QuestionId) {
3519 case KEY_INITIATOR_NAME:
3520 UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, IScsiName, ISCSI_NAME_MAX_SIZE);
3521 BufferSize = AsciiStrSize (IScsiName);
3522
3523 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);
3524 if (EFI_ERROR (Status)) {
3525 CreatePopUp (
3526 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3527 &Key,
3528 L"Invalid iSCSI Name!",
3529 NULL
3530 );
3531 }
3532
3533 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
3534 break;
3535
3536 case KEY_SAVE_ATTEMPT_CONFIG:
3537 Status = IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData, Private->Current);
3538 if (EFI_ERROR (Status)) {
3539 break;
3540 }
3541
3542 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
3543 break;
3544
3545 case KEY_SAVE_ORDER_CHANGES:
3546 //
3547 // Sync the Attempt Order to NVR.
3548 //
3549 Status = IScsiConfigOrderAttempts (IfrNvData);
3550 if (EFI_ERROR (Status)) {
3551 break;
3552 }
3553
3554 IScsiConfigUpdateAttempt ();
3555 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
3556 break;
3557
3558 case KEY_IGNORE_ORDER_CHANGES:
3559 CopyMem (
3560 IfrNvData->DynamicOrderedList,
3561 OldIfrNvData.DynamicOrderedList,
3562 sizeof (IfrNvData->DynamicOrderedList)
3563 );
3564 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
3565 break;
3566
3567 case KEY_SAVE_DELETE_ATTEMPT:
3568 //
3569 // Delete the Attempt Order from NVR
3570 //
3571 Status = IScsiConfigDeleteAttempts (IfrNvData);
3572 if (EFI_ERROR (Status)) {
3573 break;
3574 }
3575
3576 IScsiConfigUpdateAttempt ();
3577 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
3578 break;
3579
3580 case KEY_IGNORE_DELETE_ATTEMPT:
3581 CopyMem (
3582 IfrNvData->DeleteAttemptList,
3583 OldIfrNvData.DeleteAttemptList,
3584 sizeof (IfrNvData->DeleteAttemptList)
3585 );
3586 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
3587 break;
3588
3589 case KEY_IP_MODE:
3590 switch (Value->u8) {
3591 case IP_MODE_IP6:
3592 NicInfo = IScsiGetNicInfoByIndex (Private->Current->NicIndex);
3593 if(NicInfo == NULL) {
3594 break;
3595 }
3596
3597 if(!NicInfo->Ipv6Available) {
3598 //
3599 // Current NIC doesn't Support IPv6, hence use IPv4.
3600 //
3601 IfrNvData->IpMode = IP_MODE_IP4;
3602
3603 CreatePopUp (
3604 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3605 &Key,
3606 L"Current NIC doesn't Support IPv6!",
3607 NULL
3608 );
3609 }
3610
3611 case IP_MODE_IP4:
3612 ZeroMem (IfrNvData->LocalIp, sizeof (IfrNvData->LocalIp));
3613 ZeroMem (IfrNvData->SubnetMask, sizeof (IfrNvData->SubnetMask));
3614 ZeroMem (IfrNvData->Gateway, sizeof (IfrNvData->Gateway));
3615 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));
3616 Private->Current->AutoConfigureMode = 0;
3617 ZeroMem (&Private->Current->SessionConfigData.LocalIp, sizeof (EFI_IP_ADDRESS));
3618 ZeroMem (&Private->Current->SessionConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
3619 ZeroMem (&Private->Current->SessionConfigData.Gateway, sizeof (EFI_IP_ADDRESS));
3620 ZeroMem (&Private->Current->SessionConfigData.TargetIp, sizeof (EFI_IP_ADDRESS));
3621
3622 break;
3623 }
3624
3625 break;
3626
3627 case KEY_LOCAL_IP:
3628 Status = NetLibStrToIp4 (IfrNvData->LocalIp, &HostIp.v4);
3629 if (EFI_ERROR (Status) ||
3630 ((Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) &&
3631 !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), NTOHL(*(UINT32*)Private->Current->SessionConfigData.SubnetMask.Addr)))) {
3632 CreatePopUp (
3633 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3634 &Key,
3635 L"Invalid IP address!",
3636 NULL
3637 );
3638
3639 Status = EFI_INVALID_PARAMETER;
3640 } else {
3641 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
3642 }
3643
3644 break;
3645
3646 case KEY_SUBNET_MASK:
3647 Status = NetLibStrToIp4 (IfrNvData->SubnetMask, &SubnetMask.v4);
3648 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
3649 CreatePopUp (
3650 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3651 &Key,
3652 L"Invalid Subnet Mask!",
3653 NULL
3654 );
3655
3656 Status = EFI_INVALID_PARAMETER;
3657 } else {
3658 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
3659 }
3660
3661 break;
3662
3663 case KEY_GATE_WAY:
3664 Status = NetLibStrToIp4 (IfrNvData->Gateway, &Gateway.v4);
3665 if (EFI_ERROR (Status) ||
3666 ((Gateway.Addr[0] != 0) &&
3667 (Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) &&
3668 !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL(*(UINT32*)Private->Current->SessionConfigData.SubnetMask.Addr)))) {
3669 CreatePopUp (
3670 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3671 &Key,
3672 L"Invalid Gateway!",
3673 NULL
3674 );
3675 Status = EFI_INVALID_PARAMETER;
3676 } else {
3677 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));
3678 }
3679
3680 break;
3681
3682 case KEY_TARGET_IP:
3683 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, IpString, sizeof (IpString));
3684 Status = IScsiAsciiStrToIp (IpString, IfrNvData->IpMode, &HostIp);
3685 if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, IfrNvData->IpMode)) {
3686 //
3687 // The target is expressed in URL format or an invalid Ip address, just save.
3688 //
3689 Private->Current->SessionConfigData.DnsMode = TRUE;
3690 ZeroMem (&Private->Current->SessionConfigData.TargetIp, sizeof (Private->Current->SessionConfigData.TargetIp));
3691 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, Private->Current->SessionConfigData.TargetUrl, ISCSI_NAME_MAX_SIZE);
3692 } else {
3693 Private->Current->SessionConfigData.DnsMode = FALSE;
3694 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp));
3695 }
3696
3697 break;
3698
3699 case KEY_TARGET_NAME:
3700 UnicodeStrToAsciiStrS (IfrNvData->TargetName, IScsiName, ISCSI_NAME_MAX_SIZE);
3701 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));
3702 if (EFI_ERROR (Status)) {
3703 CreatePopUp (
3704 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3705 &Key,
3706 L"Invalid iSCSI Name!",
3707 NULL
3708 );
3709 } else {
3710 AsciiStrCpyS (Private->Current->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName);
3711 }
3712
3713 break;
3714
3715 case KEY_DHCP_ENABLE:
3716 if (IfrNvData->InitiatorInfoFromDhcp == 0) {
3717 IfrNvData->TargetInfoFromDhcp = 0;
3718 }
3719
3720 break;
3721
3722 case KEY_BOOT_LUN:
3723 UnicodeStrToAsciiStrS (IfrNvData->BootLun, LunString, sizeof (LunString));
3724 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);
3725 if (EFI_ERROR (Status)) {
3726 CreatePopUp (
3727 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
3728 &Key,
3729 L"Invalid LUN string!",
3730 NULL
3731 );
3732 } else {
3733 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));
3734 }
3735
3736 break;
3737
3738 case KEY_AUTH_TYPE:
3739 switch (Value->u8) {
3740 case ISCSI_AUTH_TYPE_CHAP:
3741 IfrNvData->CHAPType = ISCSI_CHAP_UNI;
3742 break;
3743 default:
3744 break;
3745 }
3746
3747 break;
3748
3749 case KEY_CHAP_NAME:
3750 UnicodeStrToAsciiStrS (
3751 IfrNvData->CHAPName,
3752 Private->Current->AuthConfigData.CHAP.CHAPName,
3753 sizeof (Private->Current->AuthConfigData.CHAP.CHAPName)
3754 );
3755 break;
3756
3757 case KEY_CHAP_SECRET:
3758 UnicodeStrToAsciiStrS (
3759 IfrNvData->CHAPSecret,
3760 Private->Current->AuthConfigData.CHAP.CHAPSecret,
3761 sizeof (Private->Current->AuthConfigData.CHAP.CHAPSecret)
3762 );
3763 break;
3764
3765 case KEY_REVERSE_CHAP_NAME:
3766 UnicodeStrToAsciiStrS (
3767 IfrNvData->ReverseCHAPName,
3768 Private->Current->AuthConfigData.CHAP.ReverseCHAPName,
3769 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPName)
3770 );
3771 break;
3772
3773 case KEY_REVERSE_CHAP_SECRET:
3774 UnicodeStrToAsciiStrS (
3775 IfrNvData->ReverseCHAPSecret,
3776 Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret,
3777 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret)
3778 );
3779 break;
3780
3781 case KEY_CONFIG_ISID:
3782 IScsiParseIsIdFromString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);
3783 IScsiConvertIsIdToString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);
3784
3785 break;
3786
3787 default:
3788 break;
3789 }
3790 }
3791
3792 if (!EFI_ERROR (Status)) {
3793 //
3794 // Pass changed uncommitted data back to Form Browser.
3795 //
3796 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
3797 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);
3798 }
3799
3800 FreePool (IfrNvData);
3801 FreePool (IScsiName);
3802
3803 return Status;
3804 }
3805
3806
3807 /**
3808 Initialize the iSCSI configuration form.
3809
3810 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3811
3812 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
3813 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
3814
3815 **/
3816 EFI_STATUS
3817 IScsiConfigFormInit (
3818 IN EFI_HANDLE DriverBindingHandle
3819 )
3820 {
3821 EFI_STATUS Status;
3822 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;
3823
3824 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO));
3825 if (CallbackInfo == NULL) {
3826 return EFI_OUT_OF_RESOURCES;
3827 }
3828
3829 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;
3830 CallbackInfo->Current = NULL;
3831
3832 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;
3833 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;
3834 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;
3835
3836 //
3837 // Install Device Path Protocol and Config Access protocol to driver handle.
3838 //
3839 Status = gBS->InstallMultipleProtocolInterfaces (
3840 &CallbackInfo->DriverHandle,
3841 &gEfiDevicePathProtocolGuid,
3842 &mIScsiHiiVendorDevicePath,
3843 &gEfiHiiConfigAccessProtocolGuid,
3844 &CallbackInfo->ConfigAccess,
3845 NULL
3846 );
3847 ASSERT_EFI_ERROR (Status);
3848
3849 //
3850 // Publish our HII data.
3851 //
3852 CallbackInfo->RegisteredHandle = HiiAddPackages (
3853 &gIScsiConfigGuid,
3854 CallbackInfo->DriverHandle,
3855 IScsiDxeStrings,
3856 IScsiConfigVfrBin,
3857 NULL
3858 );
3859 if (CallbackInfo->RegisteredHandle == NULL) {
3860 gBS->UninstallMultipleProtocolInterfaces (
3861 &CallbackInfo->DriverHandle,
3862 &gEfiDevicePathProtocolGuid,
3863 &mIScsiHiiVendorDevicePath,
3864 &gEfiHiiConfigAccessProtocolGuid,
3865 &CallbackInfo->ConfigAccess,
3866 NULL
3867 );
3868 FreePool(CallbackInfo);
3869 return EFI_OUT_OF_RESOURCES;
3870 }
3871
3872 mCallbackInfo = CallbackInfo;
3873
3874 return EFI_SUCCESS;
3875 }
3876
3877
3878 /**
3879 Unload the iSCSI configuration form, this includes: delete all the iSCSI
3880 configuration entries, uninstall the form callback protocol, and
3881 free the resources used.
3882
3883 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3884
3885 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
3886 @retval Others Failed to unload the form.
3887
3888 **/
3889 EFI_STATUS
3890 IScsiConfigFormUnload (
3891 IN EFI_HANDLE DriverBindingHandle
3892 )
3893 {
3894 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
3895 ISCSI_NIC_INFO *NicInfo;
3896 LIST_ENTRY *Entry;
3897 EFI_STATUS Status;
3898
3899 while (!IsListEmpty (&mPrivate->AttemptConfigs)) {
3900 Entry = NetListRemoveHead (&mPrivate->AttemptConfigs);
3901 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
3902 FreePool (AttemptConfigData);
3903 mPrivate->AttemptCount--;
3904 }
3905
3906 ASSERT (mPrivate->AttemptCount == 0);
3907
3908 while (!IsListEmpty (&mPrivate->NicInfoList)) {
3909 Entry = NetListRemoveHead (&mPrivate->NicInfoList);
3910 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
3911 FreePool (NicInfo);
3912 mPrivate->NicCount--;
3913 }
3914
3915 ASSERT (mPrivate->NicCount == 0);
3916
3917 FreePool (mPrivate);
3918 mPrivate = NULL;
3919
3920 //
3921 // Remove HII package list.
3922 //
3923 HiiRemovePackages (mCallbackInfo->RegisteredHandle);
3924
3925 //
3926 // Uninstall Device Path Protocol and Config Access protocol.
3927 //
3928 Status = gBS->UninstallMultipleProtocolInterfaces (
3929 mCallbackInfo->DriverHandle,
3930 &gEfiDevicePathProtocolGuid,
3931 &mIScsiHiiVendorDevicePath,
3932 &gEfiHiiConfigAccessProtocolGuid,
3933 &mCallbackInfo->ConfigAccess,
3934 NULL
3935 );
3936
3937 FreePool (mCallbackInfo);
3938
3939 return Status;
3940 }