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