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