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