VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/IScsiDxe/IScsiConfig.c

Last change on this file was 108794, checked in by vboxsync, 4 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette