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