]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IScsiDxe/IScsiConfig.c
NetworkPkg: Add dns support for target URL configuration in ISCSI.
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiConfig.c
1 /** @file
2 Helper functions for configuring or getting the parameters relating to iSCSI.
3
4 Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "IScsiImpl.h"
16
17 CHAR16 mVendorStorageName[] = L"ISCSI_CONFIG_IFR_NVDATA";
18 BOOLEAN mIScsiDeviceListUpdated = FALSE;
19 UINTN mNumberOfIScsiDevices = 0;
20 ISCSI_FORM_CALLBACK_INFO *mCallbackInfo = NULL;
21
22 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath = {
23 {
24 {
25 HARDWARE_DEVICE_PATH,
26 HW_VENDOR_DP,
27 {
28 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
29 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
30 }
31 },
32 ISCSI_CONFIG_GUID
33 },
34 {
35 END_DEVICE_PATH_TYPE,
36 END_ENTIRE_DEVICE_PATH_SUBTYPE,
37 {
38 (UINT8) (END_DEVICE_PATH_LENGTH),
39 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
40 }
41 }
42 };
43
44
45 /**
46 Convert the IP address into a dotted string.
47
48 @param[in] Ip The IP address.
49 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.
50 @param[out] Str The formatted IP string.
51
52 **/
53 VOID
54 IScsiIpToStr (
55 IN EFI_IP_ADDRESS *Ip,
56 IN BOOLEAN Ipv6Flag,
57 OUT CHAR16 *Str
58 )
59 {
60 EFI_IPv4_ADDRESS *Ip4;
61 EFI_IPv6_ADDRESS *Ip6;
62 UINTN Index;
63 BOOLEAN Short;
64 UINTN Number;
65 CHAR16 FormatString[8];
66
67 if (!Ipv6Flag) {
68 Ip4 = &Ip->v4;
69
70 UnicodeSPrint (
71 Str,
72 (UINTN) 2 * IP4_STR_MAX_SIZE,
73 L"%d.%d.%d.%d",
74 (UINTN) Ip4->Addr[0],
75 (UINTN) Ip4->Addr[1],
76 (UINTN) Ip4->Addr[2],
77 (UINTN) Ip4->Addr[3]
78 );
79
80 return ;
81 }
82
83 Ip6 = &Ip->v6;
84 Short = FALSE;
85
86 for (Index = 0; Index < 15; Index = Index + 2) {
87 if (!Short &&
88 Index % 2 == 0 &&
89 Ip6->Addr[Index] == 0 &&
90 Ip6->Addr[Index + 1] == 0
91 ) {
92 //
93 // Deal with the case of ::.
94 //
95 if (Index == 0) {
96 *Str = L':';
97 *(Str + 1) = L':';
98 Str = Str + 2;
99 } else {
100 *Str = L':';
101 Str = Str + 1;
102 }
103
104 while ((Index < 15) && (Ip6->Addr[Index] == 0) && (Ip6->Addr[Index + 1] == 0)) {
105 Index = Index + 2;
106 }
107
108 Short = TRUE;
109
110 if (Index == 16) {
111 //
112 // :: is at the end of the address.
113 //
114 *Str = L'\0';
115 break;
116 }
117 }
118
119 ASSERT (Index < 15);
120
121 if (Ip6->Addr[Index] == 0) {
122 Number = UnicodeSPrint (Str, 2 * IP_STR_MAX_SIZE, L"%x:", (UINTN) Ip6->Addr[Index + 1]);
123 } else {
124 if (Ip6->Addr[Index + 1] < 0x10) {
125 CopyMem (FormatString, L"%x0%x:", StrSize (L"%x0%x:"));
126 } else {
127 CopyMem (FormatString, L"%x%x:", StrSize (L"%x%x:"));
128 }
129
130 Number = UnicodeSPrint (
131 Str,
132 2 * IP_STR_MAX_SIZE,
133 (CONST CHAR16 *) FormatString,
134 (UINTN) Ip6->Addr[Index],
135 (UINTN) Ip6->Addr[Index + 1]
136 );
137 }
138
139 Str = Str + Number;
140
141 if (Index + 2 == 16) {
142 *Str = L'\0';
143 if (*(Str - 1) == L':') {
144 *(Str - 1) = L'\0';
145 }
146 }
147 }
148 }
149
150 /**
151 Check whether the input IP address is valid.
152
153 @param[in] Ip The IP address.
154 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.
155
156 @retval TRUE The input IP address is valid.
157 @retval FALSE Otherwise
158
159 **/
160 BOOLEAN
161 IpIsUnicast (
162 IN EFI_IP_ADDRESS *Ip,
163 IN UINT8 IpMode
164 )
165 {
166 if (IpMode == IP_MODE_IP4) {
167 if (IP4_IS_UNSPECIFIED (NTOHL (Ip->Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip->Addr[0]))) {
168 return FALSE;
169 }
170 return TRUE;
171 } else if (IpMode == IP_MODE_IP6) {
172 return NetIp6IsValidUnicast (&Ip->v6);
173 } else {
174 DEBUG ((DEBUG_ERROR, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode));
175 return FALSE;
176 }
177 }
178
179 /**
180 Parse IsId in string format and convert it to binary.
181
182 @param[in] String The buffer of the string to be parsed.
183 @param[in, out] IsId The buffer to store IsId.
184
185 @retval EFI_SUCCESS The operation finished successfully.
186 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
187
188 **/
189 EFI_STATUS
190 IScsiParseIsIdFromString (
191 IN CONST CHAR16 *String,
192 IN OUT UINT8 *IsId
193 )
194 {
195 UINT8 Index;
196 CHAR16 *IsIdStr;
197 CHAR16 TempStr[3];
198 UINTN NodeVal;
199 CHAR16 PortString[ISCSI_NAME_IFR_MAX_SIZE];
200 EFI_INPUT_KEY Key;
201
202 if ((String == NULL) || (IsId == NULL)) {
203 return EFI_INVALID_PARAMETER;
204 }
205
206 IsIdStr = (CHAR16 *) String;
207
208 if (StrLen (IsIdStr) != 6) {
209 UnicodeSPrint (
210 PortString,
211 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
212 L"Error! Input is incorrect, please input 6 hex numbers!\n"
213 );
214
215 CreatePopUp (
216 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
217 &Key,
218 PortString,
219 NULL
220 );
221
222 return EFI_INVALID_PARAMETER;
223 }
224
225 for (Index = 3; Index < 6; Index++) {
226 CopyMem (TempStr, IsIdStr, sizeof (TempStr));
227 TempStr[2] = L'\0';
228
229 //
230 // Convert the string to IsId. StrHexToUintn stops at the first character
231 // that is not a valid hex character, '\0' here.
232 //
233 NodeVal = StrHexToUintn (TempStr);
234
235 IsId[Index] = (UINT8) NodeVal;
236
237 IsIdStr = IsIdStr + 2;
238 }
239
240 return EFI_SUCCESS;
241 }
242
243 /**
244 Convert IsId from binary to string format.
245
246 @param[out] String The buffer to store the converted string.
247 @param[in] IsId The buffer to store IsId.
248
249 @retval EFI_SUCCESS The string converted successfully.
250 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
251
252 **/
253 EFI_STATUS
254 IScsiConvertIsIdToString (
255 OUT CHAR16 *String,
256 IN UINT8 *IsId
257 )
258 {
259 UINT8 Index;
260 UINTN Number;
261
262 if ((String == NULL) || (IsId == NULL)) {
263 return EFI_INVALID_PARAMETER;
264 }
265
266 for (Index = 0; Index < 6; Index++) {
267 if (IsId[Index] <= 0xF) {
268 Number = UnicodeSPrint (
269 String,
270 2 * ISID_CONFIGURABLE_STORAGE,
271 L"0%X",
272 (UINTN) IsId[Index]
273 );
274 } else {
275 Number = UnicodeSPrint (
276 String,
277 2 * ISID_CONFIGURABLE_STORAGE,
278 L"%X",
279 (UINTN) IsId[Index]
280 );
281
282 }
283
284 String = String + Number;
285 }
286
287 *String = L'\0';
288
289 return EFI_SUCCESS;
290 }
291
292 /**
293 Get the attempt config data from global structure by the ConfigIndex.
294
295 @param[in] AttemptConfigIndex The unique index indicates the attempt.
296
297 @return Pointer to the attempt config data.
298 @retval NULL The attempt configuration data cannot be found.
299
300 **/
301 ISCSI_ATTEMPT_CONFIG_NVDATA *
302 IScsiConfigGetAttemptByConfigIndex (
303 IN UINT8 AttemptConfigIndex
304 )
305 {
306 LIST_ENTRY *Entry;
307 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;
308
309 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
310 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
311 if (Attempt->AttemptConfigIndex == AttemptConfigIndex) {
312 return Attempt;
313 }
314 }
315
316 return NULL;
317 }
318
319
320 /**
321 Get the existing attempt config data from global structure by the NicIndex.
322
323 @param[in] NewAttempt The created new attempt
324 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
325 Enabled for MPIO.
326
327 @return Pointer to the existing attempt config data which
328 has the same NICIndex as the new created attempt.
329 @retval NULL The attempt with NicIndex does not exist.
330
331 **/
332 ISCSI_ATTEMPT_CONFIG_NVDATA *
333 IScsiConfigGetAttemptByNic (
334 IN ISCSI_ATTEMPT_CONFIG_NVDATA *NewAttempt,
335 IN UINT8 IScsiMode
336 )
337 {
338 LIST_ENTRY *Entry;
339 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;
340
341 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
342 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
343 if (Attempt != NewAttempt && Attempt->NicIndex == NewAttempt->NicIndex &&
344 Attempt->SessionConfigData.Enabled == IScsiMode) {
345 return Attempt;
346 }
347 }
348
349 return NULL;
350 }
351
352
353 /**
354 Convert the iSCSI configuration data into the IFR data.
355
356 @param[in] Attempt The iSCSI attempt config data.
357 @param[in, out] IfrNvData The IFR nv data.
358
359 **/
360 VOID
361 IScsiConvertAttemptConfigDataToIfrNvData (
362 IN ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt,
363 IN OUT ISCSI_CONFIG_IFR_NVDATA *IfrNvData
364 )
365 {
366 ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData;
367 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;
368 EFI_IP_ADDRESS Ip;
369 BOOLEAN DnsMode;
370
371 //
372 // Normal session configuration parameters.
373 //
374 SessionConfigData = &Attempt->SessionConfigData;
375 IfrNvData->Enabled = SessionConfigData->Enabled;
376 IfrNvData->IpMode = SessionConfigData->IpMode;
377 DnsMode = SessionConfigData->DnsMode;
378
379 IfrNvData->InitiatorInfoFromDhcp = SessionConfigData->InitiatorInfoFromDhcp;
380 IfrNvData->TargetInfoFromDhcp = SessionConfigData->TargetInfoFromDhcp;
381 IfrNvData->TargetPort = SessionConfigData->TargetPort;
382
383 if (IfrNvData->IpMode == IP_MODE_IP4) {
384 CopyMem (&Ip.v4, &SessionConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));
385 IScsiIpToStr (&Ip, FALSE, IfrNvData->LocalIp);
386 CopyMem (&Ip.v4, &SessionConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
387 IScsiIpToStr (&Ip, FALSE, IfrNvData->SubnetMask);
388 CopyMem (&Ip.v4, &SessionConfigData->Gateway, sizeof (EFI_IPv4_ADDRESS));
389 IScsiIpToStr (&Ip, FALSE, IfrNvData->Gateway);
390 if (SessionConfigData->TargetIp.v4.Addr[0] != '\0') {
391 CopyMem (&Ip.v4, &SessionConfigData->TargetIp, sizeof (EFI_IPv4_ADDRESS));
392 IScsiIpToStr (&Ip, FALSE, IfrNvData->TargetIp);
393 }
394
395 } else if (IfrNvData->IpMode == IP_MODE_IP6) {
396 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));
397 if (SessionConfigData->TargetIp.v6.Addr[0] != '\0') {
398 IP6_COPY_ADDRESS (&Ip.v6, &SessionConfigData->TargetIp);
399 IScsiIpToStr (&Ip, TRUE, IfrNvData->TargetIp);
400 }
401 }
402
403 AsciiStrToUnicodeStrS (
404 SessionConfigData->TargetName,
405 IfrNvData->TargetName,
406 sizeof (IfrNvData->TargetName) / sizeof (IfrNvData->TargetName[0])
407 );
408
409 if (DnsMode) {
410 AsciiStrToUnicodeStrS (
411 SessionConfigData->TargetUrl,
412 IfrNvData->TargetIp,
413 sizeof (IfrNvData->TargetIp) / sizeof (IfrNvData->TargetIp[0])
414 );
415 }
416
417 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->BootLun);
418 IScsiConvertIsIdToString (IfrNvData->IsId, SessionConfigData->IsId);
419
420 IfrNvData->ConnectRetryCount = SessionConfigData->ConnectRetryCount;
421 IfrNvData->ConnectTimeout = SessionConfigData->ConnectTimeout;
422
423 //
424 // Authentication parameters.
425 //
426 IfrNvData->AuthenticationType = Attempt->AuthenticationType;
427
428 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
429 AuthConfigData = &Attempt->AuthConfigData.CHAP;
430 IfrNvData->CHAPType = AuthConfigData->CHAPType;
431 AsciiStrToUnicodeStrS (
432 AuthConfigData->CHAPName,
433 IfrNvData->CHAPName,
434 sizeof (IfrNvData->CHAPName) / sizeof (IfrNvData->CHAPName[0])
435 );
436 AsciiStrToUnicodeStrS (
437 AuthConfigData->CHAPSecret,
438 IfrNvData->CHAPSecret,
439 sizeof (IfrNvData->CHAPSecret) / sizeof (IfrNvData->CHAPSecret[0])
440 );
441 AsciiStrToUnicodeStrS (
442 AuthConfigData->ReverseCHAPName,
443 IfrNvData->ReverseCHAPName,
444 sizeof (IfrNvData->ReverseCHAPName) / sizeof (IfrNvData->ReverseCHAPName[0])
445 );
446 AsciiStrToUnicodeStrS (
447 AuthConfigData->ReverseCHAPSecret,
448 IfrNvData->ReverseCHAPSecret,
449 sizeof (IfrNvData->ReverseCHAPSecret) / sizeof (IfrNvData->ReverseCHAPSecret[0])
450 );
451 }
452
453 //
454 // Other parameters.
455 //
456 AsciiStrToUnicodeStrS (
457 Attempt->AttemptName,
458 IfrNvData->AttemptName,
459 sizeof (IfrNvData->AttemptName) / sizeof (IfrNvData->AttemptName[0])
460 );
461 }
462
463 /**
464 Convert the IFR data to iSCSI configuration data.
465
466 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
467 @param[in, out] Attempt The iSCSI attempt config data.
468
469 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
470 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
471 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
472 @retval EFI_ABORTED The operation is aborted.
473 @retval EFI_SUCCESS The operation is completed successfully.
474
475 **/
476 EFI_STATUS
477 IScsiConvertIfrNvDataToAttemptConfigData (
478 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData,
479 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt
480 )
481 {
482 EFI_IP_ADDRESS HostIp;
483 EFI_IP_ADDRESS SubnetMask;
484 EFI_IP_ADDRESS Gateway;
485 CHAR16 *MacString;
486 CHAR16 *AttemptName1;
487 CHAR16 *AttemptName2;
488 ISCSI_ATTEMPT_CONFIG_NVDATA *ExistAttempt;
489 ISCSI_ATTEMPT_CONFIG_NVDATA *SameNicAttempt;
490 CHAR16 IScsiMode[64];
491 CHAR16 IpMode[64];
492 ISCSI_NIC_INFO *NicInfo;
493 EFI_INPUT_KEY Key;
494 UINT8 *AttemptConfigOrder;
495 UINTN AttemptConfigOrderSize;
496 UINT8 *AttemptOrderTmp;
497 UINTN TotalNumber;
498 EFI_STATUS Status;
499
500 if (IfrNvData == NULL || Attempt == NULL) {
501 return EFI_INVALID_PARAMETER;
502 }
503
504 //
505 // Update those fields which don't have INTERACTIVE attribute.
506 //
507 Attempt->SessionConfigData.ConnectRetryCount = IfrNvData->ConnectRetryCount;
508 Attempt->SessionConfigData.ConnectTimeout = IfrNvData->ConnectTimeout;
509 Attempt->SessionConfigData.IpMode = IfrNvData->IpMode;
510
511 if (IfrNvData->IpMode < IP_MODE_AUTOCONFIG) {
512 Attempt->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp;
513 Attempt->SessionConfigData.TargetPort = IfrNvData->TargetPort;
514
515 if (Attempt->SessionConfigData.TargetPort == 0) {
516 Attempt->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;
517 }
518
519 Attempt->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp;
520 }
521
522 Attempt->AuthenticationType = IfrNvData->AuthenticationType;
523
524 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
525 Attempt->AuthConfigData.CHAP.CHAPType = IfrNvData->CHAPType;
526 }
527
528 //
529 // Only do full parameter validation if iSCSI is enabled on this device.
530 //
531 if (IfrNvData->Enabled != ISCSI_DISABLED) {
532 if (Attempt->SessionConfigData.ConnectTimeout < CONNECT_MIN_TIMEOUT) {
533 CreatePopUp (
534 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
535 &Key,
536 L"Connection Establishing Timeout is less than minimum value 100ms.",
537 NULL
538 );
539
540 return EFI_INVALID_PARAMETER;
541 }
542
543 //
544 // Validate the address configuration of the Initiator if DHCP isn't
545 // deployed.
546 //
547 if (!Attempt->SessionConfigData.InitiatorInfoFromDhcp) {
548 CopyMem (&HostIp.v4, &Attempt->SessionConfigData.LocalIp, sizeof (HostIp.v4));
549 CopyMem (&SubnetMask.v4, &Attempt->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));
550 CopyMem (&Gateway.v4, &Attempt->SessionConfigData.Gateway, sizeof (Gateway.v4));
551
552 if ((Gateway.Addr[0] != 0)) {
553 if (SubnetMask.Addr[0] == 0) {
554 CreatePopUp (
555 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
556 &Key,
557 L"Gateway address is set but subnet mask is zero.",
558 NULL
559 );
560
561 return EFI_INVALID_PARAMETER;
562 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {
563 CreatePopUp (
564 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
565 &Key,
566 L"Local IP and Gateway are not in the same subnet.",
567 NULL
568 );
569
570 return EFI_INVALID_PARAMETER;
571 }
572 }
573 }
574 //
575 // Validate target configuration if DHCP isn't deployed.
576 //
577 if (!Attempt->SessionConfigData.TargetInfoFromDhcp && Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) {
578 if (!Attempt->SessionConfigData.DnsMode) {
579 if (!IpIsUnicast (&Attempt->SessionConfigData.TargetIp, IfrNvData->IpMode)) {
580 CreatePopUp (
581 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
582 &Key,
583 L"Target IP is invalid!",
584 NULL
585 );
586 return EFI_INVALID_PARAMETER;
587 }
588 } else {
589 if (Attempt->SessionConfigData.TargetUrl[0] == '\0') {
590 CreatePopUp (
591 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
592 &Key,
593 L"iSCSI target Url should not be NULL!",
594 NULL
595 );
596 return EFI_INVALID_PARAMETER;
597 }
598 }
599
600 //
601 // Validate iSCSI target name configuration again:
602 // The format of iSCSI target name is already verified in IScsiFormCallback() when
603 // user input the name; here we only check the case user does not input the name.
604 //
605 if (Attempt->SessionConfigData.TargetName[0] == '\0') {
606 CreatePopUp (
607 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
608 &Key,
609 L"iSCSI target name is NULL!",
610 NULL
611 );
612 return EFI_INVALID_PARAMETER;
613 }
614 }
615
616
617 //
618 // Validate the authentication info.
619 //
620 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
621 if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) {
622 CreatePopUp (
623 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
624 &Key,
625 L"CHAP Name or CHAP Secret is invalid!",
626 NULL
627 );
628
629 return EFI_INVALID_PARAMETER;
630 }
631
632 if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) &&
633 ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0'))
634 ) {
635 CreatePopUp (
636 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
637 &Key,
638 L"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
639 NULL
640 );
641 return EFI_INVALID_PARAMETER;
642 }
643 }
644
645 //
646 // Check whether this attempt uses NIC which is already used by existing attempt.
647 //
648 SameNicAttempt = IScsiConfigGetAttemptByNic (Attempt, IfrNvData->Enabled);
649 if (SameNicAttempt != NULL) {
650 AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE * sizeof (CHAR16));
651 if (AttemptName1 == NULL) {
652 return EFI_OUT_OF_RESOURCES;
653 }
654
655 AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE * sizeof (CHAR16));
656 if (AttemptName2 == NULL) {
657 FreePool (AttemptName1);
658 return EFI_OUT_OF_RESOURCES;
659 }
660
661 AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_MAX_SIZE);
662 if (StrLen (AttemptName1) > ATTEMPT_NAME_SIZE) {
663 CopyMem (&AttemptName1[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16));
664 }
665
666 AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_MAX_SIZE);
667 if (StrLen (AttemptName2) > ATTEMPT_NAME_SIZE) {
668 CopyMem (&AttemptName2[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16));
669 }
670
671 UnicodeSPrint (
672 mPrivate->PortString,
673 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
674 L"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
675 AttemptName1,
676 AttemptName2
677 );
678
679 CreatePopUp (
680 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
681 &Key,
682 mPrivate->PortString,
683 NULL
684 );
685
686 FreePool (AttemptName1);
687 FreePool (AttemptName2);
688 }
689 }
690
691 //
692 // Update the iSCSI Mode data and record it in attempt help info.
693 //
694 Attempt->SessionConfigData.Enabled = IfrNvData->Enabled;
695 if (IfrNvData->Enabled == ISCSI_DISABLED) {
696 UnicodeSPrint (IScsiMode, 64, L"Disabled");
697 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {
698 UnicodeSPrint (IScsiMode, 64, L"Enabled");
699 } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {
700 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");
701 }
702
703 if (IfrNvData->IpMode == IP_MODE_IP4) {
704 UnicodeSPrint (IpMode, 64, L"IP4");
705 } else if (IfrNvData->IpMode == IP_MODE_IP6) {
706 UnicodeSPrint (IpMode, 64, L"IP6");
707 } else if (IfrNvData->IpMode == IP_MODE_AUTOCONFIG) {
708 UnicodeSPrint (IpMode, 64, L"Autoconfigure");
709 }
710
711 NicInfo = IScsiGetNicInfoByIndex (Attempt->NicIndex);
712 if (NicInfo == NULL) {
713 return EFI_NOT_FOUND;
714 }
715
716 MacString = (CHAR16 *) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN * sizeof (CHAR16));
717 if (MacString == NULL) {
718 return EFI_OUT_OF_RESOURCES;
719 }
720
721 AsciiStrToUnicodeStrS (Attempt->MacString, MacString, ISCSI_MAX_MAC_STRING_LEN);
722
723 UnicodeSPrint (
724 mPrivate->PortString,
725 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
726 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
727 MacString,
728 NicInfo->BusNumber,
729 NicInfo->DeviceNumber,
730 NicInfo->FunctionNumber,
731 IScsiMode,
732 IpMode
733 );
734
735 Attempt->AttemptTitleHelpToken = HiiSetString (
736 mCallbackInfo->RegisteredHandle,
737 Attempt->AttemptTitleHelpToken,
738 mPrivate->PortString,
739 NULL
740 );
741 if (Attempt->AttemptTitleHelpToken == 0) {
742 FreePool (MacString);
743 return EFI_OUT_OF_RESOURCES;
744 }
745
746 //
747 // Check whether this attempt is an existing one.
748 //
749 ExistAttempt = IScsiConfigGetAttemptByConfigIndex (Attempt->AttemptConfigIndex);
750 if (ExistAttempt != NULL) {
751 ASSERT (ExistAttempt == Attempt);
752
753 if (IfrNvData->Enabled == ISCSI_DISABLED &&
754 Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
755
756 //
757 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
758 //
759 if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
760 if (mPrivate->MpioCount < 1) {
761 return EFI_ABORTED;
762 }
763
764 if (--mPrivate->MpioCount == 0) {
765 mPrivate->EnableMpio = FALSE;
766 }
767 } else if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {
768 if (mPrivate->SinglePathCount < 1) {
769 return EFI_ABORTED;
770 }
771 mPrivate->SinglePathCount--;
772 }
773
774 } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO &&
775 Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {
776 //
777 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
778 //
779 if (mPrivate->SinglePathCount < 1) {
780 return EFI_ABORTED;
781 }
782
783 mPrivate->EnableMpio = TRUE;
784 mPrivate->MpioCount++;
785 mPrivate->SinglePathCount--;
786
787 } else if (IfrNvData->Enabled == ISCSI_ENABLED &&
788 Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
789 //
790 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
791 //
792 if (mPrivate->MpioCount < 1) {
793 return EFI_ABORTED;
794 }
795
796 if (--mPrivate->MpioCount == 0) {
797 mPrivate->EnableMpio = FALSE;
798 }
799 mPrivate->SinglePathCount++;
800
801 } else if (IfrNvData->Enabled != ISCSI_DISABLED &&
802 Attempt->SessionConfigData.Enabled == ISCSI_DISABLED) {
803 //
804 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
805 //
806 if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {
807 mPrivate->EnableMpio = TRUE;
808 mPrivate->MpioCount++;
809
810 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {
811 mPrivate->SinglePathCount++;
812 }
813 }
814
815 } else if (ExistAttempt == NULL) {
816 //
817 // When a new attempt is created, pointer of the attempt is saved to
818 // mPrivate->NewAttempt, and also saved to mCallbackInfo->Current in
819 // IScsiConfigProcessDefault. If input Attempt does not match any existing
820 // attempt, it should be a new created attempt. Save it to system now.
821 //
822 ASSERT (Attempt == mPrivate->NewAttempt);
823
824 //
825 // Save current order number for this attempt.
826 //
827 AttemptConfigOrder = IScsiGetVariableAndSize (
828 L"AttemptOrder",
829 &gIScsiConfigGuid,
830 &AttemptConfigOrderSize
831 );
832
833 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);
834 TotalNumber++;
835
836 //
837 // Append the new created attempt order to the end.
838 //
839 AttemptOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));
840 if (AttemptOrderTmp == NULL) {
841 if (AttemptConfigOrder != NULL) {
842 FreePool (AttemptConfigOrder);
843 }
844 return EFI_OUT_OF_RESOURCES;
845 }
846
847 if (AttemptConfigOrder != NULL) {
848 CopyMem (AttemptOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);
849 FreePool (AttemptConfigOrder);
850 }
851
852 AttemptOrderTmp[TotalNumber - 1] = Attempt->AttemptConfigIndex;
853 AttemptConfigOrder = AttemptOrderTmp;
854 AttemptConfigOrderSize = TotalNumber * sizeof (UINT8);
855
856 Status = gRT->SetVariable (
857 L"AttemptOrder",
858 &gIScsiConfigGuid,
859 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
860 AttemptConfigOrderSize,
861 AttemptConfigOrder
862 );
863 FreePool (AttemptConfigOrder);
864 if (EFI_ERROR (Status)) {
865 return Status;
866 }
867
868 //
869 // Insert new created attempt to array.
870 //
871 InsertTailList (&mPrivate->AttemptConfigs, &Attempt->Link);
872 mPrivate->AttemptCount++;
873 //
874 // Reset mPrivate->NewAttempt to NULL, which indicates none attempt is created
875 // but not saved now.
876 //
877 mPrivate->NewAttempt = NULL;
878
879 if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {
880 //
881 // This new Attempt is enabled for MPIO; enable the multipath mode.
882 //
883 mPrivate->EnableMpio = TRUE;
884 mPrivate->MpioCount++;
885 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {
886 mPrivate->SinglePathCount++;
887 }
888
889 IScsiConfigUpdateAttempt ();
890 }
891
892 //
893 // Record the user configuration information in NVR.
894 //
895 UnicodeSPrint (
896 mPrivate->PortString,
897 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
898 L"%s%d",
899 MacString,
900 (UINTN) Attempt->AttemptConfigIndex
901 );
902
903 FreePool (MacString);
904
905 return gRT->SetVariable (
906 mPrivate->PortString,
907 &gEfiIScsiInitiatorNameProtocolGuid,
908 ISCSI_CONFIG_VAR_ATTR,
909 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
910 Attempt
911 );
912 }
913
914 /**
915 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
916 a help function.
917
918 @param[in] StartLabelNumber The number of start label.
919 @param[out] StartOpCodeHandle Points to the start opcode handle.
920 @param[out] StartLabel Points to the created start opcode.
921 @param[out] EndOpCodeHandle Points to the end opcode handle.
922 @param[out] EndLabel Points to the created end opcode.
923
924 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
925 operation.
926 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
927 @retval EFI_SUCCESS The operation is completed successfully.
928
929 **/
930 EFI_STATUS
931 IScsiCreateOpCode (
932 IN UINT16 StartLabelNumber,
933 OUT VOID **StartOpCodeHandle,
934 OUT EFI_IFR_GUID_LABEL **StartLabel,
935 OUT VOID **EndOpCodeHandle,
936 OUT EFI_IFR_GUID_LABEL **EndLabel
937 )
938 {
939 EFI_STATUS Status;
940 EFI_IFR_GUID_LABEL *InternalStartLabel;
941 EFI_IFR_GUID_LABEL *InternalEndLabel;
942
943 if (StartOpCodeHandle == NULL || StartLabel == NULL || EndOpCodeHandle == NULL || EndLabel == NULL) {
944 return EFI_INVALID_PARAMETER;
945 }
946
947 *StartOpCodeHandle = NULL;
948 *EndOpCodeHandle = NULL;
949 Status = EFI_OUT_OF_RESOURCES;
950
951 //
952 // Initialize the container for dynamic opcodes.
953 //
954 *StartOpCodeHandle = HiiAllocateOpCodeHandle ();
955 if (*StartOpCodeHandle == NULL) {
956 return Status;
957 }
958
959 *EndOpCodeHandle = HiiAllocateOpCodeHandle ();
960 if (*EndOpCodeHandle == NULL) {
961 goto Exit;
962 }
963
964 //
965 // Create Hii Extend Label OpCode as the start opcode.
966 //
967 InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
968 *StartOpCodeHandle,
969 &gEfiIfrTianoGuid,
970 NULL,
971 sizeof (EFI_IFR_GUID_LABEL)
972 );
973 if (InternalStartLabel == NULL) {
974 goto Exit;
975 }
976
977 InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
978 InternalStartLabel->Number = StartLabelNumber;
979
980 //
981 // Create Hii Extend Label OpCode as the end opcode.
982 //
983 InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
984 *EndOpCodeHandle,
985 &gEfiIfrTianoGuid,
986 NULL,
987 sizeof (EFI_IFR_GUID_LABEL)
988 );
989 if (InternalEndLabel == NULL) {
990 goto Exit;
991 }
992
993 InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
994 InternalEndLabel->Number = LABEL_END;
995
996 *StartLabel = InternalStartLabel;
997 *EndLabel = InternalEndLabel;
998
999 return EFI_SUCCESS;
1000
1001 Exit:
1002
1003 if (*StartOpCodeHandle != NULL) {
1004 HiiFreeOpCodeHandle (*StartOpCodeHandle);
1005 }
1006
1007 if (*EndOpCodeHandle != NULL) {
1008 HiiFreeOpCodeHandle (*EndOpCodeHandle);
1009 }
1010
1011 return Status;
1012 }
1013
1014 /**
1015 Callback function when user presses "Add an Attempt".
1016
1017 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1018 operation.
1019 @retval EFI_SUCCESS The operation is completed successfully.
1020
1021 **/
1022 EFI_STATUS
1023 IScsiConfigAddAttempt (
1024 VOID
1025 )
1026 {
1027 LIST_ENTRY *Entry;
1028 ISCSI_NIC_INFO *NicInfo;
1029 EFI_STRING_ID PortTitleToken;
1030 EFI_STRING_ID PortTitleHelpToken;
1031 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
1032 EFI_STATUS Status;
1033 VOID *StartOpCodeHandle;
1034 EFI_IFR_GUID_LABEL *StartLabel;
1035 VOID *EndOpCodeHandle;
1036 EFI_IFR_GUID_LABEL *EndLabel;
1037
1038 Status = IScsiCreateOpCode (
1039 MAC_ENTRY_LABEL,
1040 &StartOpCodeHandle,
1041 &StartLabel,
1042 &EndOpCodeHandle,
1043 &EndLabel
1044 );
1045 if (EFI_ERROR (Status)) {
1046 return Status;
1047 }
1048
1049 //
1050 // Ask user to select a MAC for this attempt.
1051 //
1052 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
1053 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
1054 IScsiMacAddrToStr (
1055 &NicInfo->PermanentAddress,
1056 NicInfo->HwAddressSize,
1057 NicInfo->VlanId,
1058 MacString
1059 );
1060
1061 UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"MAC %s", MacString);
1062 PortTitleToken = HiiSetString (
1063 mCallbackInfo->RegisteredHandle,
1064 0,
1065 mPrivate->PortString,
1066 NULL
1067 );
1068 if (PortTitleToken == 0) {
1069 Status = EFI_INVALID_PARAMETER;
1070 goto Exit;
1071 }
1072
1073 UnicodeSPrint (
1074 mPrivate->PortString,
1075 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
1076 L"PFA: Bus %d | Dev %d | Func %d",
1077 NicInfo->BusNumber,
1078 NicInfo->DeviceNumber,
1079 NicInfo->FunctionNumber
1080 );
1081 PortTitleHelpToken = HiiSetString (mCallbackInfo->RegisteredHandle, 0, mPrivate->PortString, NULL);
1082 if (PortTitleHelpToken == 0) {
1083 Status = EFI_INVALID_PARAMETER;
1084 goto Exit;
1085 }
1086
1087 HiiCreateGotoOpCode (
1088 StartOpCodeHandle, // Container for dynamic created opcodes
1089 FORMID_ATTEMPT_FORM,
1090 PortTitleToken,
1091 PortTitleHelpToken,
1092 EFI_IFR_FLAG_CALLBACK, // Question flag
1093 (UINT16) (KEY_MAC_ENTRY_BASE + NicInfo->NicIndex)
1094 );
1095 }
1096
1097 Status = HiiUpdateForm (
1098 mCallbackInfo->RegisteredHandle, // HII handle
1099 &gIScsiConfigGuid, // Formset GUID
1100 FORMID_MAC_FORM, // Form ID
1101 StartOpCodeHandle, // Label for where to insert opcodes
1102 EndOpCodeHandle // Replace data
1103 );
1104
1105 Exit:
1106 HiiFreeOpCodeHandle (StartOpCodeHandle);
1107 HiiFreeOpCodeHandle (EndOpCodeHandle);
1108
1109 return Status;
1110 }
1111
1112
1113 /**
1114 Update the MAIN form to display the configured attempts.
1115
1116 **/
1117 VOID
1118 IScsiConfigUpdateAttempt (
1119 VOID
1120 )
1121 {
1122 CHAR16 AttemptName[ATTEMPT_NAME_MAX_SIZE];
1123 LIST_ENTRY *Entry;
1124 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
1125 VOID *StartOpCodeHandle;
1126 EFI_IFR_GUID_LABEL *StartLabel;
1127 VOID *EndOpCodeHandle;
1128 EFI_IFR_GUID_LABEL *EndLabel;
1129 EFI_STATUS Status;
1130
1131 Status = IScsiCreateOpCode (
1132 ATTEMPT_ENTRY_LABEL,
1133 &StartOpCodeHandle,
1134 &StartLabel,
1135 &EndOpCodeHandle,
1136 &EndLabel
1137 );
1138 if (EFI_ERROR (Status)) {
1139 return ;
1140 }
1141
1142 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
1143 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
1144
1145 AsciiStrToUnicodeStrS (AttemptConfigData->AttemptName, AttemptName, ARRAY_SIZE (AttemptName));
1146 UnicodeSPrint (mPrivate->PortString, (UINTN) 128, L"Attempt %s", AttemptName);
1147 AttemptConfigData->AttemptTitleToken = HiiSetString (
1148 mCallbackInfo->RegisteredHandle,
1149 0,
1150 mPrivate->PortString,
1151 NULL
1152 );
1153 if (AttemptConfigData->AttemptTitleToken == 0) {
1154 return ;
1155 }
1156
1157 HiiCreateGotoOpCode (
1158 StartOpCodeHandle, // Container for dynamic created opcodes
1159 FORMID_ATTEMPT_FORM, // Form ID
1160 AttemptConfigData->AttemptTitleToken, // Prompt text
1161 AttemptConfigData->AttemptTitleHelpToken, // Help text
1162 EFI_IFR_FLAG_CALLBACK, // Question flag
1163 (UINT16) (KEY_ATTEMPT_ENTRY_BASE + AttemptConfigData->AttemptConfigIndex) // Question ID
1164 );
1165 }
1166
1167 HiiUpdateForm (
1168 mCallbackInfo->RegisteredHandle, // HII handle
1169 &gIScsiConfigGuid, // Formset GUID
1170 FORMID_MAIN_FORM, // Form ID
1171 StartOpCodeHandle, // Label for where to insert opcodes
1172 EndOpCodeHandle // Replace data
1173 );
1174
1175 HiiFreeOpCodeHandle (StartOpCodeHandle);
1176 HiiFreeOpCodeHandle (EndOpCodeHandle);
1177 }
1178
1179
1180 /**
1181 Callback function when user presses "Commit Changes and Exit" in Delete Attempts.
1182
1183 @param[in] IfrNvData The IFR NV data.
1184
1185 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1186 @retval EFI_SUCCESS The operation is completed successfully.
1187 @retval EFI_ABOTRED This operation is aborted cause of error
1188 configuration.
1189 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
1190 resources.
1191
1192 **/
1193 EFI_STATUS
1194 IScsiConfigDeleteAttempts (
1195 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData
1196 )
1197 {
1198 EFI_STATUS Status;
1199 UINTN Index;
1200 UINTN NewIndex;
1201 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
1202 UINT8 *AttemptConfigOrder;
1203 UINTN AttemptConfigOrderSize;
1204 UINT8 *AttemptNewOrder;
1205 UINT32 Attribute;
1206 UINTN Total;
1207 UINTN NewTotal;
1208 LIST_ENTRY *Entry;
1209 LIST_ENTRY *NextEntry;
1210 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
1211
1212 AttemptConfigOrder = IScsiGetVariableAndSize (
1213 L"AttemptOrder",
1214 &gIScsiConfigGuid,
1215 &AttemptConfigOrderSize
1216 );
1217 if ((AttemptConfigOrder == NULL) || (AttemptConfigOrderSize == 0)) {
1218 return EFI_NOT_FOUND;
1219 }
1220
1221 AttemptNewOrder = AllocateZeroPool (AttemptConfigOrderSize);
1222 if (AttemptNewOrder == NULL) {
1223 Status = EFI_OUT_OF_RESOURCES;
1224 goto Error;
1225 }
1226
1227 Total = AttemptConfigOrderSize / sizeof (UINT8);
1228 NewTotal = Total;
1229 Index = 0;
1230
1231 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
1232 if (IfrNvData->DeleteAttemptList[Index] == 0) {
1233 Index++;
1234 continue;
1235 }
1236
1237 //
1238 // Delete the attempt.
1239 //
1240
1241 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
1242 if (AttemptConfigData == NULL) {
1243 Status = EFI_NOT_FOUND;
1244 goto Error;
1245 }
1246
1247 //
1248 // Remove this attempt from UI configured attempt list.
1249 //
1250 RemoveEntryList (&AttemptConfigData->Link);
1251 mPrivate->AttemptCount--;
1252
1253 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
1254 if (mPrivate->MpioCount < 1) {
1255 Status = EFI_ABORTED;
1256 goto Error;
1257 }
1258
1259 //
1260 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
1261 //
1262 if (--mPrivate->MpioCount == 0) {
1263 mPrivate->EnableMpio = FALSE;
1264 }
1265 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
1266 if (mPrivate->SinglePathCount < 1) {
1267 Status = EFI_ABORTED;
1268 goto Error;
1269 }
1270
1271 mPrivate->SinglePathCount--;
1272 }
1273
1274 AsciiStrToUnicodeStrS (AttemptConfigData->MacString, MacString, ARRAY_SIZE (MacString));
1275
1276 UnicodeSPrint (
1277 mPrivate->PortString,
1278 (UINTN) 128,
1279 L"%s%d",
1280 MacString,
1281 (UINTN) AttemptConfigData->AttemptConfigIndex
1282 );
1283
1284 gRT->SetVariable (
1285 mPrivate->PortString,
1286 &gEfiIScsiInitiatorNameProtocolGuid,
1287 0,
1288 0,
1289 NULL
1290 );
1291
1292 //
1293 // Mark the attempt order in NVR to be deleted - 0.
1294 //
1295 for (NewIndex = 0; NewIndex < Total; NewIndex++) {
1296 if (AttemptConfigOrder[NewIndex] == AttemptConfigData->AttemptConfigIndex) {
1297 AttemptConfigOrder[NewIndex] = 0;
1298 break;
1299 }
1300 }
1301
1302 NewTotal--;
1303 FreePool (AttemptConfigData);
1304
1305 //
1306 // Check next Attempt.
1307 //
1308 Index++;
1309 }
1310
1311 //
1312 // Construct AttemptNewOrder.
1313 //
1314 for (Index = 0, NewIndex = 0; Index < Total; Index++) {
1315 if (AttemptConfigOrder[Index] != 0) {
1316 AttemptNewOrder[NewIndex] = AttemptConfigOrder[Index];
1317 NewIndex++;
1318 }
1319 }
1320
1321 Attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE;
1322
1323 //
1324 // Update AttemptOrder in NVR.
1325 //
1326 Status = gRT->SetVariable (
1327 L"AttemptOrder",
1328 &gIScsiConfigGuid,
1329 Attribute,
1330 NewTotal * sizeof (UINT8),
1331 AttemptNewOrder
1332 );
1333
1334 Error:
1335 if (AttemptConfigOrder != NULL) {
1336 FreePool (AttemptConfigOrder);
1337 }
1338
1339 if (AttemptNewOrder != NULL) {
1340 FreePool (AttemptNewOrder);
1341 }
1342
1343 return Status;
1344 }
1345
1346
1347 /**
1348 Callback function when user presses "Delete Attempts".
1349
1350 @param[in] IfrNvData The IFR nv data.
1351
1352 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1353 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
1354 @retval EFI_SUCCESS The operation is completed successfully.
1355
1356 **/
1357 EFI_STATUS
1358 IScsiConfigDisplayDeleteAttempts (
1359 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData
1360 )
1361 {
1362
1363 UINT8 *AttemptConfigOrder;
1364 UINTN AttemptConfigOrderSize;
1365 LIST_ENTRY *Entry;
1366 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
1367 UINT8 Index;
1368 VOID *StartOpCodeHandle;
1369 EFI_IFR_GUID_LABEL *StartLabel;
1370 VOID *EndOpCodeHandle;
1371 EFI_IFR_GUID_LABEL *EndLabel;
1372 EFI_STATUS Status;
1373
1374 Status = IScsiCreateOpCode (
1375 DELETE_ENTRY_LABEL,
1376 &StartOpCodeHandle,
1377 &StartLabel,
1378 &EndOpCodeHandle,
1379 &EndLabel
1380 );
1381 if (EFI_ERROR (Status)) {
1382 return Status;
1383 }
1384
1385 AttemptConfigOrder = IScsiGetVariableAndSize (
1386 L"AttemptOrder",
1387 &gIScsiConfigGuid,
1388 &AttemptConfigOrderSize
1389 );
1390 if (AttemptConfigOrder != NULL) {
1391 //
1392 // Create the check box opcode to be deleted.
1393 //
1394 Index = 0;
1395
1396 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
1397 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
1398 IfrNvData->DeleteAttemptList[Index] = 0x00;
1399
1400 HiiCreateCheckBoxOpCode(
1401 StartOpCodeHandle,
1402 (EFI_QUESTION_ID) (ATTEMPT_DEL_QUESTION_ID + Index),
1403 CONFIGURATION_VARSTORE_ID,
1404 (UINT16) (ATTEMPT_DEL_VAR_OFFSET + Index),
1405 AttemptConfigData->AttemptTitleToken,
1406 AttemptConfigData->AttemptTitleHelpToken,
1407 0,
1408 0,
1409 NULL
1410 );
1411
1412 Index++;
1413
1414 if (Index == ISCSI_MAX_ATTEMPTS_NUM) {
1415 break;
1416 }
1417 }
1418
1419 FreePool (AttemptConfigOrder);
1420 }
1421
1422 Status = HiiUpdateForm (
1423 mCallbackInfo->RegisteredHandle, // HII handle
1424 &gIScsiConfigGuid, // Formset GUID
1425 FORMID_DELETE_FORM, // Form ID
1426 StartOpCodeHandle, // Label for where to insert opcodes
1427 EndOpCodeHandle // Replace data
1428 );
1429
1430 HiiFreeOpCodeHandle (StartOpCodeHandle);
1431 HiiFreeOpCodeHandle (EndOpCodeHandle);
1432
1433 return Status;
1434 }
1435
1436
1437 /**
1438 Callback function when user presses "Change Attempt Order".
1439
1440 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
1441 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1442 operation.
1443 @retval EFI_SUCCESS The operation is completed successfully.
1444
1445 **/
1446 EFI_STATUS
1447 IScsiConfigDisplayOrderAttempts (
1448 VOID
1449 )
1450 {
1451 EFI_STATUS Status;
1452 UINT8 Index;
1453 LIST_ENTRY *Entry;
1454 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
1455 VOID *StartOpCodeHandle;
1456 EFI_IFR_GUID_LABEL *StartLabel;
1457 VOID *EndOpCodeHandle;
1458 EFI_IFR_GUID_LABEL *EndLabel;
1459 VOID *OptionsOpCodeHandle;
1460
1461 Status = IScsiCreateOpCode (
1462 ORDER_ENTRY_LABEL,
1463 &StartOpCodeHandle,
1464 &StartLabel,
1465 &EndOpCodeHandle,
1466 &EndLabel
1467 );
1468 if (EFI_ERROR (Status)) {
1469 return Status;
1470 }
1471 ASSERT (StartOpCodeHandle != NULL);
1472
1473 OptionsOpCodeHandle = NULL;
1474
1475 //
1476 // If no attempt to be ordered, update the original form and exit.
1477 //
1478 if (mPrivate->AttemptCount == 0) {
1479 goto Exit;
1480 }
1481
1482 //
1483 // Create Option OpCode.
1484 //
1485 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
1486 if (OptionsOpCodeHandle == NULL) {
1487 Status = EFI_OUT_OF_RESOURCES;
1488 goto Error;
1489 }
1490
1491 Index = 0;
1492
1493 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
1494 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
1495 HiiCreateOneOfOptionOpCode (
1496 OptionsOpCodeHandle,
1497 AttemptConfigData->AttemptTitleToken,
1498 0,
1499 EFI_IFR_NUMERIC_SIZE_1,
1500 AttemptConfigData->AttemptConfigIndex
1501 );
1502 Index++;
1503 }
1504
1505 ASSERT (Index == mPrivate->AttemptCount);
1506
1507 HiiCreateOrderedListOpCode (
1508 StartOpCodeHandle, // Container for dynamic created opcodes
1509 DYNAMIC_ORDERED_LIST_QUESTION_ID, // Question ID
1510 CONFIGURATION_VARSTORE_ID, // VarStore ID
1511 DYNAMIC_ORDERED_LIST_VAR_OFFSET, // Offset in Buffer Storage
1512 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY), // Question prompt text
1513 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY), // Question help text
1514 0, // Question flag
1515 EFI_IFR_UNIQUE_SET, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1516 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question value
1517 ISCSI_MAX_ATTEMPTS_NUM, // Maximum container
1518 OptionsOpCodeHandle, // Option Opcode list
1519 NULL // Default Opcode is NULL
1520 );
1521
1522 Exit:
1523 Status = HiiUpdateForm (
1524 mCallbackInfo->RegisteredHandle, // HII handle
1525 &gIScsiConfigGuid, // Formset GUID
1526 FORMID_ORDER_FORM, // Form ID
1527 StartOpCodeHandle, // Label for where to insert opcodes
1528 EndOpCodeHandle // Replace data
1529 );
1530
1531 Error:
1532 HiiFreeOpCodeHandle (StartOpCodeHandle);
1533 HiiFreeOpCodeHandle (EndOpCodeHandle);
1534 if (OptionsOpCodeHandle != NULL) {
1535 HiiFreeOpCodeHandle (OptionsOpCodeHandle);
1536 }
1537
1538 return Status;
1539 }
1540
1541
1542 /**
1543 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order.
1544
1545 @param[in] IfrNvData The IFR nv data.
1546
1547 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1548 operation.
1549 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1550 @retval EFI_SUCCESS The operation is completed successfully.
1551
1552 **/
1553 EFI_STATUS
1554 IScsiConfigOrderAttempts (
1555 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData
1556 )
1557 {
1558 EFI_STATUS Status;
1559 UINTN Index;
1560 UINTN Indexj;
1561 UINT8 AttemptConfigIndex;
1562 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
1563 UINT8 *AttemptConfigOrder;
1564 UINT8 *AttemptConfigOrderTmp;
1565 UINTN AttemptConfigOrderSize;
1566
1567 AttemptConfigOrder = IScsiGetVariableAndSize (
1568 L"AttemptOrder",
1569 &gIScsiConfigGuid,
1570 &AttemptConfigOrderSize
1571 );
1572 if (AttemptConfigOrder == NULL) {
1573 return EFI_NOT_FOUND;
1574 }
1575
1576 AttemptConfigOrderTmp = AllocateZeroPool (AttemptConfigOrderSize);
1577 if (AttemptConfigOrderTmp == NULL) {
1578 Status = EFI_OUT_OF_RESOURCES;
1579 goto Exit;
1580 }
1581
1582 for (Index = 0; Index < ISCSI_MAX_ATTEMPTS_NUM; Index++) {
1583 //
1584 // The real content ends with 0.
1585 //
1586 if (IfrNvData->DynamicOrderedList[Index] == 0) {
1587 break;
1588 }
1589
1590 AttemptConfigIndex = IfrNvData->DynamicOrderedList[Index];
1591 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex);
1592 if (AttemptConfigData == NULL) {
1593 Status = EFI_NOT_FOUND;
1594 goto Exit;
1595 }
1596
1597 //
1598 // Reorder the Attempt List.
1599 //
1600 RemoveEntryList (&AttemptConfigData->Link);
1601 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
1602
1603 AttemptConfigOrderTmp[Index] = AttemptConfigIndex;
1604
1605 //
1606 // Mark it to be deleted - 0.
1607 //
1608 for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) {
1609 if (AttemptConfigOrder[Indexj] == AttemptConfigIndex) {
1610 AttemptConfigOrder[Indexj] = 0;
1611 break;
1612 }
1613 }
1614 }
1615
1616 //
1617 // Adjust the attempt order in NVR.
1618 //
1619 for (; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1620 for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) {
1621 if (AttemptConfigOrder[Indexj] != 0) {
1622 AttemptConfigOrderTmp[Index] = AttemptConfigOrder[Indexj];
1623 AttemptConfigOrder[Indexj] = 0;
1624 continue;
1625 }
1626 }
1627 }
1628
1629 Status = gRT->SetVariable (
1630 L"AttemptOrder",
1631 &gIScsiConfigGuid,
1632 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
1633 AttemptConfigOrderSize,
1634 AttemptConfigOrderTmp
1635 );
1636
1637 Exit:
1638 if (AttemptConfigOrderTmp != NULL) {
1639 FreePool (AttemptConfigOrderTmp);
1640 }
1641
1642 FreePool (AttemptConfigOrder);
1643 return Status;
1644 }
1645
1646
1647 /**
1648 Callback function when a user presses "Attempt *" or when a user selects a NIC to
1649 create the new attempt.
1650
1651 @param[in] KeyValue A unique value which is sent to the original
1652 exporting driver so that it can identify the type
1653 of data to expect.
1654 @param[in] IfrNvData The IFR nv data.
1655
1656 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1657 operation.
1658 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
1659 @retval EFI_SUCCESS The operation is completed successfully.
1660
1661 **/
1662 EFI_STATUS
1663 IScsiConfigProcessDefault (
1664 IN EFI_QUESTION_ID KeyValue,
1665 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData
1666 )
1667 {
1668 BOOLEAN NewAttempt;
1669 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
1670 ISCSI_SESSION_CONFIG_NVDATA *ConfigData;
1671 UINT8 CurrentAttemptConfigIndex;
1672 ISCSI_NIC_INFO *NicInfo;
1673 UINT8 NicIndex;
1674 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
1675 UINT8 *AttemptConfigOrder;
1676 UINTN AttemptConfigOrderSize;
1677 UINTN TotalNumber;
1678 UINTN Index;
1679
1680 //
1681 // Is User creating a new attempt?
1682 //
1683 NewAttempt = FALSE;
1684
1685 if ((KeyValue >= KEY_MAC_ENTRY_BASE) &&
1686 (KeyValue <= (UINT16) (mPrivate->MaxNic + KEY_MAC_ENTRY_BASE))) {
1687 //
1688 // User has pressed "Add an Attempt" and then selects a NIC.
1689 //
1690 NewAttempt = TRUE;
1691 } else if ((KeyValue >= KEY_ATTEMPT_ENTRY_BASE) &&
1692 (KeyValue < (ISCSI_MAX_ATTEMPTS_NUM + KEY_ATTEMPT_ENTRY_BASE))) {
1693
1694 //
1695 // User has pressed "Attempt *".
1696 //
1697 NewAttempt = FALSE;
1698 } else {
1699 //
1700 // Don't process anything.
1701 //
1702 return EFI_SUCCESS;
1703 }
1704
1705 //
1706 // Free any attempt that is previously created but not saved to system.
1707 //
1708 if (mPrivate->NewAttempt != NULL) {
1709 FreePool (mPrivate->NewAttempt);
1710 mPrivate->NewAttempt = NULL;
1711 }
1712
1713 if (NewAttempt) {
1714 //
1715 // Determine which NIC user has selected for the new created attempt.
1716 //
1717 NicIndex = (UINT8) (KeyValue - KEY_MAC_ENTRY_BASE);
1718 NicInfo = IScsiGetNicInfoByIndex (NicIndex);
1719 if (NicInfo == NULL) {
1720 return EFI_NOT_FOUND;
1721 }
1722
1723 //
1724 // Create new attempt.
1725 //
1726
1727 AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA));
1728 if (AttemptConfigData == NULL) {
1729 return EFI_OUT_OF_RESOURCES;
1730 }
1731
1732 ConfigData = &AttemptConfigData->SessionConfigData;
1733 ConfigData->TargetPort = ISCSI_WELL_KNOWN_PORT;
1734 ConfigData->ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;
1735 ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY;
1736
1737 AttemptConfigData->AuthenticationType = ISCSI_AUTH_TYPE_CHAP;
1738 AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI;
1739
1740 //
1741 // Get current order number for this attempt.
1742 //
1743 AttemptConfigOrder = IScsiGetVariableAndSize (
1744 L"AttemptOrder",
1745 &gIScsiConfigGuid,
1746 &AttemptConfigOrderSize
1747 );
1748
1749 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);
1750
1751 if (AttemptConfigOrder == NULL) {
1752 CurrentAttemptConfigIndex = 1;
1753 } else {
1754 //
1755 // Get the max attempt config index.
1756 //
1757 CurrentAttemptConfigIndex = AttemptConfigOrder[0];
1758 for (Index = 1; Index < TotalNumber; Index++) {
1759 if (CurrentAttemptConfigIndex < AttemptConfigOrder[Index]) {
1760 CurrentAttemptConfigIndex = AttemptConfigOrder[Index];
1761 }
1762 }
1763
1764 CurrentAttemptConfigIndex++;
1765 }
1766
1767 TotalNumber++;
1768
1769 //
1770 // Record the mapping between attempt order and attempt's configdata.
1771 //
1772 AttemptConfigData->AttemptConfigIndex = CurrentAttemptConfigIndex;
1773
1774 if (AttemptConfigOrder != NULL) {
1775 FreePool (AttemptConfigOrder);
1776 }
1777
1778 //
1779 // Record the MAC info in Config Data.
1780 //
1781 IScsiMacAddrToStr (
1782 &NicInfo->PermanentAddress,
1783 NicInfo->HwAddressSize,
1784 NicInfo->VlanId,
1785 MacString
1786 );
1787
1788 UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, sizeof (AttemptConfigData->MacString));
1789 AttemptConfigData->NicIndex = NicIndex;
1790
1791 //
1792 // Generate OUI-format ISID based on MAC address.
1793 //
1794 CopyMem (AttemptConfigData->SessionConfigData.IsId, &NicInfo->PermanentAddress, 6);
1795 AttemptConfigData->SessionConfigData.IsId[0] =
1796 (UINT8) (AttemptConfigData->SessionConfigData.IsId[0] & 0x3F);
1797
1798 //
1799 // Add the help info for the new attempt.
1800 //
1801 UnicodeSPrint (
1802 mPrivate->PortString,
1803 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
1804 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
1805 MacString,
1806 NicInfo->BusNumber,
1807 NicInfo->DeviceNumber,
1808 NicInfo->FunctionNumber
1809 );
1810
1811 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (
1812 mCallbackInfo->RegisteredHandle,
1813 0,
1814 mPrivate->PortString,
1815 NULL
1816 );
1817 if (AttemptConfigData->AttemptTitleHelpToken == 0) {
1818 FreePool (AttemptConfigData);
1819 return EFI_INVALID_PARAMETER;
1820 }
1821
1822 //
1823 // Set the attempt name to default.
1824 //
1825 UnicodeSPrint (
1826 mPrivate->PortString,
1827 (UINTN) 128,
1828 L"%d",
1829 (UINTN) AttemptConfigData->AttemptConfigIndex
1830 );
1831 UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, sizeof (AttemptConfigData->AttemptName));
1832
1833 //
1834 // Save the created Attempt temporarily. If user does not save the attempt
1835 // by press 'KEY_SAVE_ATTEMPT_CONFIG' later, iSCSI driver would know that
1836 // and free resources.
1837 //
1838 mPrivate->NewAttempt = (VOID *) AttemptConfigData;
1839
1840 } else {
1841 //
1842 // Determine which Attempt user has selected to configure.
1843 // Get the attempt configuration data.
1844 //
1845 CurrentAttemptConfigIndex = (UINT8) (KeyValue - KEY_ATTEMPT_ENTRY_BASE);
1846
1847 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex);
1848 if (AttemptConfigData == NULL) {
1849 DEBUG ((DEBUG_ERROR, "Corresponding configuration data can not be retrieved!\n"));
1850 return EFI_NOT_FOUND;
1851 }
1852 }
1853
1854 //
1855 // Clear the old IFR data to avoid sharing it with other attempts.
1856 //
1857 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
1858 ZeroMem (IfrNvData->CHAPName, sizeof (IfrNvData->CHAPName));
1859 ZeroMem (IfrNvData->CHAPSecret, sizeof (IfrNvData->CHAPSecret));
1860 ZeroMem (IfrNvData->ReverseCHAPName, sizeof (IfrNvData->ReverseCHAPName));
1861 ZeroMem (IfrNvData->ReverseCHAPSecret, sizeof (IfrNvData->ReverseCHAPSecret));
1862 }
1863
1864 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData, IfrNvData);
1865
1866 //
1867 // Update current attempt to be a new created attempt or an existing attempt.
1868 //
1869 mCallbackInfo->Current = AttemptConfigData;
1870
1871 return EFI_SUCCESS;
1872 }
1873
1874
1875 /**
1876
1877 This function allows the caller to request the current
1878 configuration for one or more named elements. The resulting
1879 string is in <ConfigAltResp> format. Also, any and all alternative
1880 configuration strings shall be appended to the end of the
1881 current configuration string. If they are, they must appear
1882 after the current configuration. They must contain the same
1883 routing (GUID, NAME, PATH) as the current configuration string.
1884 They must have an additional description indicating the type of
1885 alternative configuration the string represents,
1886 "ALTCFG=<StringToken>". That <StringToken> (when
1887 converted from Hex UNICODE to binary) is a reference to a
1888 string in the associated string pack.
1889
1890 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1891
1892 @param[in] Request A null-terminated Unicode string in
1893 <ConfigRequest> format. Note that this
1894 includes the routing information as well as
1895 the configurable name / value pairs. It is
1896 invalid for this string to be in
1897 <MultiConfigRequest> format.
1898
1899 @param[out] Progress On return, points to a character in the
1900 Request string. Points to the string's null
1901 terminator if request was successful. Points
1902 to the most recent "&" before the first
1903 failing name / value pair (or the beginning
1904 of the string if the failure is in the first
1905 name / value pair) if the request was not successful.
1906
1907 @param[out] Results A null-terminated Unicode string in
1908 <ConfigAltResp> format which has all values
1909 filled in for the names in the Request string.
1910 String to be allocated by the called function.
1911
1912 @retval EFI_SUCCESS The Results string is filled with the
1913 values corresponding to all requested
1914 names.
1915
1916 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1917 parts of the results that must be
1918 stored awaiting possible future
1919 protocols.
1920
1921 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
1922 for the Request parameter
1923 would result in this type of
1924 error. In this case, the
1925 Progress parameter would be
1926 set to NULL.
1927
1928 @retval EFI_NOT_FOUND Routing data doesn't match any
1929 known driver. Progress set to the
1930 first character in the routing header.
1931 Note: There is no requirement that the
1932 driver validate the routing data. It
1933 must skip the <ConfigHdr> in order to
1934 process the names.
1935
1936 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
1937 to most recent "&" before the
1938 error or the beginning of the
1939 string.
1940
1941 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
1942 to the & before the name in
1943 question.
1944
1945 **/
1946 EFI_STATUS
1947 EFIAPI
1948 IScsiFormExtractConfig (
1949 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1950 IN CONST EFI_STRING Request,
1951 OUT EFI_STRING *Progress,
1952 OUT EFI_STRING *Results
1953 )
1954 {
1955 EFI_STATUS Status;
1956 CHAR8 *InitiatorName;
1957 UINTN BufferSize;
1958 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
1959 ISCSI_FORM_CALLBACK_INFO *Private;
1960 EFI_STRING ConfigRequestHdr;
1961 EFI_STRING ConfigRequest;
1962 BOOLEAN AllocatedRequest;
1963 UINTN Size;
1964
1965 if (This == NULL || Progress == NULL || Results == NULL) {
1966 return EFI_INVALID_PARAMETER;
1967 }
1968
1969 *Progress = Request;
1970 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gIScsiConfigGuid, mVendorStorageName)) {
1971 return EFI_NOT_FOUND;
1972 }
1973
1974 ConfigRequestHdr = NULL;
1975 ConfigRequest = NULL;
1976 AllocatedRequest = FALSE;
1977 Size = 0;
1978
1979 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
1980 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));
1981 if (IfrNvData == NULL) {
1982 return EFI_OUT_OF_RESOURCES;
1983 }
1984
1985 if (Private->Current != NULL) {
1986 IScsiConvertAttemptConfigDataToIfrNvData (Private->Current, IfrNvData);
1987 }
1988
1989 BufferSize = ISCSI_NAME_MAX_SIZE;
1990 InitiatorName = (CHAR8 *) AllocateZeroPool (BufferSize);
1991 if (InitiatorName == NULL) {
1992 FreePool (IfrNvData);
1993 return EFI_OUT_OF_RESOURCES;
1994 }
1995
1996 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);
1997 if (EFI_ERROR (Status)) {
1998 IfrNvData->InitiatorName[0] = L'\0';
1999 } else {
2000 AsciiStrToUnicodeStrS (
2001 InitiatorName,
2002 IfrNvData->InitiatorName,
2003 sizeof (IfrNvData->InitiatorName) / sizeof (IfrNvData->InitiatorName[0])
2004 );
2005 }
2006
2007 //
2008 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
2009 //
2010 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
2011 ConfigRequest = Request;
2012 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
2013 //
2014 // Request has no request element, construct full request string.
2015 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2016 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2017 //
2018 ConfigRequestHdr = HiiConstructConfigHdr (&gIScsiConfigGuid, mVendorStorageName, Private->DriverHandle);
2019 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
2020 ConfigRequest = AllocateZeroPool (Size);
2021 if (ConfigRequest == NULL) {
2022 FreePool (IfrNvData);
2023 FreePool (InitiatorName);
2024 return EFI_OUT_OF_RESOURCES;
2025 }
2026 AllocatedRequest = TRUE;
2027 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
2028 FreePool (ConfigRequestHdr);
2029 }
2030
2031 Status = gHiiConfigRouting->BlockToConfig (
2032 gHiiConfigRouting,
2033 ConfigRequest,
2034 (UINT8 *) IfrNvData,
2035 BufferSize,
2036 Results,
2037 Progress
2038 );
2039 FreePool (IfrNvData);
2040 FreePool (InitiatorName);
2041
2042 //
2043 // Free the allocated config request string.
2044 //
2045 if (AllocatedRequest) {
2046 FreePool (ConfigRequest);
2047 ConfigRequest = NULL;
2048 }
2049 //
2050 // Set Progress string to the original request string.
2051 //
2052 if (Request == NULL) {
2053 *Progress = NULL;
2054 } else if (StrStr (Request, L"OFFSET") == NULL) {
2055 *Progress = Request + StrLen (Request);
2056 }
2057
2058 return Status;
2059 }
2060
2061
2062 /**
2063
2064 This function applies changes in a driver's configuration.
2065 Input is a Configuration, which has the routing data for this
2066 driver followed by name / value configuration pairs. The driver
2067 must apply those pairs to its configurable storage. If the
2068 driver's configuration is stored in a linear block of data
2069 and the driver's name / value pairs are in <BlockConfig>
2070 format, it may use the ConfigToBlock helper function (above) to
2071 simplify the job.
2072
2073 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2074
2075 @param[in] Configuration A null-terminated Unicode string in
2076 <ConfigString> format.
2077
2078 @param[out] Progress A pointer to a string filled in with the
2079 offset of the most recent '&' before the
2080 first failing name / value pair (or the
2081 beginning of the string if the failure
2082 is in the first name / value pair) or
2083 the terminating NULL if all was
2084 successful.
2085
2086 @retval EFI_SUCCESS The results have been distributed or are
2087 awaiting distribution.
2088
2089 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2090 parts of the results that must be
2091 stored awaiting possible future
2092 protocols.
2093
2094 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
2095 Results parameter would result
2096 in this type of error.
2097
2098 @retval EFI_NOT_FOUND Target for the specified routing data
2099 was not found.
2100
2101 **/
2102 EFI_STATUS
2103 EFIAPI
2104 IScsiFormRouteConfig (
2105 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
2106 IN CONST EFI_STRING Configuration,
2107 OUT EFI_STRING *Progress
2108 )
2109 {
2110 if (This == NULL || Configuration == NULL || Progress == NULL) {
2111 return EFI_INVALID_PARAMETER;
2112 }
2113
2114 //
2115 // Check routing data in <ConfigHdr>.
2116 // Note: if only one Storage is used, then this checking could be skipped.
2117 //
2118 if (!HiiIsConfigHdrMatch (Configuration, &gIScsiConfigGuid, mVendorStorageName)) {
2119 *Progress = Configuration;
2120 return EFI_NOT_FOUND;
2121 }
2122
2123 *Progress = Configuration + StrLen (Configuration);
2124 return EFI_SUCCESS;
2125 }
2126
2127
2128 /**
2129
2130 This function is called to provide results data to the driver.
2131 This data consists of a unique key that is used to identify
2132 which data is either being passed back or being asked for.
2133
2134 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2135 @param[in] Action Specifies the type of action taken by the browser.
2136 @param[in] QuestionId A unique value which is sent to the original
2137 exporting driver so that it can identify the type
2138 of data to expect. The format of the data tends to
2139 vary based on the opcode that generated the callback.
2140 @param[in] Type The type of value for the question.
2141 @param[in, out] Value A pointer to the data being sent to the original
2142 exporting driver.
2143 @param[out] ActionRequest On return, points to the action requested by the
2144 callback function.
2145
2146 @retval EFI_SUCCESS The callback successfully handled the action.
2147 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2148 variable and its data.
2149 @retval EFI_DEVICE_ERROR The variable could not be saved.
2150 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2151 callback.
2152 **/
2153 EFI_STATUS
2154 EFIAPI
2155 IScsiFormCallback (
2156 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
2157 IN EFI_BROWSER_ACTION Action,
2158 IN EFI_QUESTION_ID QuestionId,
2159 IN UINT8 Type,
2160 IN OUT EFI_IFR_TYPE_VALUE *Value,
2161 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
2162 )
2163 {
2164 ISCSI_FORM_CALLBACK_INFO *Private;
2165 UINTN BufferSize;
2166 CHAR8 *IScsiName;
2167 CHAR8 IpString[ISCSI_NAME_MAX_SIZE];
2168 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];
2169 UINT64 Lun;
2170 EFI_IP_ADDRESS HostIp;
2171 EFI_IP_ADDRESS SubnetMask;
2172 EFI_IP_ADDRESS Gateway;
2173 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
2174 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData;
2175 EFI_STATUS Status;
2176 CHAR16 AttemptName[ATTEMPT_NAME_SIZE + 4];
2177 EFI_INPUT_KEY Key;
2178
2179 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
2180 //
2181 // Do nothing for UEFI OPEN/CLOSE Action
2182 //
2183 return EFI_SUCCESS;
2184 }
2185
2186 if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {
2187 //
2188 // All other type return unsupported.
2189 //
2190 return EFI_UNSUPPORTED;
2191 }
2192
2193 if ((Value == NULL) || (ActionRequest == NULL)) {
2194 return EFI_INVALID_PARAMETER;
2195 }
2196
2197 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
2198
2199 //
2200 // Retrieve uncommitted data from Browser
2201 //
2202
2203 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
2204 IfrNvData = AllocateZeroPool (BufferSize);
2205 if (IfrNvData == NULL) {
2206 return EFI_OUT_OF_RESOURCES;
2207 }
2208
2209 IScsiName = (CHAR8 *) AllocateZeroPool (ISCSI_NAME_MAX_SIZE);
2210 if (IScsiName == NULL) {
2211 FreePool (IfrNvData);
2212 return EFI_OUT_OF_RESOURCES;
2213 }
2214
2215 Status = EFI_SUCCESS;
2216
2217 ZeroMem (&OldIfrNvData, BufferSize);
2218
2219 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);
2220
2221 CopyMem (&OldIfrNvData, IfrNvData, BufferSize);
2222
2223 if (Action == EFI_BROWSER_ACTION_CHANGING) {
2224 switch (QuestionId) {
2225 case KEY_ADD_ATTEMPT:
2226 //
2227 // Check whether iSCSI initiator name is configured already.
2228 //
2229 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
2230 Status = gIScsiInitiatorName.Get (
2231 &gIScsiInitiatorName,
2232 &mPrivate->InitiatorNameLength,
2233 mPrivate->InitiatorName
2234 );
2235 if (EFI_ERROR (Status)) {
2236 CreatePopUp (
2237 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2238 &Key,
2239 L"Error: please configure iSCSI initiator name first!",
2240 NULL
2241 );
2242 break;
2243 }
2244
2245 Status = IScsiConfigAddAttempt ();
2246 break;
2247
2248 case KEY_DELETE_ATTEMPT:
2249 CopyMem (
2250 OldIfrNvData.DeleteAttemptList,
2251 IfrNvData->DeleteAttemptList,
2252 sizeof (IfrNvData->DeleteAttemptList)
2253 );
2254 Status = IScsiConfigDisplayDeleteAttempts (IfrNvData);
2255 break;
2256
2257 case KEY_ORDER_ATTEMPT_CONFIG:
2258 //
2259 // Order the attempt according to user input.
2260 //
2261 CopyMem (
2262 OldIfrNvData.DynamicOrderedList,
2263 IfrNvData->DynamicOrderedList,
2264 sizeof (IfrNvData->DynamicOrderedList)
2265 );
2266 IScsiConfigDisplayOrderAttempts ();
2267 break;
2268
2269 default:
2270 Status = IScsiConfigProcessDefault (QuestionId, IfrNvData);
2271 break;
2272 }
2273 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
2274 switch (QuestionId) {
2275 case KEY_INITIATOR_NAME:
2276 UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, IScsiName, ISCSI_NAME_MAX_SIZE);
2277 BufferSize = AsciiStrSize (IScsiName);
2278
2279 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);
2280 if (EFI_ERROR (Status)) {
2281 CreatePopUp (
2282 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2283 &Key,
2284 L"Invalid iSCSI Name!",
2285 NULL
2286 );
2287 }
2288
2289 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
2290 break;
2291 case KEY_ATTEMPT_NAME:
2292 if (StrLen (IfrNvData->AttemptName) > ATTEMPT_NAME_SIZE) {
2293 CopyMem (AttemptName, IfrNvData->AttemptName, ATTEMPT_NAME_SIZE * sizeof (CHAR16));
2294 CopyMem (&AttemptName[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16));
2295 } else {
2296 CopyMem (
2297 AttemptName,
2298 IfrNvData->AttemptName,
2299 (StrLen (IfrNvData->AttemptName) + 1) * sizeof (CHAR16)
2300 );
2301 }
2302
2303 UnicodeStrToAsciiStrS (IfrNvData->AttemptName, Private->Current->AttemptName, sizeof (Private->Current->AttemptName));
2304
2305 IScsiConfigUpdateAttempt ();
2306
2307 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
2308 break;
2309
2310 case KEY_SAVE_ATTEMPT_CONFIG:
2311 Status = IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData, Private->Current);
2312 if (EFI_ERROR (Status)) {
2313 break;
2314 }
2315
2316 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
2317 break;
2318
2319 case KEY_SAVE_ORDER_CHANGES:
2320 //
2321 // Sync the Attempt Order to NVR.
2322 //
2323 Status = IScsiConfigOrderAttempts (IfrNvData);
2324 if (EFI_ERROR (Status)) {
2325 break;
2326 }
2327
2328 IScsiConfigUpdateAttempt ();
2329 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
2330 break;
2331
2332 case KEY_IGNORE_ORDER_CHANGES:
2333 CopyMem (
2334 IfrNvData->DynamicOrderedList,
2335 OldIfrNvData.DynamicOrderedList,
2336 sizeof (IfrNvData->DynamicOrderedList)
2337 );
2338 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
2339 break;
2340
2341 case KEY_SAVE_DELETE_ATTEMPT:
2342 //
2343 // Delete the Attempt Order from NVR
2344 //
2345 Status = IScsiConfigDeleteAttempts (IfrNvData);
2346 if (EFI_ERROR (Status)) {
2347 break;
2348 }
2349
2350 IScsiConfigUpdateAttempt ();
2351 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
2352 break;
2353
2354 case KEY_IGNORE_DELETE_ATTEMPT:
2355 CopyMem (
2356 IfrNvData->DeleteAttemptList,
2357 OldIfrNvData.DeleteAttemptList,
2358 sizeof (IfrNvData->DeleteAttemptList)
2359 );
2360 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
2361 break;
2362
2363 case KEY_IP_MODE:
2364 switch (Value->u8) {
2365 case IP_MODE_IP6:
2366 case IP_MODE_IP4:
2367 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));
2368 Private->Current->AutoConfigureMode = 0;
2369
2370 break;
2371 }
2372
2373 break;
2374
2375 case KEY_LOCAL_IP:
2376 Status = NetLibStrToIp4 (IfrNvData->LocalIp, &HostIp.v4);
2377 if (EFI_ERROR (Status) ||
2378 ((Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) &&
2379 !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), NTOHL(*(UINT32*)Private->Current->SessionConfigData.SubnetMask.Addr)))) {
2380 CreatePopUp (
2381 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2382 &Key,
2383 L"Invalid IP address!",
2384 NULL
2385 );
2386
2387 Status = EFI_INVALID_PARAMETER;
2388 } else {
2389 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
2390 }
2391
2392 break;
2393
2394 case KEY_SUBNET_MASK:
2395 Status = NetLibStrToIp4 (IfrNvData->SubnetMask, &SubnetMask.v4);
2396 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
2397 CreatePopUp (
2398 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2399 &Key,
2400 L"Invalid Subnet Mask!",
2401 NULL
2402 );
2403
2404 Status = EFI_INVALID_PARAMETER;
2405 } else {
2406 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
2407 }
2408
2409 break;
2410
2411 case KEY_GATE_WAY:
2412 Status = NetLibStrToIp4 (IfrNvData->Gateway, &Gateway.v4);
2413 if (EFI_ERROR (Status) ||
2414 ((Gateway.Addr[0] != 0) &&
2415 (Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) &&
2416 !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL(*(UINT32*)Private->Current->SessionConfigData.SubnetMask.Addr)))) {
2417 CreatePopUp (
2418 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2419 &Key,
2420 L"Invalid Gateway!",
2421 NULL
2422 );
2423 Status = EFI_INVALID_PARAMETER;
2424 } else {
2425 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));
2426 }
2427
2428 break;
2429
2430 case KEY_TARGET_IP:
2431 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, IpString, sizeof (IpString));
2432 Status = IScsiAsciiStrToIp (IpString, IfrNvData->IpMode, &HostIp);
2433 if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, IfrNvData->IpMode)) {
2434 //
2435 // The target is expressed in URL format or an invalid Ip address, just save.
2436 //
2437 Private->Current->SessionConfigData.DnsMode = TRUE;
2438 ZeroMem (&Private->Current->SessionConfigData.TargetIp, sizeof (Private->Current->SessionConfigData.TargetIp));
2439 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, Private->Current->SessionConfigData.TargetUrl, ISCSI_NAME_MAX_SIZE);
2440 } else {
2441 Private->Current->SessionConfigData.DnsMode = FALSE;
2442 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp));
2443 }
2444
2445 break;
2446
2447 case KEY_TARGET_NAME:
2448 UnicodeStrToAsciiStrS (IfrNvData->TargetName, IScsiName, ISCSI_NAME_MAX_SIZE);
2449 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));
2450 if (EFI_ERROR (Status)) {
2451 CreatePopUp (
2452 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2453 &Key,
2454 L"Invalid iSCSI Name!",
2455 NULL
2456 );
2457 } else {
2458 AsciiStrCpyS (Private->Current->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName);
2459 }
2460
2461 break;
2462
2463 case KEY_DHCP_ENABLE:
2464 if (IfrNvData->InitiatorInfoFromDhcp == 0) {
2465 IfrNvData->TargetInfoFromDhcp = 0;
2466 }
2467
2468 break;
2469
2470 case KEY_BOOT_LUN:
2471 UnicodeStrToAsciiStrS (IfrNvData->BootLun, LunString, sizeof (LunString));
2472 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);
2473 if (EFI_ERROR (Status)) {
2474 CreatePopUp (
2475 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2476 &Key,
2477 L"Invalid LUN string!",
2478 NULL
2479 );
2480 } else {
2481 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));
2482 }
2483
2484 break;
2485
2486 case KEY_AUTH_TYPE:
2487 switch (Value->u8) {
2488 case ISCSI_AUTH_TYPE_CHAP:
2489 IfrNvData->CHAPType = ISCSI_CHAP_UNI;
2490 break;
2491 default:
2492 break;
2493 }
2494
2495 break;
2496
2497 case KEY_CHAP_NAME:
2498 UnicodeStrToAsciiStrS (
2499 IfrNvData->CHAPName,
2500 Private->Current->AuthConfigData.CHAP.CHAPName,
2501 sizeof (Private->Current->AuthConfigData.CHAP.CHAPName)
2502 );
2503 break;
2504
2505 case KEY_CHAP_SECRET:
2506 UnicodeStrToAsciiStrS (
2507 IfrNvData->CHAPSecret,
2508 Private->Current->AuthConfigData.CHAP.CHAPSecret,
2509 sizeof (Private->Current->AuthConfigData.CHAP.CHAPSecret)
2510 );
2511 break;
2512
2513 case KEY_REVERSE_CHAP_NAME:
2514 UnicodeStrToAsciiStrS (
2515 IfrNvData->ReverseCHAPName,
2516 Private->Current->AuthConfigData.CHAP.ReverseCHAPName,
2517 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPName)
2518 );
2519 break;
2520
2521 case KEY_REVERSE_CHAP_SECRET:
2522 UnicodeStrToAsciiStrS (
2523 IfrNvData->ReverseCHAPSecret,
2524 Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret,
2525 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret)
2526 );
2527 break;
2528
2529 case KEY_CONFIG_ISID:
2530 IScsiParseIsIdFromString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);
2531 IScsiConvertIsIdToString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);
2532
2533 break;
2534
2535 default:
2536 break;
2537 }
2538 }
2539
2540 if (!EFI_ERROR (Status)) {
2541 //
2542 // Pass changed uncommitted data back to Form Browser.
2543 //
2544 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
2545 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);
2546 }
2547
2548 FreePool (IfrNvData);
2549 FreePool (IScsiName);
2550
2551 return Status;
2552 }
2553
2554
2555 /**
2556 Initialize the iSCSI configuration form.
2557
2558 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2559
2560 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
2561 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2562
2563 **/
2564 EFI_STATUS
2565 IScsiConfigFormInit (
2566 IN EFI_HANDLE DriverBindingHandle
2567 )
2568 {
2569 EFI_STATUS Status;
2570 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;
2571
2572 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO));
2573 if (CallbackInfo == NULL) {
2574 return EFI_OUT_OF_RESOURCES;
2575 }
2576
2577 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;
2578 CallbackInfo->Current = NULL;
2579
2580 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;
2581 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;
2582 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;
2583
2584 //
2585 // Install Device Path Protocol and Config Access protocol to driver handle.
2586 //
2587 Status = gBS->InstallMultipleProtocolInterfaces (
2588 &CallbackInfo->DriverHandle,
2589 &gEfiDevicePathProtocolGuid,
2590 &mIScsiHiiVendorDevicePath,
2591 &gEfiHiiConfigAccessProtocolGuid,
2592 &CallbackInfo->ConfigAccess,
2593 NULL
2594 );
2595 ASSERT_EFI_ERROR (Status);
2596
2597 //
2598 // Publish our HII data.
2599 //
2600 CallbackInfo->RegisteredHandle = HiiAddPackages (
2601 &gIScsiConfigGuid,
2602 CallbackInfo->DriverHandle,
2603 IScsiDxeStrings,
2604 IScsiConfigVfrBin,
2605 NULL
2606 );
2607 if (CallbackInfo->RegisteredHandle == NULL) {
2608 gBS->UninstallMultipleProtocolInterfaces (
2609 &CallbackInfo->DriverHandle,
2610 &gEfiDevicePathProtocolGuid,
2611 &mIScsiHiiVendorDevicePath,
2612 &gEfiHiiConfigAccessProtocolGuid,
2613 &CallbackInfo->ConfigAccess,
2614 NULL
2615 );
2616 FreePool(CallbackInfo);
2617 return EFI_OUT_OF_RESOURCES;
2618 }
2619
2620 mCallbackInfo = CallbackInfo;
2621
2622 return EFI_SUCCESS;
2623 }
2624
2625
2626 /**
2627 Unload the iSCSI configuration form, this includes: delete all the iSCSI
2628 configuration entries, uninstall the form callback protocol, and
2629 free the resources used.
2630
2631 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2632
2633 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
2634 @retval Others Failed to unload the form.
2635
2636 **/
2637 EFI_STATUS
2638 IScsiConfigFormUnload (
2639 IN EFI_HANDLE DriverBindingHandle
2640 )
2641 {
2642 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2643 ISCSI_NIC_INFO *NicInfo;
2644 LIST_ENTRY *Entry;
2645 EFI_STATUS Status;
2646
2647 while (!IsListEmpty (&mPrivate->AttemptConfigs)) {
2648 Entry = NetListRemoveHead (&mPrivate->AttemptConfigs);
2649 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
2650 FreePool (AttemptConfigData);
2651 mPrivate->AttemptCount--;
2652 }
2653
2654 ASSERT (mPrivate->AttemptCount == 0);
2655
2656 while (!IsListEmpty (&mPrivate->NicInfoList)) {
2657 Entry = NetListRemoveHead (&mPrivate->NicInfoList);
2658 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
2659 FreePool (NicInfo);
2660 mPrivate->NicCount--;
2661 }
2662
2663 ASSERT (mPrivate->NicCount == 0);
2664
2665 //
2666 // Free attempt is created but not saved to system.
2667 //
2668 if (mPrivate->NewAttempt != NULL) {
2669 FreePool (mPrivate->NewAttempt);
2670 }
2671
2672 FreePool (mPrivate);
2673 mPrivate = NULL;
2674
2675 //
2676 // Remove HII package list.
2677 //
2678 HiiRemovePackages (mCallbackInfo->RegisteredHandle);
2679
2680 //
2681 // Uninstall Device Path Protocol and Config Access protocol.
2682 //
2683 Status = gBS->UninstallMultipleProtocolInterfaces (
2684 mCallbackInfo->DriverHandle,
2685 &gEfiDevicePathProtocolGuid,
2686 &mIScsiHiiVendorDevicePath,
2687 &gEfiHiiConfigAccessProtocolGuid,
2688 &mCallbackInfo->ConfigAccess,
2689 NULL
2690 );
2691
2692 FreePool (mCallbackInfo);
2693
2694 return Status;
2695 }