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