]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IScsiDxe/IScsiConfig.c
NetworkPkg: Replace UnicodeStrToAsciiStr/AsciiStrToUnicodeStr
[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, sizeof (MacString) / sizeof (MacString[0]));
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 ASSERT (ConfigRequest != NULL);
1991 AllocatedRequest = TRUE;
1992 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
1993 FreePool (ConfigRequestHdr);
1994 }
1995
1996 Status = gHiiConfigRouting->BlockToConfig (
1997 gHiiConfigRouting,
1998 ConfigRequest,
1999 (UINT8 *) IfrNvData,
2000 BufferSize,
2001 Results,
2002 Progress
2003 );
2004 FreePool (IfrNvData);
2005 FreePool (InitiatorName);
2006
2007 //
2008 // Free the allocated config request string.
2009 //
2010 if (AllocatedRequest) {
2011 FreePool (ConfigRequest);
2012 ConfigRequest = NULL;
2013 }
2014 //
2015 // Set Progress string to the original request string.
2016 //
2017 if (Request == NULL) {
2018 *Progress = NULL;
2019 } else if (StrStr (Request, L"OFFSET") == NULL) {
2020 *Progress = Request + StrLen (Request);
2021 }
2022
2023 return Status;
2024 }
2025
2026
2027 /**
2028
2029 This function applies changes in a driver's configuration.
2030 Input is a Configuration, which has the routing data for this
2031 driver followed by name / value configuration pairs. The driver
2032 must apply those pairs to its configurable storage. If the
2033 driver's configuration is stored in a linear block of data
2034 and the driver's name / value pairs are in <BlockConfig>
2035 format, it may use the ConfigToBlock helper function (above) to
2036 simplify the job.
2037
2038 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2039
2040 @param[in] Configuration A null-terminated Unicode string in
2041 <ConfigString> format.
2042
2043 @param[out] Progress A pointer to a string filled in with the
2044 offset of the most recent '&' before the
2045 first failing name / value pair (or the
2046 beginning of the string if the failure
2047 is in the first name / value pair) or
2048 the terminating NULL if all was
2049 successful.
2050
2051 @retval EFI_SUCCESS The results have been distributed or are
2052 awaiting distribution.
2053
2054 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2055 parts of the results that must be
2056 stored awaiting possible future
2057 protocols.
2058
2059 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
2060 Results parameter would result
2061 in this type of error.
2062
2063 @retval EFI_NOT_FOUND Target for the specified routing data
2064 was not found.
2065
2066 **/
2067 EFI_STATUS
2068 EFIAPI
2069 IScsiFormRouteConfig (
2070 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
2071 IN CONST EFI_STRING Configuration,
2072 OUT EFI_STRING *Progress
2073 )
2074 {
2075 if (This == NULL || Configuration == NULL || Progress == NULL) {
2076 return EFI_INVALID_PARAMETER;
2077 }
2078
2079 //
2080 // Check routing data in <ConfigHdr>.
2081 // Note: if only one Storage is used, then this checking could be skipped.
2082 //
2083 if (!HiiIsConfigHdrMatch (Configuration, &gIScsiConfigGuid, mVendorStorageName)) {
2084 *Progress = Configuration;
2085 return EFI_NOT_FOUND;
2086 }
2087
2088 *Progress = Configuration + StrLen (Configuration);
2089 return EFI_SUCCESS;
2090 }
2091
2092
2093 /**
2094
2095 This function is called to provide results data to the driver.
2096 This data consists of a unique key that is used to identify
2097 which data is either being passed back or being asked for.
2098
2099 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2100 @param[in] Action Specifies the type of action taken by the browser.
2101 @param[in] QuestionId A unique value which is sent to the original
2102 exporting driver so that it can identify the type
2103 of data to expect. The format of the data tends to
2104 vary based on the opcode that generated the callback.
2105 @param[in] Type The type of value for the question.
2106 @param[in, out] Value A pointer to the data being sent to the original
2107 exporting driver.
2108 @param[out] ActionRequest On return, points to the action requested by the
2109 callback function.
2110
2111 @retval EFI_SUCCESS The callback successfully handled the action.
2112 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2113 variable and its data.
2114 @retval EFI_DEVICE_ERROR The variable could not be saved.
2115 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2116 callback.
2117 **/
2118 EFI_STATUS
2119 EFIAPI
2120 IScsiFormCallback (
2121 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
2122 IN EFI_BROWSER_ACTION Action,
2123 IN EFI_QUESTION_ID QuestionId,
2124 IN UINT8 Type,
2125 IN OUT EFI_IFR_TYPE_VALUE *Value,
2126 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
2127 )
2128 {
2129 ISCSI_FORM_CALLBACK_INFO *Private;
2130 UINTN BufferSize;
2131 CHAR8 *IScsiName;
2132 CHAR8 IpString[IP_STR_MAX_SIZE];
2133 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];
2134 UINT64 Lun;
2135 EFI_IP_ADDRESS HostIp;
2136 EFI_IP_ADDRESS SubnetMask;
2137 EFI_IP_ADDRESS Gateway;
2138 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
2139 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData;
2140 EFI_STATUS Status;
2141 CHAR16 AttemptName[ATTEMPT_NAME_SIZE + 4];
2142 EFI_INPUT_KEY Key;
2143
2144 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
2145 //
2146 // Do nothing for UEFI OPEN/CLOSE Action
2147 //
2148 return EFI_SUCCESS;
2149 }
2150
2151 if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {
2152 //
2153 // All other type return unsupported.
2154 //
2155 return EFI_UNSUPPORTED;
2156 }
2157
2158 if ((Value == NULL) || (ActionRequest == NULL)) {
2159 return EFI_INVALID_PARAMETER;
2160 }
2161
2162 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
2163
2164 //
2165 // Retrieve uncommitted data from Browser
2166 //
2167
2168 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
2169 IfrNvData = AllocateZeroPool (BufferSize);
2170 if (IfrNvData == NULL) {
2171 return EFI_OUT_OF_RESOURCES;
2172 }
2173
2174 IScsiName = (CHAR8 *) AllocateZeroPool (ISCSI_NAME_MAX_SIZE);
2175 if (IScsiName == NULL) {
2176 FreePool (IfrNvData);
2177 return EFI_OUT_OF_RESOURCES;
2178 }
2179
2180 Status = EFI_SUCCESS;
2181
2182 ZeroMem (&OldIfrNvData, BufferSize);
2183
2184 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);
2185
2186 CopyMem (&OldIfrNvData, IfrNvData, BufferSize);
2187
2188 if (Action == EFI_BROWSER_ACTION_CHANGING) {
2189 switch (QuestionId) {
2190 case KEY_ADD_ATTEMPT:
2191 //
2192 // Check whether iSCSI initiator name is configured already.
2193 //
2194 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
2195 Status = gIScsiInitiatorName.Get (
2196 &gIScsiInitiatorName,
2197 &mPrivate->InitiatorNameLength,
2198 mPrivate->InitiatorName
2199 );
2200 if (EFI_ERROR (Status)) {
2201 CreatePopUp (
2202 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2203 &Key,
2204 L"Error: please configure iSCSI initiator name first!",
2205 NULL
2206 );
2207 break;
2208 }
2209
2210 Status = IScsiConfigAddAttempt ();
2211 break;
2212
2213 case KEY_DELETE_ATTEMPT:
2214 CopyMem (
2215 OldIfrNvData.DeleteAttemptList,
2216 IfrNvData->DeleteAttemptList,
2217 sizeof (IfrNvData->DeleteAttemptList)
2218 );
2219 Status = IScsiConfigDisplayDeleteAttempts (IfrNvData);
2220 break;
2221
2222 case KEY_ORDER_ATTEMPT_CONFIG:
2223 //
2224 // Order the attempt according to user input.
2225 //
2226 CopyMem (
2227 OldIfrNvData.DynamicOrderedList,
2228 IfrNvData->DynamicOrderedList,
2229 sizeof (IfrNvData->DynamicOrderedList)
2230 );
2231 IScsiConfigDisplayOrderAttempts ();
2232 break;
2233
2234 default:
2235 Status = IScsiConfigProcessDefault (QuestionId, IfrNvData);
2236 break;
2237 }
2238 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
2239 switch (QuestionId) {
2240 case KEY_INITIATOR_NAME:
2241 UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, IScsiName, ISCSI_NAME_MAX_SIZE);
2242 BufferSize = AsciiStrSize (IScsiName);
2243
2244 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);
2245 if (EFI_ERROR (Status)) {
2246 CreatePopUp (
2247 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2248 &Key,
2249 L"Invalid iSCSI Name!",
2250 NULL
2251 );
2252 }
2253
2254 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
2255 break;
2256 case KEY_ATTEMPT_NAME:
2257 if (StrLen (IfrNvData->AttemptName) > ATTEMPT_NAME_SIZE) {
2258 CopyMem (AttemptName, IfrNvData->AttemptName, ATTEMPT_NAME_SIZE * sizeof (CHAR16));
2259 CopyMem (&AttemptName[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16));
2260 } else {
2261 CopyMem (
2262 AttemptName,
2263 IfrNvData->AttemptName,
2264 (StrLen (IfrNvData->AttemptName) + 1) * sizeof (CHAR16)
2265 );
2266 }
2267
2268 UnicodeStrToAsciiStrS (IfrNvData->AttemptName, Private->Current->AttemptName, sizeof (Private->Current->AttemptName));
2269
2270 IScsiConfigUpdateAttempt ();
2271
2272 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
2273 break;
2274
2275 case KEY_SAVE_ATTEMPT_CONFIG:
2276 Status = IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData, Private->Current);
2277 if (EFI_ERROR (Status)) {
2278 break;
2279 }
2280
2281 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
2282 break;
2283
2284 case KEY_SAVE_ORDER_CHANGES:
2285 //
2286 // Sync the Attempt Order to NVR.
2287 //
2288 Status = IScsiConfigOrderAttempts (IfrNvData);
2289 if (EFI_ERROR (Status)) {
2290 break;
2291 }
2292
2293 IScsiConfigUpdateAttempt ();
2294 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
2295 break;
2296
2297 case KEY_IGNORE_ORDER_CHANGES:
2298 CopyMem (
2299 IfrNvData->DynamicOrderedList,
2300 OldIfrNvData.DynamicOrderedList,
2301 sizeof (IfrNvData->DynamicOrderedList)
2302 );
2303 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
2304 break;
2305
2306 case KEY_SAVE_DELETE_ATTEMPT:
2307 //
2308 // Delete the Attempt Order from NVR
2309 //
2310 Status = IScsiConfigDeleteAttempts (IfrNvData);
2311 if (EFI_ERROR (Status)) {
2312 break;
2313 }
2314
2315 IScsiConfigUpdateAttempt ();
2316 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
2317 break;
2318
2319 case KEY_IGNORE_DELETE_ATTEMPT:
2320 CopyMem (
2321 IfrNvData->DeleteAttemptList,
2322 OldIfrNvData.DeleteAttemptList,
2323 sizeof (IfrNvData->DeleteAttemptList)
2324 );
2325 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
2326 break;
2327
2328 case KEY_IP_MODE:
2329 switch (Value->u8) {
2330 case IP_MODE_IP6:
2331 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));
2332 IScsiIpToStr (&Private->Current->SessionConfigData.TargetIp, TRUE, IfrNvData->TargetIp);
2333 Private->Current->AutoConfigureMode = 0;
2334 break;
2335
2336 case IP_MODE_IP4:
2337 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));
2338 IScsiIpToStr (&Private->Current->SessionConfigData.TargetIp, FALSE, IfrNvData->TargetIp);
2339 Private->Current->AutoConfigureMode = 0;
2340
2341 break;
2342 }
2343
2344 break;
2345
2346 case KEY_LOCAL_IP:
2347 Status = NetLibStrToIp4 (IfrNvData->LocalIp, &HostIp.v4);
2348 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
2349 CreatePopUp (
2350 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2351 &Key,
2352 L"Invalid IP address!",
2353 NULL
2354 );
2355
2356 Status = EFI_INVALID_PARAMETER;
2357 } else {
2358 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
2359 }
2360
2361 break;
2362
2363 case KEY_SUBNET_MASK:
2364 Status = NetLibStrToIp4 (IfrNvData->SubnetMask, &SubnetMask.v4);
2365 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
2366 CreatePopUp (
2367 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2368 &Key,
2369 L"Invalid Subnet Mask!",
2370 NULL
2371 );
2372
2373 Status = EFI_INVALID_PARAMETER;
2374 } else {
2375 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
2376 }
2377
2378 break;
2379
2380 case KEY_GATE_WAY:
2381 Status = NetLibStrToIp4 (IfrNvData->Gateway, &Gateway.v4);
2382 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {
2383 CreatePopUp (
2384 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2385 &Key,
2386 L"Invalid Gateway!",
2387 NULL
2388 );
2389 Status = EFI_INVALID_PARAMETER;
2390 } else {
2391 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));
2392 }
2393
2394 break;
2395
2396 case KEY_TARGET_IP:
2397 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, IpString, sizeof (IpString));
2398 Status = IScsiAsciiStrToIp (IpString, IfrNvData->IpMode, &HostIp);
2399 if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, IfrNvData->IpMode)) {
2400 CreatePopUp (
2401 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2402 &Key,
2403 L"Invalid IP address!",
2404 NULL
2405 );
2406 Status = EFI_INVALID_PARAMETER;
2407 } else {
2408 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp));
2409 }
2410
2411 break;
2412
2413 case KEY_TARGET_NAME:
2414 UnicodeStrToAsciiStrS (IfrNvData->TargetName, IScsiName, ISCSI_NAME_MAX_SIZE);
2415 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));
2416 if (EFI_ERROR (Status)) {
2417 CreatePopUp (
2418 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2419 &Key,
2420 L"Invalid iSCSI Name!",
2421 NULL
2422 );
2423 } else {
2424 AsciiStrCpyS (Private->Current->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName);
2425 }
2426
2427 break;
2428
2429 case KEY_DHCP_ENABLE:
2430 if (IfrNvData->InitiatorInfoFromDhcp == 0) {
2431 IfrNvData->TargetInfoFromDhcp = 0;
2432 }
2433
2434 break;
2435
2436 case KEY_BOOT_LUN:
2437 UnicodeStrToAsciiStrS (IfrNvData->BootLun, LunString, sizeof (LunString));
2438 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);
2439 if (EFI_ERROR (Status)) {
2440 CreatePopUp (
2441 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2442 &Key,
2443 L"Invalid LUN string!",
2444 NULL
2445 );
2446 } else {
2447 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));
2448 }
2449
2450 break;
2451
2452 case KEY_AUTH_TYPE:
2453 switch (Value->u8) {
2454 case ISCSI_AUTH_TYPE_CHAP:
2455 IfrNvData->CHAPType = ISCSI_CHAP_UNI;
2456 break;
2457 default:
2458 break;
2459 }
2460
2461 break;
2462
2463 case KEY_CHAP_NAME:
2464 UnicodeStrToAsciiStrS (
2465 IfrNvData->CHAPName,
2466 Private->Current->AuthConfigData.CHAP.CHAPName,
2467 sizeof (Private->Current->AuthConfigData.CHAP.CHAPName)
2468 );
2469 break;
2470
2471 case KEY_CHAP_SECRET:
2472 UnicodeStrToAsciiStrS (
2473 IfrNvData->CHAPSecret,
2474 Private->Current->AuthConfigData.CHAP.CHAPSecret,
2475 sizeof (Private->Current->AuthConfigData.CHAP.CHAPSecret)
2476 );
2477 break;
2478
2479 case KEY_REVERSE_CHAP_NAME:
2480 UnicodeStrToAsciiStrS (
2481 IfrNvData->ReverseCHAPName,
2482 Private->Current->AuthConfigData.CHAP.ReverseCHAPName,
2483 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPName)
2484 );
2485 break;
2486
2487 case KEY_REVERSE_CHAP_SECRET:
2488 UnicodeStrToAsciiStrS (
2489 IfrNvData->ReverseCHAPSecret,
2490 Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret,
2491 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret)
2492 );
2493 break;
2494
2495 case KEY_CONFIG_ISID:
2496 IScsiParseIsIdFromString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);
2497 IScsiConvertIsIdToString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);
2498
2499 break;
2500
2501 default:
2502 break;
2503 }
2504 }
2505
2506 if (!EFI_ERROR (Status)) {
2507 //
2508 // Pass changed uncommitted data back to Form Browser.
2509 //
2510 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
2511 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);
2512 }
2513
2514 FreePool (IfrNvData);
2515 FreePool (IScsiName);
2516
2517 return Status;
2518 }
2519
2520
2521 /**
2522 Initialize the iSCSI configuration form.
2523
2524 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2525
2526 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
2527 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2528
2529 **/
2530 EFI_STATUS
2531 IScsiConfigFormInit (
2532 IN EFI_HANDLE DriverBindingHandle
2533 )
2534 {
2535 EFI_STATUS Status;
2536 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;
2537
2538 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO));
2539 if (CallbackInfo == NULL) {
2540 return EFI_OUT_OF_RESOURCES;
2541 }
2542
2543 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;
2544 CallbackInfo->Current = NULL;
2545
2546 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;
2547 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;
2548 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;
2549
2550 //
2551 // Install Device Path Protocol and Config Access protocol to driver handle.
2552 //
2553 Status = gBS->InstallMultipleProtocolInterfaces (
2554 &CallbackInfo->DriverHandle,
2555 &gEfiDevicePathProtocolGuid,
2556 &mIScsiHiiVendorDevicePath,
2557 &gEfiHiiConfigAccessProtocolGuid,
2558 &CallbackInfo->ConfigAccess,
2559 NULL
2560 );
2561 ASSERT_EFI_ERROR (Status);
2562
2563 //
2564 // Publish our HII data.
2565 //
2566 CallbackInfo->RegisteredHandle = HiiAddPackages (
2567 &gIScsiConfigGuid,
2568 CallbackInfo->DriverHandle,
2569 IScsiDxeStrings,
2570 IScsiConfigVfrBin,
2571 NULL
2572 );
2573 if (CallbackInfo->RegisteredHandle == NULL) {
2574 gBS->UninstallMultipleProtocolInterfaces (
2575 &CallbackInfo->DriverHandle,
2576 &gEfiDevicePathProtocolGuid,
2577 &mIScsiHiiVendorDevicePath,
2578 &gEfiHiiConfigAccessProtocolGuid,
2579 &CallbackInfo->ConfigAccess,
2580 NULL
2581 );
2582 FreePool(CallbackInfo);
2583 return EFI_OUT_OF_RESOURCES;
2584 }
2585
2586 mCallbackInfo = CallbackInfo;
2587
2588 return EFI_SUCCESS;
2589 }
2590
2591
2592 /**
2593 Unload the iSCSI configuration form, this includes: delete all the iSCSI
2594 configuration entries, uninstall the form callback protocol, and
2595 free the resources used.
2596
2597 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
2598
2599 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
2600 @retval Others Failed to unload the form.
2601
2602 **/
2603 EFI_STATUS
2604 IScsiConfigFormUnload (
2605 IN EFI_HANDLE DriverBindingHandle
2606 )
2607 {
2608 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2609 ISCSI_NIC_INFO *NicInfo;
2610 LIST_ENTRY *Entry;
2611 EFI_STATUS Status;
2612
2613 while (!IsListEmpty (&mPrivate->AttemptConfigs)) {
2614 Entry = NetListRemoveHead (&mPrivate->AttemptConfigs);
2615 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
2616 FreePool (AttemptConfigData);
2617 mPrivate->AttemptCount--;
2618 }
2619
2620 ASSERT (mPrivate->AttemptCount == 0);
2621
2622 while (!IsListEmpty (&mPrivate->NicInfoList)) {
2623 Entry = NetListRemoveHead (&mPrivate->NicInfoList);
2624 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
2625 FreePool (NicInfo);
2626 mPrivate->NicCount--;
2627 }
2628
2629 ASSERT (mPrivate->NicCount == 0);
2630
2631 //
2632 // Free attempt is created but not saved to system.
2633 //
2634 if (mPrivate->NewAttempt != NULL) {
2635 FreePool (mPrivate->NewAttempt);
2636 }
2637
2638 FreePool (mPrivate);
2639 mPrivate = NULL;
2640
2641 //
2642 // Remove HII package list.
2643 //
2644 HiiRemovePackages (mCallbackInfo->RegisteredHandle);
2645
2646 //
2647 // Uninstall Device Path Protocol and Config Access protocol.
2648 //
2649 Status = gBS->UninstallMultipleProtocolInterfaces (
2650 mCallbackInfo->DriverHandle,
2651 &gEfiDevicePathProtocolGuid,
2652 &mIScsiHiiVendorDevicePath,
2653 &gEfiHiiConfigAccessProtocolGuid,
2654 &mCallbackInfo->ConfigAccess,
2655 NULL
2656 );
2657
2658 FreePool (mCallbackInfo);
2659
2660 return Status;
2661 }