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