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