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