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