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