]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - NetworkPkg/IScsiDxe/IScsiConfig.c
OvmfPkg: raise DXEFV size to 13 MB in the traditional platform FDFs
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiConfig.c
... / ...
CommitLineData
1/** @file\r
2 Helper functions for configuring or getting the parameters relating to iSCSI.\r
3\r
4Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>\r
5SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include "IScsiImpl.h"\r
10\r
11CHAR16 mVendorStorageName[] = L"ISCSI_CONFIG_IFR_NVDATA";\r
12ISCSI_FORM_CALLBACK_INFO *mCallbackInfo = NULL;\r
13\r
14HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath = {\r
15 {\r
16 {\r
17 HARDWARE_DEVICE_PATH,\r
18 HW_VENDOR_DP,\r
19 {\r
20 (UINT8)(sizeof (VENDOR_DEVICE_PATH)),\r
21 (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
22 }\r
23 },\r
24 ISCSI_CONFIG_GUID\r
25 },\r
26 {\r
27 END_DEVICE_PATH_TYPE,\r
28 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
29 {\r
30 (UINT8)(END_DEVICE_PATH_LENGTH),\r
31 (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)\r
32 }\r
33 }\r
34};\r
35\r
36/**\r
37 Convert the IP address into a dotted string.\r
38\r
39 @param[in] Ip The IP address.\r
40 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.\r
41 @param[out] Str The formatted IP string.\r
42\r
43**/\r
44VOID\r
45IScsiIpToStr (\r
46 IN EFI_IP_ADDRESS *Ip,\r
47 IN BOOLEAN Ipv6Flag,\r
48 OUT CHAR16 *Str\r
49 )\r
50{\r
51 EFI_IPv4_ADDRESS *Ip4;\r
52 EFI_IPv6_ADDRESS *Ip6;\r
53 UINTN Index;\r
54 BOOLEAN Short;\r
55 UINTN Number;\r
56 CHAR16 FormatString[8];\r
57\r
58 if (!Ipv6Flag) {\r
59 Ip4 = &Ip->v4;\r
60\r
61 UnicodeSPrint (\r
62 Str,\r
63 (UINTN)2 * IP4_STR_MAX_SIZE,\r
64 L"%d.%d.%d.%d",\r
65 (UINTN)Ip4->Addr[0],\r
66 (UINTN)Ip4->Addr[1],\r
67 (UINTN)Ip4->Addr[2],\r
68 (UINTN)Ip4->Addr[3]\r
69 );\r
70\r
71 return;\r
72 }\r
73\r
74 Ip6 = &Ip->v6;\r
75 Short = FALSE;\r
76\r
77 for (Index = 0; Index < 15; Index = Index + 2) {\r
78 if (!Short &&\r
79 (Index % 2 == 0) &&\r
80 (Ip6->Addr[Index] == 0) &&\r
81 (Ip6->Addr[Index + 1] == 0)\r
82 )\r
83 {\r
84 //\r
85 // Deal with the case of ::.\r
86 //\r
87 if (Index == 0) {\r
88 *Str = L':';\r
89 *(Str + 1) = L':';\r
90 Str = Str + 2;\r
91 } else {\r
92 *Str = L':';\r
93 Str = Str + 1;\r
94 }\r
95\r
96 while ((Index < 15) && (Ip6->Addr[Index] == 0) && (Ip6->Addr[Index + 1] == 0)) {\r
97 Index = Index + 2;\r
98 }\r
99\r
100 Short = TRUE;\r
101\r
102 if (Index == 16) {\r
103 //\r
104 // :: is at the end of the address.\r
105 //\r
106 *Str = L'\0';\r
107 break;\r
108 }\r
109 }\r
110\r
111 ASSERT (Index < 15);\r
112\r
113 if (Ip6->Addr[Index] == 0) {\r
114 Number = UnicodeSPrint (Str, 2 * IP_STR_MAX_SIZE, L"%x:", (UINTN)Ip6->Addr[Index + 1]);\r
115 } else {\r
116 if (Ip6->Addr[Index + 1] < 0x10) {\r
117 CopyMem (FormatString, L"%x0%x:", StrSize (L"%x0%x:"));\r
118 } else {\r
119 CopyMem (FormatString, L"%x%x:", StrSize (L"%x%x:"));\r
120 }\r
121\r
122 Number = UnicodeSPrint (\r
123 Str,\r
124 2 * IP_STR_MAX_SIZE,\r
125 (CONST CHAR16 *)FormatString,\r
126 (UINTN)Ip6->Addr[Index],\r
127 (UINTN)Ip6->Addr[Index + 1]\r
128 );\r
129 }\r
130\r
131 Str = Str + Number;\r
132\r
133 if (Index + 2 == 16) {\r
134 *Str = L'\0';\r
135 if (*(Str - 1) == L':') {\r
136 *(Str - 1) = L'\0';\r
137 }\r
138 }\r
139 }\r
140}\r
141\r
142/**\r
143 Check whether the input IP address is valid.\r
144\r
145 @param[in] Ip The IP address.\r
146 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.\r
147\r
148 @retval TRUE The input IP address is valid.\r
149 @retval FALSE Otherwise\r
150\r
151**/\r
152BOOLEAN\r
153IpIsUnicast (\r
154 IN EFI_IP_ADDRESS *Ip,\r
155 IN UINT8 IpMode\r
156 )\r
157{\r
158 if (IpMode == IP_MODE_IP4) {\r
159 if (IP4_IS_UNSPECIFIED (NTOHL (Ip->Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip->Addr[0]))) {\r
160 return FALSE;\r
161 }\r
162\r
163 return TRUE;\r
164 } else if (IpMode == IP_MODE_IP6) {\r
165 return NetIp6IsValidUnicast (&Ip->v6);\r
166 } else {\r
167 DEBUG ((DEBUG_ERROR, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode));\r
168 return FALSE;\r
169 }\r
170}\r
171\r
172/**\r
173 Parse IsId in string format and convert it to binary.\r
174\r
175 @param[in] String The buffer of the string to be parsed.\r
176 @param[in, out] IsId The buffer to store IsId.\r
177\r
178 @retval EFI_SUCCESS The operation finished successfully.\r
179 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
180\r
181**/\r
182EFI_STATUS\r
183IScsiParseIsIdFromString (\r
184 IN CONST CHAR16 *String,\r
185 IN OUT UINT8 *IsId\r
186 )\r
187{\r
188 UINT8 Index;\r
189 CHAR16 *IsIdStr;\r
190 CHAR16 TempStr[3];\r
191 UINTN NodeVal;\r
192 CHAR16 PortString[ISCSI_NAME_IFR_MAX_SIZE];\r
193 EFI_INPUT_KEY Key;\r
194\r
195 if ((String == NULL) || (IsId == NULL)) {\r
196 return EFI_INVALID_PARAMETER;\r
197 }\r
198\r
199 IsIdStr = (CHAR16 *)String;\r
200\r
201 if ((StrLen (IsIdStr) != 6) && (StrLen (IsIdStr) != 12)) {\r
202 UnicodeSPrint (\r
203 PortString,\r
204 (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
205 L"Error! Only last 3 bytes are configurable, please input 6 hex numbers for last 3 bytes only or 12 hex numbers for full SSID!\n"\r
206 );\r
207\r
208 CreatePopUp (\r
209 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
210 &Key,\r
211 PortString,\r
212 NULL\r
213 );\r
214\r
215 return EFI_INVALID_PARAMETER;\r
216 }\r
217\r
218 if (StrLen (IsIdStr) == 12) {\r
219 IsIdStr += 6;\r
220 }\r
221\r
222 for (Index = 3; Index < 6; Index++) {\r
223 CopyMem (TempStr, IsIdStr, sizeof (TempStr));\r
224 TempStr[2] = L'\0';\r
225\r
226 //\r
227 // Convert the string to IsId. StrHexToUintn stops at the first character\r
228 // that is not a valid hex character, '\0' here.\r
229 //\r
230 NodeVal = StrHexToUintn (TempStr);\r
231\r
232 IsId[Index] = (UINT8)NodeVal;\r
233\r
234 IsIdStr = IsIdStr + 2;\r
235 }\r
236\r
237 return EFI_SUCCESS;\r
238}\r
239\r
240/**\r
241 Convert IsId from binary to string format.\r
242\r
243 @param[out] String The buffer to store the converted string.\r
244 @param[in] IsId The buffer to store IsId.\r
245\r
246 @retval EFI_SUCCESS The string converted successfully.\r
247 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
248\r
249**/\r
250EFI_STATUS\r
251IScsiConvertIsIdToString (\r
252 OUT CHAR16 *String,\r
253 IN UINT8 *IsId\r
254 )\r
255{\r
256 UINT8 Index;\r
257 UINTN Number;\r
258\r
259 if ((String == NULL) || (IsId == NULL)) {\r
260 return EFI_INVALID_PARAMETER;\r
261 }\r
262\r
263 for (Index = 0; Index < 6; Index++) {\r
264 if (IsId[Index] <= 0xF) {\r
265 Number = UnicodeSPrint (\r
266 String,\r
267 2 * ISID_CONFIGURABLE_STORAGE,\r
268 L"0%X",\r
269 (UINTN)IsId[Index]\r
270 );\r
271 } else {\r
272 Number = UnicodeSPrint (\r
273 String,\r
274 2 * ISID_CONFIGURABLE_STORAGE,\r
275 L"%X",\r
276 (UINTN)IsId[Index]\r
277 );\r
278 }\r
279\r
280 String = String + Number;\r
281 }\r
282\r
283 *String = L'\0';\r
284\r
285 return EFI_SUCCESS;\r
286}\r
287\r
288/**\r
289 Get the Offset value specified by the input String.\r
290\r
291 @param[in] Configuration A null-terminated Unicode string in\r
292 <ConfigString> format.\r
293 @param[in] String The string is "&OFFSET=".\r
294 @param[out] Value The Offset value.\r
295\r
296 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary\r
297 structures.\r
298 @retval EFI_SUCCESS Value of <Number> is outputted in Number\r
299 successfully.\r
300\r
301**/\r
302EFI_STATUS\r
303IScsiGetValue (\r
304 IN CONST EFI_STRING Configuration,\r
305 IN CHAR16 *String,\r
306 OUT UINTN *Value\r
307 )\r
308{\r
309 CHAR16 *StringPtr;\r
310 CHAR16 *TmpPtr;\r
311 CHAR16 *Str;\r
312 CHAR16 TmpStr[2];\r
313 UINTN Length;\r
314 UINTN Len;\r
315 UINTN Index;\r
316 UINT8 *Buf;\r
317 UINT8 DigitUint8;\r
318 EFI_STATUS Status;\r
319\r
320 //\r
321 // Get Value.\r
322 //\r
323 Buf = NULL;\r
324 StringPtr = StrStr (Configuration, String);\r
325 ASSERT (StringPtr != NULL);\r
326 StringPtr += StrLen (String);\r
327 TmpPtr = StringPtr;\r
328\r
329 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
330 StringPtr++;\r
331 }\r
332\r
333 Length = StringPtr - TmpPtr;\r
334 Len = Length + 1;\r
335\r
336 Str = AllocateZeroPool (Len * sizeof (CHAR16));\r
337 if (Str == NULL) {\r
338 Status = EFI_OUT_OF_RESOURCES;\r
339 goto Exit;\r
340 }\r
341\r
342 CopyMem (Str, TmpPtr, Len * sizeof (CHAR16));\r
343 *(Str + Length) = L'\0';\r
344\r
345 Len = (Len + 1) / 2;\r
346 Buf = (UINT8 *)AllocateZeroPool (Len);\r
347 if (Buf == NULL) {\r
348 Status = EFI_OUT_OF_RESOURCES;\r
349 goto Exit;\r
350 }\r
351\r
352 ZeroMem (TmpStr, sizeof (TmpStr));\r
353 for (Index = 0; Index < Length; Index++) {\r
354 TmpStr[0] = Str[Length - Index - 1];\r
355 DigitUint8 = (UINT8)StrHexToUint64 (TmpStr);\r
356 if ((Index & 1) == 0) {\r
357 Buf[Index/2] = DigitUint8;\r
358 } else {\r
359 Buf[Index/2] = (UINT8)((DigitUint8 << 4) + Buf[Index/2]);\r
360 }\r
361 }\r
362\r
363 *Value = 0;\r
364 CopyMem (\r
365 Value,\r
366 Buf,\r
367 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
368 );\r
369\r
370 FreePool (Buf);\r
371 Status = EFI_SUCCESS;\r
372\r
373Exit:\r
374 if (Str != NULL) {\r
375 FreePool (Str);\r
376 }\r
377\r
378 return Status;\r
379}\r
380\r
381/**\r
382 Get the attempt config data from global structure by the ConfigIndex.\r
383\r
384 @param[in] AttemptConfigIndex The unique index indicates the attempt.\r
385\r
386 @return Pointer to the attempt config data.\r
387 @retval NULL The attempt configuration data cannot be found.\r
388\r
389**/\r
390ISCSI_ATTEMPT_CONFIG_NVDATA *\r
391IScsiConfigGetAttemptByConfigIndex (\r
392 IN UINT8 AttemptConfigIndex\r
393 )\r
394{\r
395 LIST_ENTRY *Entry;\r
396 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;\r
397\r
398 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
399 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
400 if (Attempt->AttemptConfigIndex == AttemptConfigIndex) {\r
401 return Attempt;\r
402 }\r
403 }\r
404\r
405 return NULL;\r
406}\r
407\r
408/**\r
409 Get the existing attempt config data from global structure by the NicIndex.\r
410\r
411 @param[in] NewAttempt The created new attempt\r
412 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or\r
413 Enabled for MPIO.\r
414\r
415 @return Pointer to the existing attempt config data which\r
416 has the same NICIndex as the new created attempt.\r
417 @retval NULL The attempt with NicIndex does not exist.\r
418\r
419**/\r
420ISCSI_ATTEMPT_CONFIG_NVDATA *\r
421IScsiConfigGetAttemptByNic (\r
422 IN ISCSI_ATTEMPT_CONFIG_NVDATA *NewAttempt,\r
423 IN UINT8 IScsiMode\r
424 )\r
425{\r
426 LIST_ENTRY *Entry;\r
427 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;\r
428\r
429 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
430 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
431 if ((Attempt != NewAttempt) && (Attempt->NicIndex == NewAttempt->NicIndex) &&\r
432 (Attempt->SessionConfigData.Enabled == IScsiMode))\r
433 {\r
434 return Attempt;\r
435 }\r
436 }\r
437\r
438 return NULL;\r
439}\r
440\r
441/**\r
442 Extract the Index of the attempt list.\r
443\r
444 @param[in] AttemptNameList The Name list of the Attempts.\r
445 @param[out] AttemptIndexList The Index list of the Attempts.\r
446 @param[in] IsAddAttempts If TRUE, Indicates add one or more attempts.\r
447 If FALSE, Indicates delete attempts or change attempt order.\r
448\r
449 @retval EFI_SUCCESS The Attempt list is valid.\r
450 @retval EFI_INVALID_PARAMETERS The Attempt List is invalid.\r
451\r
452**/\r
453EFI_STATUS\r
454IScsiGetAttemptIndexList (\r
455 IN CHAR16 *AttemptNameList,\r
456 OUT UINT8 *AttemptIndexList,\r
457 IN BOOLEAN IsAddAttempts\r
458 )\r
459{\r
460 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
461 CHAR16 *AttemptStr;\r
462 UINT8 AttemptIndex;\r
463 UINTN Len;\r
464 UINTN Index;\r
465\r
466 Index = 0;\r
467\r
468 if ((AttemptNameList == NULL) || (*AttemptNameList == L'\0')) {\r
469 return EFI_INVALID_PARAMETER;\r
470 }\r
471\r
472 AttemptStr = AttemptNameList;\r
473 Len = StrLen (L"attempt:");\r
474\r
475 while (*AttemptStr != L'\0') {\r
476 AttemptStr = StrStr (AttemptStr, L"attempt:");\r
477 if (AttemptStr == NULL) {\r
478 return EFI_INVALID_PARAMETER;\r
479 }\r
480\r
481 AttemptStr += Len;\r
482 AttemptIndex = (UINT8)(*AttemptStr - L'0');\r
483 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
484 if (IsAddAttempts) {\r
485 if ((AttemptConfigData != NULL) || ((AttemptIndex) > PcdGet8 (PcdMaxIScsiAttemptNumber))) {\r
486 return EFI_INVALID_PARAMETER;\r
487 }\r
488 } else {\r
489 if (AttemptConfigData == NULL) {\r
490 return EFI_INVALID_PARAMETER;\r
491 }\r
492 }\r
493\r
494 AttemptIndexList[Index] = AttemptIndex;\r
495 Index++;\r
496 AttemptStr += 2;\r
497 }\r
498\r
499 return EFI_SUCCESS;\r
500}\r
501\r
502/**\r
503 Convert the iSCSI configuration data into the IFR data.\r
504\r
505 @param[in] Attempt The iSCSI attempt config data.\r
506 @param[in, out] IfrNvData The IFR nv data.\r
507\r
508**/\r
509VOID\r
510IScsiConvertAttemptConfigDataToIfrNvData (\r
511 IN ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt,\r
512 IN OUT ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
513 )\r
514{\r
515 ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData;\r
516 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;\r
517 EFI_IP_ADDRESS Ip;\r
518 BOOLEAN DnsMode;\r
519\r
520 //\r
521 // Normal session configuration parameters.\r
522 //\r
523 SessionConfigData = &Attempt->SessionConfigData;\r
524 IfrNvData->Enabled = SessionConfigData->Enabled;\r
525 IfrNvData->IpMode = SessionConfigData->IpMode;\r
526 DnsMode = SessionConfigData->DnsMode;\r
527\r
528 IfrNvData->InitiatorInfoFromDhcp = SessionConfigData->InitiatorInfoFromDhcp;\r
529 IfrNvData->TargetInfoFromDhcp = SessionConfigData->TargetInfoFromDhcp;\r
530 IfrNvData->TargetPort = SessionConfigData->TargetPort;\r
531\r
532 if (IfrNvData->IpMode == IP_MODE_IP4) {\r
533 CopyMem (&Ip.v4, &SessionConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));\r
534 IScsiIpToStr (&Ip, FALSE, IfrNvData->LocalIp);\r
535 CopyMem (&Ip.v4, &SessionConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
536 IScsiIpToStr (&Ip, FALSE, IfrNvData->SubnetMask);\r
537 CopyMem (&Ip.v4, &SessionConfigData->Gateway, sizeof (EFI_IPv4_ADDRESS));\r
538 IScsiIpToStr (&Ip, FALSE, IfrNvData->Gateway);\r
539 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));\r
540 if (SessionConfigData->TargetIp.v4.Addr[0] != '\0') {\r
541 CopyMem (&Ip.v4, &SessionConfigData->TargetIp, sizeof (EFI_IPv4_ADDRESS));\r
542 IScsiIpToStr (&Ip, FALSE, IfrNvData->TargetIp);\r
543 }\r
544 } else if (IfrNvData->IpMode == IP_MODE_IP6) {\r
545 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));\r
546 if (SessionConfigData->TargetIp.v6.Addr[0] != '\0') {\r
547 IP6_COPY_ADDRESS (&Ip.v6, &SessionConfigData->TargetIp);\r
548 IScsiIpToStr (&Ip, TRUE, IfrNvData->TargetIp);\r
549 }\r
550 }\r
551\r
552 AsciiStrToUnicodeStrS (\r
553 SessionConfigData->TargetName,\r
554 IfrNvData->TargetName,\r
555 sizeof (IfrNvData->TargetName) / sizeof (IfrNvData->TargetName[0])\r
556 );\r
557\r
558 if (DnsMode) {\r
559 AsciiStrToUnicodeStrS (\r
560 SessionConfigData->TargetUrl,\r
561 IfrNvData->TargetIp,\r
562 sizeof (IfrNvData->TargetIp) / sizeof (IfrNvData->TargetIp[0])\r
563 );\r
564 }\r
565\r
566 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->BootLun);\r
567 IScsiConvertIsIdToString (IfrNvData->IsId, SessionConfigData->IsId);\r
568\r
569 IfrNvData->ConnectRetryCount = SessionConfigData->ConnectRetryCount;\r
570 IfrNvData->ConnectTimeout = SessionConfigData->ConnectTimeout;\r
571\r
572 //\r
573 // Authentication parameters.\r
574 //\r
575 IfrNvData->AuthenticationType = Attempt->AuthenticationType;\r
576\r
577 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
578 AuthConfigData = &Attempt->AuthConfigData.CHAP;\r
579 IfrNvData->CHAPType = AuthConfigData->CHAPType;\r
580 AsciiStrToUnicodeStrS (\r
581 AuthConfigData->CHAPName,\r
582 IfrNvData->CHAPName,\r
583 sizeof (IfrNvData->CHAPName) / sizeof (IfrNvData->CHAPName[0])\r
584 );\r
585 AsciiStrToUnicodeStrS (\r
586 AuthConfigData->CHAPSecret,\r
587 IfrNvData->CHAPSecret,\r
588 sizeof (IfrNvData->CHAPSecret) / sizeof (IfrNvData->CHAPSecret[0])\r
589 );\r
590 AsciiStrToUnicodeStrS (\r
591 AuthConfigData->ReverseCHAPName,\r
592 IfrNvData->ReverseCHAPName,\r
593 sizeof (IfrNvData->ReverseCHAPName) / sizeof (IfrNvData->ReverseCHAPName[0])\r
594 );\r
595 AsciiStrToUnicodeStrS (\r
596 AuthConfigData->ReverseCHAPSecret,\r
597 IfrNvData->ReverseCHAPSecret,\r
598 sizeof (IfrNvData->ReverseCHAPSecret) / sizeof (IfrNvData->ReverseCHAPSecret[0])\r
599 );\r
600 }\r
601\r
602 //\r
603 // Other parameters.\r
604 //\r
605 AsciiStrToUnicodeStrS (\r
606 Attempt->AttemptName,\r
607 IfrNvData->AttemptName,\r
608 sizeof (IfrNvData->AttemptName) / sizeof (IfrNvData->AttemptName[0])\r
609 );\r
610}\r
611\r
612/**\r
613 Convert the iSCSI configuration data into the IFR data Which will be used\r
614 to extract the iSCSI Keyword configuration in <ConfigAltResp> format.\r
615\r
616 @param[in, out] IfrNvData The IFR nv data.\r
617\r
618**/\r
619VOID\r
620EFIAPI\r
621IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (\r
622 IN OUT ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
623 )\r
624{\r
625 LIST_ENTRY *Entry;\r
626 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;\r
627 ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData;\r
628 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;\r
629 CHAR16 AttemptNameList[ATTEMPT_NAME_LIST_SIZE];\r
630 ISCSI_NIC_INFO *NicInfo;\r
631 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
632 EFI_IP_ADDRESS Ip;\r
633 UINTN Index;\r
634 UINTN StringLen;\r
635\r
636 NicInfo = NULL;\r
637 ZeroMem (AttemptNameList, sizeof (AttemptNameList));\r
638\r
639 if ((mPrivate != NULL) && (mPrivate->AttemptCount != 0)) {\r
640 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
641 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
642 //\r
643 // Normal session configuration parameters.\r
644 //\r
645 SessionConfigData = &Attempt->SessionConfigData;\r
646\r
647 ASSERT ((Attempt->AttemptConfigIndex > 0) && (Attempt->AttemptConfigIndex <= FixedPcdGet8 (PcdMaxIScsiAttemptNumber)));\r
648 Index = Attempt->AttemptConfigIndex - 1;\r
649\r
650 //\r
651 // Save the attempt to AttemptNameList as Attempt:1 Attempt:2\r
652 //\r
653 AsciiStrToUnicodeStrS (\r
654 Attempt->AttemptName,\r
655 AttemptNameList + StrLen (AttemptNameList),\r
656 ATTEMPT_NAME_LIST_SIZE - StrLen (AttemptNameList)\r
657 );\r
658\r
659 StringLen = StrLen (AttemptNameList);\r
660 ASSERT (StringLen > 2);\r
661 *(AttemptNameList + StringLen - 2) = L':';\r
662 *(AttemptNameList + StringLen) = L' ';\r
663\r
664 AsciiStrToUnicodeStrS (\r
665 Attempt->AttemptName,\r
666 IfrNvData->ISCSIAttemptName + ATTEMPT_NAME_SIZE * Index,\r
667 ATTEMPT_NAME_LIST_SIZE - ATTEMPT_NAME_SIZE * Index\r
668 );\r
669\r
670 IfrNvData->ISCSIBootEnableList[Index] = SessionConfigData->Enabled;\r
671 IfrNvData->ISCSIIpAddressTypeList[Index] = SessionConfigData->IpMode;\r
672\r
673 IfrNvData->ISCSIInitiatorInfoViaDHCP[Index] = SessionConfigData->InitiatorInfoFromDhcp;\r
674 IfrNvData->ISCSITargetInfoViaDHCP[Index] = SessionConfigData->TargetInfoFromDhcp;\r
675 IfrNvData->ISCSIConnectRetry[Index] = SessionConfigData->ConnectRetryCount;\r
676 IfrNvData->ISCSIConnectTimeout[Index] = SessionConfigData->ConnectTimeout;\r
677 IfrNvData->ISCSITargetTcpPort[Index] = SessionConfigData->TargetPort;\r
678\r
679 if (SessionConfigData->IpMode == IP_MODE_IP4) {\r
680 CopyMem (&Ip.v4, &SessionConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));\r
681 IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSIInitiatorIpAddress);\r
682 CopyMem (&Ip.v4, &SessionConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
683 IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSIInitiatorNetmask);\r
684 CopyMem (&Ip.v4, &SessionConfigData->Gateway, sizeof (EFI_IPv4_ADDRESS));\r
685 IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSIInitiatorGateway);\r
686 if (SessionConfigData->TargetIp.v4.Addr[0] != '\0') {\r
687 CopyMem (&Ip.v4, &SessionConfigData->TargetIp, sizeof (EFI_IPv4_ADDRESS));\r
688 IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSITargetIpAddress);\r
689 }\r
690 } else if (SessionConfigData->IpMode == IP_MODE_IP6) {\r
691 ZeroMem (IfrNvData->Keyword[Index].ISCSITargetIpAddress, sizeof (IfrNvData->TargetIp));\r
692 if (SessionConfigData->TargetIp.v6.Addr[0] != '\0') {\r
693 IP6_COPY_ADDRESS (&Ip.v6, &SessionConfigData->TargetIp);\r
694 IScsiIpToStr (&Ip, TRUE, IfrNvData->Keyword[Index].ISCSITargetIpAddress);\r
695 }\r
696 }\r
697\r
698 AsciiStrToUnicodeStrS (\r
699 SessionConfigData->TargetName,\r
700 IfrNvData->Keyword[Index].ISCSITargetName,\r
701 ISCSI_NAME_MAX_SIZE\r
702 );\r
703\r
704 if (SessionConfigData->DnsMode) {\r
705 AsciiStrToUnicodeStrS (\r
706 SessionConfigData->TargetUrl,\r
707 IfrNvData->Keyword[Index].ISCSITargetIpAddress,\r
708 sizeof (IfrNvData->Keyword[Index].ISCSITargetIpAddress) / sizeof (IfrNvData->Keyword[Index].ISCSITargetIpAddress[0])\r
709 );\r
710 }\r
711\r
712 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->Keyword[Index].ISCSILun);\r
713 IScsiConvertIsIdToString (IfrNvData->Keyword[Index].ISCSIIsId, SessionConfigData->IsId);\r
714\r
715 IfrNvData->ISCSIAuthenticationMethod[Index] = Attempt->AuthenticationType;\r
716\r
717 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
718 AuthConfigData = &Attempt->AuthConfigData.CHAP;\r
719 IfrNvData->ISCSIChapType[Index] = AuthConfigData->CHAPType;\r
720 AsciiStrToUnicodeStrS (\r
721 AuthConfigData->CHAPName,\r
722 IfrNvData->Keyword[Index].ISCSIChapUsername,\r
723 ISCSI_CHAP_NAME_STORAGE\r
724 );\r
725\r
726 AsciiStrToUnicodeStrS (\r
727 AuthConfigData->CHAPSecret,\r
728 IfrNvData->Keyword[Index].ISCSIChapSecret,\r
729 ISCSI_CHAP_SECRET_STORAGE\r
730 );\r
731\r
732 AsciiStrToUnicodeStrS (\r
733 AuthConfigData->ReverseCHAPName,\r
734 IfrNvData->Keyword[Index].ISCSIReverseChapUsername,\r
735 ISCSI_CHAP_NAME_STORAGE\r
736 );\r
737\r
738 AsciiStrToUnicodeStrS (\r
739 AuthConfigData->ReverseCHAPSecret,\r
740 IfrNvData->Keyword[Index].ISCSIReverseChapSecret,\r
741 ISCSI_CHAP_SECRET_STORAGE\r
742 );\r
743 }\r
744 }\r
745 CopyMem (IfrNvData->ISCSIDisplayAttemptList, AttemptNameList, ATTEMPT_NAME_LIST_SIZE);\r
746\r
747 ZeroMem (IfrNvData->ISCSIMacAddr, sizeof (IfrNvData->ISCSIMacAddr));\r
748 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
749 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
750 IScsiMacAddrToStr (\r
751 &NicInfo->PermanentAddress,\r
752 NicInfo->HwAddressSize,\r
753 NicInfo->VlanId,\r
754 MacString\r
755 );\r
756 CopyMem (\r
757 IfrNvData->ISCSIMacAddr + StrLen (IfrNvData->ISCSIMacAddr),\r
758 MacString,\r
759 StrLen (MacString) * sizeof (CHAR16)\r
760 );\r
761\r
762 *(IfrNvData->ISCSIMacAddr + StrLen (IfrNvData->ISCSIMacAddr)) = L'/';\r
763 }\r
764\r
765 StringLen = StrLen (IfrNvData->ISCSIMacAddr);\r
766 if (StringLen > 0) {\r
767 *(IfrNvData->ISCSIMacAddr + StringLen - 1) = L'\0';\r
768 }\r
769 }\r
770}\r
771\r
772/**\r
773 Convert the IFR data to iSCSI configuration data.\r
774\r
775 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.\r
776 @param[in, out] Attempt The iSCSI attempt config data.\r
777\r
778 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.\r
779 @retval EFI_NOT_FOUND Cannot find the corresponding variable.\r
780 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.\r
781 @retval EFI_ABORTED The operation is aborted.\r
782 @retval EFI_SUCCESS The operation is completed successfully.\r
783\r
784**/\r
785EFI_STATUS\r
786IScsiConvertIfrNvDataToAttemptConfigData (\r
787 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData,\r
788 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt\r
789 )\r
790{\r
791 EFI_IP_ADDRESS HostIp;\r
792 EFI_IP_ADDRESS SubnetMask;\r
793 EFI_IP_ADDRESS Gateway;\r
794 CHAR16 *MacString;\r
795 CHAR16 *AttemptName1;\r
796 CHAR16 *AttemptName2;\r
797 ISCSI_ATTEMPT_CONFIG_NVDATA *ExistAttempt;\r
798 ISCSI_ATTEMPT_CONFIG_NVDATA *SameNicAttempt;\r
799 CHAR16 IScsiMode[64];\r
800 CHAR16 IpMode[64];\r
801 ISCSI_NIC_INFO *NicInfo;\r
802 EFI_INPUT_KEY Key;\r
803 UINT8 *AttemptConfigOrder;\r
804 UINTN AttemptConfigOrderSize;\r
805 UINT8 *AttemptOrderTmp;\r
806 UINTN TotalNumber;\r
807 EFI_STATUS Status;\r
808\r
809 if ((IfrNvData == NULL) || (Attempt == NULL)) {\r
810 return EFI_INVALID_PARAMETER;\r
811 }\r
812\r
813 //\r
814 // Update those fields which don't have INTERACTIVE attribute.\r
815 //\r
816 Attempt->SessionConfigData.ConnectRetryCount = IfrNvData->ConnectRetryCount;\r
817 Attempt->SessionConfigData.ConnectTimeout = IfrNvData->ConnectTimeout;\r
818 Attempt->SessionConfigData.IpMode = IfrNvData->IpMode;\r
819\r
820 if (IfrNvData->IpMode < IP_MODE_AUTOCONFIG) {\r
821 Attempt->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp;\r
822 Attempt->SessionConfigData.TargetPort = IfrNvData->TargetPort;\r
823\r
824 if (Attempt->SessionConfigData.TargetPort == 0) {\r
825 Attempt->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;\r
826 }\r
827\r
828 Attempt->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp;\r
829 }\r
830\r
831 Attempt->AuthenticationType = IfrNvData->AuthenticationType;\r
832\r
833 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
834 Attempt->AuthConfigData.CHAP.CHAPType = IfrNvData->CHAPType;\r
835 }\r
836\r
837 //\r
838 // Only do full parameter validation if iSCSI is enabled on this device.\r
839 //\r
840 if (IfrNvData->Enabled != ISCSI_DISABLED) {\r
841 if (Attempt->SessionConfigData.ConnectTimeout < CONNECT_MIN_TIMEOUT) {\r
842 CreatePopUp (\r
843 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
844 &Key,\r
845 L"Connection Establishing Timeout is less than minimum value 100ms.",\r
846 NULL\r
847 );\r
848\r
849 return EFI_INVALID_PARAMETER;\r
850 }\r
851\r
852 //\r
853 // Validate the address configuration of the Initiator if DHCP isn't\r
854 // deployed.\r
855 //\r
856 if (!Attempt->SessionConfigData.InitiatorInfoFromDhcp) {\r
857 CopyMem (&HostIp.v4, &Attempt->SessionConfigData.LocalIp, sizeof (HostIp.v4));\r
858 CopyMem (&SubnetMask.v4, &Attempt->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));\r
859 CopyMem (&Gateway.v4, &Attempt->SessionConfigData.Gateway, sizeof (Gateway.v4));\r
860\r
861 if ((Gateway.Addr[0] != 0)) {\r
862 if (SubnetMask.Addr[0] == 0) {\r
863 CreatePopUp (\r
864 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
865 &Key,\r
866 L"Gateway address is set but subnet mask is zero.",\r
867 NULL\r
868 );\r
869\r
870 return EFI_INVALID_PARAMETER;\r
871 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {\r
872 CreatePopUp (\r
873 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
874 &Key,\r
875 L"Local IP and Gateway are not in the same subnet.",\r
876 NULL\r
877 );\r
878\r
879 return EFI_INVALID_PARAMETER;\r
880 }\r
881 }\r
882 }\r
883\r
884 //\r
885 // Validate target configuration if DHCP isn't deployed.\r
886 //\r
887 if (!Attempt->SessionConfigData.TargetInfoFromDhcp && (Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG)) {\r
888 if (!Attempt->SessionConfigData.DnsMode) {\r
889 if (!IpIsUnicast (&Attempt->SessionConfigData.TargetIp, IfrNvData->IpMode)) {\r
890 CreatePopUp (\r
891 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
892 &Key,\r
893 L"Target IP is invalid!",\r
894 NULL\r
895 );\r
896 return EFI_INVALID_PARAMETER;\r
897 }\r
898 } else {\r
899 if (Attempt->SessionConfigData.TargetUrl[0] == '\0') {\r
900 CreatePopUp (\r
901 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
902 &Key,\r
903 L"iSCSI target Url should not be NULL!",\r
904 NULL\r
905 );\r
906 return EFI_INVALID_PARAMETER;\r
907 }\r
908 }\r
909\r
910 //\r
911 // Validate iSCSI target name configuration again:\r
912 // The format of iSCSI target name is already verified in IScsiFormCallback() when\r
913 // user input the name; here we only check the case user does not input the name.\r
914 //\r
915 if (Attempt->SessionConfigData.TargetName[0] == '\0') {\r
916 CreatePopUp (\r
917 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
918 &Key,\r
919 L"iSCSI target name is NULL!",\r
920 NULL\r
921 );\r
922 return EFI_INVALID_PARAMETER;\r
923 }\r
924 }\r
925\r
926 //\r
927 // Validate the authentication info.\r
928 //\r
929 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
930 if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) {\r
931 CreatePopUp (\r
932 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
933 &Key,\r
934 L"CHAP Name or CHAP Secret is invalid!",\r
935 NULL\r
936 );\r
937\r
938 return EFI_INVALID_PARAMETER;\r
939 }\r
940\r
941 if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) &&\r
942 ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0'))\r
943 )\r
944 {\r
945 CreatePopUp (\r
946 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
947 &Key,\r
948 L"Reverse CHAP Name or Reverse CHAP Secret is invalid!",\r
949 NULL\r
950 );\r
951 return EFI_INVALID_PARAMETER;\r
952 }\r
953 }\r
954\r
955 //\r
956 // Check whether this attempt uses NIC which is already used by existing attempt.\r
957 //\r
958 SameNicAttempt = IScsiConfigGetAttemptByNic (Attempt, IfrNvData->Enabled);\r
959 if (SameNicAttempt != NULL) {\r
960 AttemptName1 = (CHAR16 *)AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));\r
961 if (AttemptName1 == NULL) {\r
962 return EFI_OUT_OF_RESOURCES;\r
963 }\r
964\r
965 AttemptName2 = (CHAR16 *)AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));\r
966 if (AttemptName2 == NULL) {\r
967 FreePool (AttemptName1);\r
968 return EFI_OUT_OF_RESOURCES;\r
969 }\r
970\r
971 AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_SIZE);\r
972 AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_SIZE);\r
973\r
974 UnicodeSPrint (\r
975 mPrivate->PortString,\r
976 (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
977 L"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",\r
978 AttemptName1,\r
979 AttemptName2\r
980 );\r
981\r
982 CreatePopUp (\r
983 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
984 &Key,\r
985 mPrivate->PortString,\r
986 NULL\r
987 );\r
988\r
989 FreePool (AttemptName1);\r
990 FreePool (AttemptName2);\r
991 }\r
992 }\r
993\r
994 //\r
995 // Update the iSCSI Mode data and record it in attempt help info.\r
996 //\r
997 if (IfrNvData->Enabled == ISCSI_DISABLED) {\r
998 UnicodeSPrint (IScsiMode, 64, L"Disabled");\r
999 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {\r
1000 UnicodeSPrint (IScsiMode, 64, L"Enabled");\r
1001 } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
1002 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");\r
1003 }\r
1004\r
1005 if (IfrNvData->IpMode == IP_MODE_IP4) {\r
1006 UnicodeSPrint (IpMode, 64, L"IP4");\r
1007 } else if (IfrNvData->IpMode == IP_MODE_IP6) {\r
1008 UnicodeSPrint (IpMode, 64, L"IP6");\r
1009 } else if (IfrNvData->IpMode == IP_MODE_AUTOCONFIG) {\r
1010 UnicodeSPrint (IpMode, 64, L"Autoconfigure");\r
1011 }\r
1012\r
1013 NicInfo = IScsiGetNicInfoByIndex (Attempt->NicIndex);\r
1014 if (NicInfo == NULL) {\r
1015 return EFI_NOT_FOUND;\r
1016 }\r
1017\r
1018 MacString = (CHAR16 *)AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN * sizeof (CHAR16));\r
1019 if (MacString == NULL) {\r
1020 return EFI_OUT_OF_RESOURCES;\r
1021 }\r
1022\r
1023 AsciiStrToUnicodeStrS (Attempt->MacString, MacString, ISCSI_MAX_MAC_STRING_LEN);\r
1024\r
1025 UnicodeSPrint (\r
1026 mPrivate->PortString,\r
1027 (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
1028 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",\r
1029 MacString,\r
1030 NicInfo->BusNumber,\r
1031 NicInfo->DeviceNumber,\r
1032 NicInfo->FunctionNumber,\r
1033 IScsiMode,\r
1034 IpMode\r
1035 );\r
1036\r
1037 Attempt->AttemptTitleHelpToken = HiiSetString (\r
1038 mCallbackInfo->RegisteredHandle,\r
1039 Attempt->AttemptTitleHelpToken,\r
1040 mPrivate->PortString,\r
1041 NULL\r
1042 );\r
1043 if (Attempt->AttemptTitleHelpToken == 0) {\r
1044 FreePool (MacString);\r
1045 return EFI_OUT_OF_RESOURCES;\r
1046 }\r
1047\r
1048 //\r
1049 // Check whether this attempt is an existing one.\r
1050 //\r
1051 ExistAttempt = IScsiConfigGetAttemptByConfigIndex (Attempt->AttemptConfigIndex);\r
1052 if (ExistAttempt != NULL) {\r
1053 ASSERT (ExistAttempt == Attempt);\r
1054\r
1055 if ((IfrNvData->Enabled == ISCSI_DISABLED) &&\r
1056 (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED))\r
1057 {\r
1058 //\r
1059 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".\r
1060 //\r
1061 if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
1062 if (mPrivate->MpioCount < 1) {\r
1063 return EFI_ABORTED;\r
1064 }\r
1065\r
1066 if (--mPrivate->MpioCount == 0) {\r
1067 mPrivate->EnableMpio = FALSE;\r
1068 }\r
1069 } else if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
1070 if (mPrivate->SinglePathCount < 1) {\r
1071 return EFI_ABORTED;\r
1072 }\r
1073\r
1074 mPrivate->SinglePathCount--;\r
1075 }\r
1076 } else if ((IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) &&\r
1077 (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED))\r
1078 {\r
1079 //\r
1080 // User updates the Attempt from "Enabled" to "Enabled for MPIO".\r
1081 //\r
1082 if (mPrivate->SinglePathCount < 1) {\r
1083 return EFI_ABORTED;\r
1084 }\r
1085\r
1086 mPrivate->EnableMpio = TRUE;\r
1087 mPrivate->MpioCount++;\r
1088 mPrivate->SinglePathCount--;\r
1089 } else if ((IfrNvData->Enabled == ISCSI_ENABLED) &&\r
1090 (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO))\r
1091 {\r
1092 //\r
1093 // User updates the Attempt from "Enabled for MPIO" to "Enabled".\r
1094 //\r
1095 if (mPrivate->MpioCount < 1) {\r
1096 return EFI_ABORTED;\r
1097 }\r
1098\r
1099 if (--mPrivate->MpioCount == 0) {\r
1100 mPrivate->EnableMpio = FALSE;\r
1101 }\r
1102\r
1103 mPrivate->SinglePathCount++;\r
1104 } else if ((IfrNvData->Enabled != ISCSI_DISABLED) &&\r
1105 (Attempt->SessionConfigData.Enabled == ISCSI_DISABLED))\r
1106 {\r
1107 //\r
1108 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".\r
1109 //\r
1110 if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
1111 mPrivate->EnableMpio = TRUE;\r
1112 mPrivate->MpioCount++;\r
1113 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {\r
1114 mPrivate->SinglePathCount++;\r
1115 }\r
1116 }\r
1117 } else if (ExistAttempt == NULL) {\r
1118 //\r
1119 // When a new attempt is created, pointer of the attempt is saved to\r
1120 // mCallbackInfo->Current in IScsiConfigProcessDefault. If input Attempt\r
1121 // does not match any existing attempt, it should be a new created attempt.\r
1122 // Save it to system now.\r
1123 //\r
1124\r
1125 //\r
1126 // Save current order number for this attempt.\r
1127 //\r
1128 AttemptConfigOrder = IScsiGetVariableAndSize (\r
1129 L"AttemptOrder",\r
1130 &gIScsiConfigGuid,\r
1131 &AttemptConfigOrderSize\r
1132 );\r
1133\r
1134 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);\r
1135 TotalNumber++;\r
1136\r
1137 //\r
1138 // Append the new created attempt order to the end.\r
1139 //\r
1140 AttemptOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));\r
1141 if (AttemptOrderTmp == NULL) {\r
1142 if (AttemptConfigOrder != NULL) {\r
1143 FreePool (AttemptConfigOrder);\r
1144 }\r
1145\r
1146 return EFI_OUT_OF_RESOURCES;\r
1147 }\r
1148\r
1149 if (AttemptConfigOrder != NULL) {\r
1150 CopyMem (AttemptOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);\r
1151 FreePool (AttemptConfigOrder);\r
1152 }\r
1153\r
1154 AttemptOrderTmp[TotalNumber - 1] = Attempt->AttemptConfigIndex;\r
1155 AttemptConfigOrder = AttemptOrderTmp;\r
1156 AttemptConfigOrderSize = TotalNumber * sizeof (UINT8);\r
1157\r
1158 Status = gRT->SetVariable (\r
1159 L"AttemptOrder",\r
1160 &gIScsiConfigGuid,\r
1161 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
1162 AttemptConfigOrderSize,\r
1163 AttemptConfigOrder\r
1164 );\r
1165 FreePool (AttemptConfigOrder);\r
1166 if (EFI_ERROR (Status)) {\r
1167 return Status;\r
1168 }\r
1169\r
1170 //\r
1171 // Insert new created attempt to array.\r
1172 //\r
1173 InsertTailList (&mPrivate->AttemptConfigs, &Attempt->Link);\r
1174 mPrivate->AttemptCount++;\r
1175\r
1176 if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
1177 //\r
1178 // This new Attempt is enabled for MPIO; enable the multipath mode.\r
1179 //\r
1180 mPrivate->EnableMpio = TRUE;\r
1181 mPrivate->MpioCount++;\r
1182 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {\r
1183 mPrivate->SinglePathCount++;\r
1184 }\r
1185\r
1186 IScsiConfigUpdateAttempt ();\r
1187 }\r
1188\r
1189 Attempt->SessionConfigData.Enabled = IfrNvData->Enabled;\r
1190\r
1191 //\r
1192 // Record the user configuration information in NVR.\r
1193 //\r
1194 UnicodeSPrint (mPrivate->PortString, (UINTN)ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", Attempt->AttemptConfigIndex);\r
1195\r
1196 FreePool (MacString);\r
1197\r
1198 return gRT->SetVariable (\r
1199 mPrivate->PortString,\r
1200 &gEfiIScsiInitiatorNameProtocolGuid,\r
1201 ISCSI_CONFIG_VAR_ATTR,\r
1202 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
1203 Attempt\r
1204 );\r
1205}\r
1206\r
1207/**\r
1208 Convert the IFR data configured by keyword to iSCSI configuration data.\r
1209\r
1210 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.\r
1211 @param[in] OffSet The offset of the variable to the configuration structure.\r
1212\r
1213 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.\r
1214 @retval EFI_SUCCESS The operation is completed successfully.\r
1215\r
1216**/\r
1217EFI_STATUS\r
1218IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (\r
1219 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData,\r
1220 IN UINTN OffSet\r
1221 )\r
1222{\r
1223 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;\r
1224 UINT8 AttemptIndex;\r
1225 UINT8 Index;\r
1226 UINT8 ChapSecretLen;\r
1227 UINT8 ReverseChapSecretLen;\r
1228 CHAR16 *AttemptName1;\r
1229 CHAR16 *AttemptName2;\r
1230 ISCSI_ATTEMPT_CONFIG_NVDATA *SameNicAttempt;\r
1231 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];\r
1232 CHAR8 IScsiName[ISCSI_NAME_MAX_SIZE];\r
1233 CHAR8 IpString[IP_STR_MAX_SIZE];\r
1234 EFI_IP_ADDRESS HostIp;\r
1235 EFI_IP_ADDRESS SubnetMask;\r
1236 EFI_IP_ADDRESS Gateway;\r
1237 EFI_INPUT_KEY Key;\r
1238 UINT64 Lun;\r
1239 EFI_STATUS Status;\r
1240\r
1241 Attempt = NULL;\r
1242 ZeroMem (IScsiName, sizeof (IScsiName));\r
1243\r
1244 if (OffSet < ATTEMPT_BOOTENABLE_VAR_OFFSET) {\r
1245 return EFI_SUCCESS;\r
1246 } else if ((OffSet >= ATTEMPT_BOOTENABLE_VAR_OFFSET) && (OffSet < ATTEMPT_ADDRESS_TYPE_VAR_OFFSET)) {\r
1247 AttemptIndex = (UINT8)((OffSet - ATTEMPT_BOOTENABLE_VAR_OFFSET) + 1);\r
1248 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
1249 if (Attempt == NULL) {\r
1250 return EFI_INVALID_PARAMETER;\r
1251 }\r
1252\r
1253 IfrNvData->Enabled = IfrNvData->ISCSIBootEnableList[AttemptIndex - 1];\r
1254 //\r
1255 // Validate the configuration of attempt.\r
1256 //\r
1257 if (IfrNvData->Enabled != ISCSI_DISABLED) {\r
1258 //\r
1259 // Check whether this attempt uses NIC which is already used by existing attempt.\r
1260 //\r
1261 SameNicAttempt = IScsiConfigGetAttemptByNic (Attempt, IfrNvData->Enabled);\r
1262 if (SameNicAttempt != NULL) {\r
1263 AttemptName1 = (CHAR16 *)AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));\r
1264 if (AttemptName1 == NULL) {\r
1265 return EFI_OUT_OF_RESOURCES;\r
1266 }\r
1267\r
1268 AttemptName2 = (CHAR16 *)AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));\r
1269 if (AttemptName2 == NULL) {\r
1270 FreePool (AttemptName1);\r
1271 return EFI_OUT_OF_RESOURCES;\r
1272 }\r
1273\r
1274 AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_SIZE);\r
1275 AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_SIZE);\r
1276\r
1277 UnicodeSPrint (\r
1278 mPrivate->PortString,\r
1279 (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
1280 L"Warning! \"%s\" uses same NIC as Attempt \"%s\".",\r
1281 AttemptName1,\r
1282 AttemptName2\r
1283 );\r
1284\r
1285 CreatePopUp (\r
1286 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1287 &Key,\r
1288 mPrivate->PortString,\r
1289 NULL\r
1290 );\r
1291\r
1292 FreePool (AttemptName1);\r
1293 FreePool (AttemptName2);\r
1294 }\r
1295 }\r
1296\r
1297 if ((IfrNvData->Enabled == ISCSI_DISABLED) &&\r
1298 (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED))\r
1299 {\r
1300 //\r
1301 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".\r
1302 //\r
1303 if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
1304 if (mPrivate->MpioCount < 1) {\r
1305 return EFI_ABORTED;\r
1306 }\r
1307\r
1308 if (--mPrivate->MpioCount == 0) {\r
1309 mPrivate->EnableMpio = FALSE;\r
1310 }\r
1311 } else if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
1312 if (mPrivate->SinglePathCount < 1) {\r
1313 return EFI_ABORTED;\r
1314 }\r
1315\r
1316 mPrivate->SinglePathCount--;\r
1317 }\r
1318 } else if ((IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) &&\r
1319 (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED))\r
1320 {\r
1321 //\r
1322 // User updates the Attempt from "Enabled" to "Enabled for MPIO".\r
1323 //\r
1324 if (mPrivate->SinglePathCount < 1) {\r
1325 return EFI_ABORTED;\r
1326 }\r
1327\r
1328 mPrivate->EnableMpio = TRUE;\r
1329 mPrivate->MpioCount++;\r
1330 mPrivate->SinglePathCount--;\r
1331 } else if ((IfrNvData->Enabled == ISCSI_ENABLED) &&\r
1332 (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO))\r
1333 {\r
1334 //\r
1335 // User updates the Attempt from "Enabled for MPIO" to "Enabled".\r
1336 //\r
1337 if (mPrivate->MpioCount < 1) {\r
1338 return EFI_ABORTED;\r
1339 }\r
1340\r
1341 if (--mPrivate->MpioCount == 0) {\r
1342 mPrivate->EnableMpio = FALSE;\r
1343 }\r
1344\r
1345 mPrivate->SinglePathCount++;\r
1346 } else if ((IfrNvData->Enabled != ISCSI_DISABLED) &&\r
1347 (Attempt->SessionConfigData.Enabled == ISCSI_DISABLED))\r
1348 {\r
1349 //\r
1350 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".\r
1351 //\r
1352 if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
1353 mPrivate->EnableMpio = TRUE;\r
1354 mPrivate->MpioCount++;\r
1355 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {\r
1356 mPrivate->SinglePathCount++;\r
1357 }\r
1358 }\r
1359\r
1360 Attempt->SessionConfigData.Enabled = IfrNvData->Enabled;\r
1361 } else if ((OffSet >= ATTEMPT_ADDRESS_TYPE_VAR_OFFSET) && (OffSet < ATTEMPT_CONNECT_RETRY_VAR_OFFSET)) {\r
1362 AttemptIndex = (UINT8)((OffSet - ATTEMPT_ADDRESS_TYPE_VAR_OFFSET) + 1);\r
1363 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
1364 if (Attempt == NULL) {\r
1365 return EFI_INVALID_PARAMETER;\r
1366 }\r
1367\r
1368 Attempt->SessionConfigData.IpMode = IfrNvData->ISCSIIpAddressTypeList[AttemptIndex - 1];\r
1369 if (Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) {\r
1370 Attempt->AutoConfigureMode = 0;\r
1371 }\r
1372 } else if ((OffSet >= ATTEMPT_CONNECT_RETRY_VAR_OFFSET) && (OffSet < ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET)) {\r
1373 AttemptIndex = (UINT8)((OffSet - ATTEMPT_CONNECT_RETRY_VAR_OFFSET) + 1);\r
1374 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
1375 if (Attempt == NULL) {\r
1376 return EFI_INVALID_PARAMETER;\r
1377 }\r
1378\r
1379 if (IfrNvData->ISCSIConnectRetry[AttemptIndex - 1] > CONNECT_MAX_RETRY) {\r
1380 CreatePopUp (\r
1381 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1382 &Key,\r
1383 L"The minimum value is 0 and the maximum is 16. 0 means no retry.",\r
1384 NULL\r
1385 );\r
1386 return EFI_INVALID_PARAMETER;\r
1387 }\r
1388\r
1389 Attempt->SessionConfigData.ConnectRetryCount = IfrNvData->ISCSIConnectRetry[AttemptIndex - 1];\r
1390 } else if ((OffSet >= ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET)) {\r
1391 AttemptIndex = (UINT8)((OffSet - ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET) / 2 + 1);\r
1392 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
1393 if (Attempt == NULL) {\r
1394 return EFI_INVALID_PARAMETER;\r
1395 }\r
1396\r
1397 if ((IfrNvData->ISCSIConnectTimeout[AttemptIndex - 1] < CONNECT_MIN_TIMEOUT) ||\r
1398 (IfrNvData->ISCSIConnectTimeout[AttemptIndex - 1] > CONNECT_MAX_TIMEOUT))\r
1399 {\r
1400 CreatePopUp (\r
1401 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1402 &Key,\r
1403 L"The minimum value is 100 milliseconds and the maximum is 20 seconds.",\r
1404 NULL\r
1405 );\r
1406 return EFI_INVALID_PARAMETER;\r
1407 }\r
1408\r
1409 Attempt->SessionConfigData.ConnectTimeout = IfrNvData->ISCSIConnectTimeout[AttemptIndex - 1];\r
1410 if (Attempt->SessionConfigData.ConnectTimeout == 0) {\r
1411 Attempt->SessionConfigData.ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;\r
1412 }\r
1413 } else if ((OffSet >= ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET)) {\r
1414 AttemptIndex = (UINT8)((OffSet - ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET) + 1);\r
1415 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
1416 if (Attempt == NULL) {\r
1417 return EFI_INVALID_PARAMETER;\r
1418 }\r
1419\r
1420 Attempt->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->ISCSIInitiatorInfoViaDHCP[AttemptIndex - 1];\r
1421 } else if ((OffSet >= ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET)) {\r
1422 AttemptIndex = (UINT8)((OffSet - ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET) + 1);\r
1423 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
1424 if (Attempt == NULL) {\r
1425 return EFI_INVALID_PARAMETER;\r
1426 }\r
1427\r
1428 if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {\r
1429 Attempt->SessionConfigData.TargetInfoFromDhcp = IfrNvData->ISCSITargetInfoViaDHCP[AttemptIndex - 1];\r
1430 } else {\r
1431 CreatePopUp (\r
1432 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1433 &Key,\r
1434 L"Invalid Configuration, Check value of IpMode or Enable DHCP!",\r
1435 NULL\r
1436 );\r
1437 return EFI_INVALID_PARAMETER;\r
1438 }\r
1439 } else if ((OffSet >= ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET) && (OffSet < ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET)) {\r
1440 AttemptIndex = (UINT8)((OffSet - ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET) / 2 + 1);\r
1441 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
1442 if (Attempt == NULL) {\r
1443 return EFI_INVALID_PARAMETER;\r
1444 }\r
1445\r
1446 if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (!Attempt->SessionConfigData.TargetInfoFromDhcp)) {\r
1447 Attempt->SessionConfigData.TargetPort = IfrNvData->ISCSITargetTcpPort[AttemptIndex - 1];\r
1448 if (Attempt->SessionConfigData.TargetPort == 0) {\r
1449 Attempt->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;\r
1450 }\r
1451 } else {\r
1452 CreatePopUp (\r
1453 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1454 &Key,\r
1455 L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",\r
1456 NULL\r
1457 );\r
1458 return EFI_INVALID_PARAMETER;\r
1459 }\r
1460 } else if ((OffSet >= ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET) && (OffSet < ATTEMPT_CHARTYPE_VAR_OFFSET)) {\r
1461 AttemptIndex = (UINT8)((OffSet - ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET) + 1);\r
1462 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
1463 if (Attempt == NULL) {\r
1464 return EFI_INVALID_PARAMETER;\r
1465 }\r
1466\r
1467 Attempt->AuthenticationType = IfrNvData->ISCSIAuthenticationMethod[AttemptIndex - 1];\r
1468 } else if ((OffSet >= ATTEMPT_CHARTYPE_VAR_OFFSET) && (OffSet < ATTEMPT_ISID_VAR_OFFSET)) {\r
1469 AttemptIndex = (UINT8)((OffSet - ATTEMPT_CHARTYPE_VAR_OFFSET) + 1);\r
1470 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
1471 if (Attempt == NULL) {\r
1472 return EFI_INVALID_PARAMETER;\r
1473 }\r
1474\r
1475 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
1476 Attempt->AuthConfigData.CHAP.CHAPType = IfrNvData->ISCSIChapType[AttemptIndex - 1];\r
1477 }\r
1478 } else if (OffSet >= ATTEMPT_ISID_VAR_OFFSET) {\r
1479 Index = (UINT8)((OffSet - ATTEMPT_ISID_VAR_OFFSET) / sizeof (KEYWORD_STR));\r
1480 AttemptIndex = Index + 1;\r
1481 Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
1482 if (Attempt == NULL) {\r
1483 return EFI_INVALID_PARAMETER;\r
1484 }\r
1485\r
1486 OffSet = OffSet - Index * sizeof (KEYWORD_STR);\r
1487\r
1488 if ((OffSet >= ATTEMPT_ISID_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET)) {\r
1489 IScsiParseIsIdFromString (IfrNvData->Keyword[Index].ISCSIIsId, Attempt->SessionConfigData.IsId);\r
1490 } else if ((OffSet >= ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET)) {\r
1491 if ((Attempt->SessionConfigData.IpMode == IP_MODE_IP4) && (!Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {\r
1492 //\r
1493 // Config Local ip\r
1494 //\r
1495 Status = NetLibStrToIp4 (IfrNvData->Keyword[Index].ISCSIInitiatorIpAddress, &HostIp.v4);\r
1496 if (EFI_ERROR (Status) || ((Attempt->SessionConfigData.SubnetMask.Addr[0] != 0) &&\r
1497 !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), NTOHL (*(UINT32 *)Attempt->SessionConfigData.SubnetMask.Addr))))\r
1498 {\r
1499 CreatePopUp (\r
1500 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1501 &Key,\r
1502 L"Invalid IP address!",\r
1503 NULL\r
1504 );\r
1505 return EFI_INVALID_PARAMETER;\r
1506 } else {\r
1507 CopyMem (&Attempt->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
1508 }\r
1509 } else {\r
1510 CreatePopUp (\r
1511 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1512 &Key,\r
1513 L"Invalid Configuration, Check value of IpMode or Enable DHCP!",\r
1514 NULL\r
1515 );\r
1516 return EFI_INVALID_PARAMETER;\r
1517 }\r
1518 } else if ((OffSet >= ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET)) {\r
1519 if ((Attempt->SessionConfigData.IpMode == IP_MODE_IP4) && (!Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {\r
1520 Status = NetLibStrToIp4 (IfrNvData->Keyword[Index].ISCSIInitiatorNetmask, &SubnetMask.v4);\r
1521 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
1522 CreatePopUp (\r
1523 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1524 &Key,\r
1525 L"Invalid Subnet Mask!",\r
1526 NULL\r
1527 );\r
1528 return EFI_INVALID_PARAMETER;\r
1529 } else {\r
1530 CopyMem (&Attempt->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
1531 }\r
1532 } else {\r
1533 CreatePopUp (\r
1534 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1535 &Key,\r
1536 L"Invalid Configuration, Check value of IpMode or Enable DHCP!",\r
1537 NULL\r
1538 );\r
1539 return EFI_INVALID_PARAMETER;\r
1540 }\r
1541 } else if ((OffSet >= ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_NAME_VAR_OFFSET)) {\r
1542 if ((Attempt->SessionConfigData.IpMode == IP_MODE_IP4) && (!Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {\r
1543 Status = NetLibStrToIp4 (IfrNvData->Keyword[Index].ISCSIInitiatorGateway, &Gateway.v4);\r
1544 if (EFI_ERROR (Status) ||\r
1545 ((Gateway.Addr[0] != 0) && (Attempt->SessionConfigData.SubnetMask.Addr[0] != 0) &&\r
1546 !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL (*(UINT32 *)Attempt->SessionConfigData.SubnetMask.Addr))))\r
1547 {\r
1548 CreatePopUp (\r
1549 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1550 &Key,\r
1551 L"Invalid Gateway!",\r
1552 NULL\r
1553 );\r
1554 return EFI_INVALID_PARAMETER;\r
1555 } else {\r
1556 CopyMem (&Attempt->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
1557 }\r
1558 } else {\r
1559 CreatePopUp (\r
1560 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1561 &Key,\r
1562 L"Invalid Configuration, Check value of IpMode or Enable DHCP!",\r
1563 NULL\r
1564 );\r
1565 return EFI_INVALID_PARAMETER;\r
1566 }\r
1567 } else if ((OffSet >= ATTEMPT_TARGET_NAME_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET)) {\r
1568 if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (!Attempt->SessionConfigData.TargetInfoFromDhcp)) {\r
1569 UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSITargetName, IScsiName, ISCSI_NAME_MAX_SIZE);\r
1570 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));\r
1571 if (EFI_ERROR (Status)) {\r
1572 CreatePopUp (\r
1573 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1574 &Key,\r
1575 L"Invalid iSCSI Name!",\r
1576 NULL\r
1577 );\r
1578 } else {\r
1579 AsciiStrCpyS (Attempt->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName);\r
1580 }\r
1581\r
1582 if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
1583 if (Attempt->SessionConfigData.TargetName[0] == L'\0') {\r
1584 CreatePopUp (\r
1585 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1586 &Key,\r
1587 L"iSCSI target name is NULL!",\r
1588 NULL\r
1589 );\r
1590 return EFI_INVALID_PARAMETER;\r
1591 }\r
1592 }\r
1593 } else {\r
1594 CreatePopUp (\r
1595 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1596 &Key,\r
1597 L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",\r
1598 NULL\r
1599 );\r
1600 return EFI_INVALID_PARAMETER;\r
1601 }\r
1602 } else if ((OffSet >= ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET) && (OffSet < ATTEMPT_LUN_VAR_OFFSET)) {\r
1603 if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (!Attempt->SessionConfigData.TargetInfoFromDhcp)) {\r
1604 UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSITargetIpAddress, IpString, sizeof (IpString));\r
1605 Status = IScsiAsciiStrToIp (IpString, Attempt->SessionConfigData.IpMode, &HostIp);\r
1606 if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, Attempt->SessionConfigData.IpMode)) {\r
1607 Attempt->SessionConfigData.DnsMode = TRUE;\r
1608 ZeroMem (&Attempt->SessionConfigData.TargetIp, sizeof (Attempt->SessionConfigData.TargetIp));\r
1609 UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSITargetIpAddress, Attempt->SessionConfigData.TargetUrl, ISCSI_NAME_MAX_SIZE);\r
1610 } else {\r
1611 Attempt->SessionConfigData.DnsMode = FALSE;\r
1612 CopyMem (&Attempt->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp));\r
1613 }\r
1614 } else {\r
1615 CreatePopUp (\r
1616 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1617 &Key,\r
1618 L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",\r
1619 NULL\r
1620 );\r
1621 return EFI_INVALID_PARAMETER;\r
1622 }\r
1623 } else if ((OffSet >= ATTEMPT_LUN_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_USER_NAME_VAR_OFFSET)) {\r
1624 if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (Attempt->SessionConfigData.TargetInfoFromDhcp == 0)) {\r
1625 //\r
1626 // Config LUN.\r
1627 //\r
1628 UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSILun, LunString, ISCSI_LUN_STR_MAX_LEN);\r
1629 Status = IScsiAsciiStrToLun (LunString, (UINT8 *)&Lun);\r
1630 if (EFI_ERROR (Status)) {\r
1631 CreatePopUp (\r
1632 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1633 &Key,\r
1634 L"Invalid LUN string, Examples are: 4752-3A4F-6b7e-2F99, 6734-9-156f-127, 4186-9!",\r
1635 NULL\r
1636 );\r
1637 } else {\r
1638 CopyMem (&Attempt->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
1639 }\r
1640 } else {\r
1641 CreatePopUp (\r
1642 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1643 &Key,\r
1644 L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",\r
1645 NULL\r
1646 );\r
1647 return EFI_INVALID_PARAMETER;\r
1648 }\r
1649 } else if ((OffSet >= ATTEMPT_CHAR_USER_NAME_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_SECRET_VAR_OFFSET)) {\r
1650 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
1651 UnicodeStrToAsciiStrS (\r
1652 IfrNvData->Keyword[Index].ISCSIChapUsername,\r
1653 Attempt->AuthConfigData.CHAP.CHAPName,\r
1654 ISCSI_CHAP_NAME_STORAGE\r
1655 );\r
1656\r
1657 if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
1658 if (IfrNvData->Keyword[Index].ISCSIChapUsername[0] == L'\0') {\r
1659 CreatePopUp (\r
1660 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1661 &Key,\r
1662 L"CHAP Name is invalid!",\r
1663 NULL\r
1664 );\r
1665 return EFI_INVALID_PARAMETER;\r
1666 }\r
1667 }\r
1668 } else {\r
1669 CreatePopUp (\r
1670 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1671 &Key,\r
1672 L"Invalid Configuration, Check value of AuthenticationType!",\r
1673 NULL\r
1674 );\r
1675 return EFI_INVALID_PARAMETER;\r
1676 }\r
1677 } else if ((OffSet >= ATTEMPT_CHAR_SECRET_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET)) {\r
1678 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
1679 ChapSecretLen = (UINT8)StrLen (IfrNvData->Keyword[Index].ISCSIChapSecret);\r
1680 UnicodeStrToAsciiStrS (\r
1681 IfrNvData->Keyword[Index].ISCSIChapSecret,\r
1682 Attempt->AuthConfigData.CHAP.CHAPSecret,\r
1683 ISCSI_CHAP_SECRET_STORAGE\r
1684 );\r
1685\r
1686 if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
1687 if ((ChapSecretLen < ISCSI_CHAP_SECRET_MIN_LEN) || (ChapSecretLen > ISCSI_CHAP_SECRET_MAX_LEN)) {\r
1688 CreatePopUp (\r
1689 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1690 &Key,\r
1691 L"The Chap Secret minimum length is 12 bytes and the maximum length is 16 bytes.",\r
1692 NULL\r
1693 );\r
1694 return EFI_INVALID_PARAMETER;\r
1695 }\r
1696 }\r
1697 } else {\r
1698 CreatePopUp (\r
1699 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1700 &Key,\r
1701 L"Invalid Configuration, Check value of AuthenticationType!",\r
1702 NULL\r
1703 );\r
1704 return EFI_INVALID_PARAMETER;\r
1705 }\r
1706 } else if ((OffSet >= ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET)) {\r
1707 if (Attempt->AuthConfigData.CHAP.CHAPType == ISCSI_CHAP_MUTUAL) {\r
1708 UnicodeStrToAsciiStrS (\r
1709 IfrNvData->Keyword[Index].ISCSIReverseChapUsername,\r
1710 Attempt->AuthConfigData.CHAP.ReverseCHAPName,\r
1711 ISCSI_CHAP_NAME_STORAGE\r
1712 );\r
1713 if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
1714 if (IfrNvData->Keyword[Index].ISCSIReverseChapUsername[0] == L'\0') {\r
1715 CreatePopUp (\r
1716 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1717 &Key,\r
1718 L"Reverse CHAP Name is invalid!",\r
1719 NULL\r
1720 );\r
1721 return EFI_INVALID_PARAMETER;\r
1722 }\r
1723 }\r
1724 } else {\r
1725 CreatePopUp (\r
1726 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1727 &Key,\r
1728 L"Invalid Configuration, Check value of AuthenticationType or Chap Type!",\r
1729 NULL\r
1730 );\r
1731 return EFI_INVALID_PARAMETER;\r
1732 }\r
1733 } else if (OffSet >= ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET) {\r
1734 if (Attempt->AuthConfigData.CHAP.CHAPType == ISCSI_CHAP_MUTUAL) {\r
1735 ReverseChapSecretLen = (UINT8)StrLen (IfrNvData->Keyword[Index].ISCSIReverseChapSecret);\r
1736 UnicodeStrToAsciiStrS (\r
1737 IfrNvData->Keyword[Index].ISCSIReverseChapSecret,\r
1738 Attempt->AuthConfigData.CHAP.ReverseCHAPSecret,\r
1739 ISCSI_CHAP_SECRET_STORAGE\r
1740 );\r
1741\r
1742 if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
1743 if ((ReverseChapSecretLen < ISCSI_CHAP_SECRET_MIN_LEN) || (ReverseChapSecretLen > ISCSI_CHAP_SECRET_MAX_LEN)) {\r
1744 CreatePopUp (\r
1745 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1746 &Key,\r
1747 L"The Reverse CHAP Secret minimum length is 12 bytes and the maximum length is 16 bytes.",\r
1748 NULL\r
1749 );\r
1750 return EFI_INVALID_PARAMETER;\r
1751 }\r
1752 }\r
1753 } else {\r
1754 CreatePopUp (\r
1755 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1756 &Key,\r
1757 L"Invalid Configuration, Check value of AuthenticationType or Chap Type!",\r
1758 NULL\r
1759 );\r
1760 return EFI_INVALID_PARAMETER;\r
1761 }\r
1762 }\r
1763 }\r
1764\r
1765 //\r
1766 // Record the user configuration information in NVR.\r
1767 //\r
1768 ASSERT (Attempt != NULL);\r
1769 UnicodeSPrint (mPrivate->PortString, (UINTN)ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", Attempt->AttemptConfigIndex);\r
1770 return gRT->SetVariable (\r
1771 mPrivate->PortString,\r
1772 &gEfiIScsiInitiatorNameProtocolGuid,\r
1773 ISCSI_CONFIG_VAR_ATTR,\r
1774 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
1775 Attempt\r
1776 );\r
1777}\r
1778\r
1779/**\r
1780 Create Hii Extend Label OpCode as the start opcode and end opcode. It is\r
1781 a help function.\r
1782\r
1783 @param[in] StartLabelNumber The number of start label.\r
1784 @param[out] StartOpCodeHandle Points to the start opcode handle.\r
1785 @param[out] StartLabel Points to the created start opcode.\r
1786 @param[out] EndOpCodeHandle Points to the end opcode handle.\r
1787 @param[out] EndLabel Points to the created end opcode.\r
1788\r
1789 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this\r
1790 operation.\r
1791 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
1792 @retval EFI_SUCCESS The operation is completed successfully.\r
1793\r
1794**/\r
1795EFI_STATUS\r
1796IScsiCreateOpCode (\r
1797 IN UINT16 StartLabelNumber,\r
1798 OUT VOID **StartOpCodeHandle,\r
1799 OUT EFI_IFR_GUID_LABEL **StartLabel,\r
1800 OUT VOID **EndOpCodeHandle,\r
1801 OUT EFI_IFR_GUID_LABEL **EndLabel\r
1802 )\r
1803{\r
1804 EFI_STATUS Status;\r
1805 EFI_IFR_GUID_LABEL *InternalStartLabel;\r
1806 EFI_IFR_GUID_LABEL *InternalEndLabel;\r
1807\r
1808 if ((StartOpCodeHandle == NULL) || (StartLabel == NULL) || (EndOpCodeHandle == NULL) || (EndLabel == NULL)) {\r
1809 return EFI_INVALID_PARAMETER;\r
1810 }\r
1811\r
1812 *StartOpCodeHandle = NULL;\r
1813 *EndOpCodeHandle = NULL;\r
1814 Status = EFI_OUT_OF_RESOURCES;\r
1815\r
1816 //\r
1817 // Initialize the container for dynamic opcodes.\r
1818 //\r
1819 *StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1820 if (*StartOpCodeHandle == NULL) {\r
1821 return Status;\r
1822 }\r
1823\r
1824 *EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1825 if (*EndOpCodeHandle == NULL) {\r
1826 goto Exit;\r
1827 }\r
1828\r
1829 //\r
1830 // Create Hii Extend Label OpCode as the start opcode.\r
1831 //\r
1832 InternalStartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (\r
1833 *StartOpCodeHandle,\r
1834 &gEfiIfrTianoGuid,\r
1835 NULL,\r
1836 sizeof (EFI_IFR_GUID_LABEL)\r
1837 );\r
1838 if (InternalStartLabel == NULL) {\r
1839 goto Exit;\r
1840 }\r
1841\r
1842 InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1843 InternalStartLabel->Number = StartLabelNumber;\r
1844\r
1845 //\r
1846 // Create Hii Extend Label OpCode as the end opcode.\r
1847 //\r
1848 InternalEndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (\r
1849 *EndOpCodeHandle,\r
1850 &gEfiIfrTianoGuid,\r
1851 NULL,\r
1852 sizeof (EFI_IFR_GUID_LABEL)\r
1853 );\r
1854 if (InternalEndLabel == NULL) {\r
1855 goto Exit;\r
1856 }\r
1857\r
1858 InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1859 InternalEndLabel->Number = LABEL_END;\r
1860\r
1861 *StartLabel = InternalStartLabel;\r
1862 *EndLabel = InternalEndLabel;\r
1863\r
1864 return EFI_SUCCESS;\r
1865\r
1866Exit:\r
1867\r
1868 if (*StartOpCodeHandle != NULL) {\r
1869 HiiFreeOpCodeHandle (*StartOpCodeHandle);\r
1870 }\r
1871\r
1872 if (*EndOpCodeHandle != NULL) {\r
1873 HiiFreeOpCodeHandle (*EndOpCodeHandle);\r
1874 }\r
1875\r
1876 return Status;\r
1877}\r
1878\r
1879/**\r
1880 Update the MAIN form to display the configured attempts.\r
1881\r
1882**/\r
1883VOID\r
1884IScsiConfigUpdateAttempt (\r
1885 VOID\r
1886 )\r
1887{\r
1888 LIST_ENTRY *Entry;\r
1889 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
1890 VOID *StartOpCodeHandle;\r
1891 EFI_IFR_GUID_LABEL *StartLabel;\r
1892 VOID *EndOpCodeHandle;\r
1893 EFI_IFR_GUID_LABEL *EndLabel;\r
1894 EFI_STATUS Status;\r
1895\r
1896 Status = IScsiCreateOpCode (\r
1897 ATTEMPT_ENTRY_LABEL,\r
1898 &StartOpCodeHandle,\r
1899 &StartLabel,\r
1900 &EndOpCodeHandle,\r
1901 &EndLabel\r
1902 );\r
1903 if (EFI_ERROR (Status)) {\r
1904 return;\r
1905 }\r
1906\r
1907 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
1908 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
1909 if (AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED) {\r
1910 //\r
1911 // Update Attempt Help Info.\r
1912 //\r
1913 UnicodeSPrint (mPrivate->PortString, (UINTN)ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", (UINTN)AttemptConfigData->AttemptConfigIndex);\r
1914 AttemptConfigData->AttemptTitleToken = HiiSetString (\r
1915 mCallbackInfo->RegisteredHandle,\r
1916 0,\r
1917 mPrivate->PortString,\r
1918 NULL\r
1919 );\r
1920 if (AttemptConfigData->AttemptTitleToken == 0) {\r
1921 return;\r
1922 }\r
1923\r
1924 HiiCreateGotoOpCode (\r
1925 StartOpCodeHandle, // Container for dynamic created opcodes\r
1926 FORMID_ATTEMPT_FORM, // Form ID\r
1927 AttemptConfigData->AttemptTitleToken, // Prompt text\r
1928 AttemptConfigData->AttemptTitleHelpToken, // Help text\r
1929 EFI_IFR_FLAG_CALLBACK, // Question flag\r
1930 (UINT16)(KEY_ATTEMPT_ENTRY_BASE + AttemptConfigData->AttemptConfigIndex) // Question ID\r
1931 );\r
1932 }\r
1933 }\r
1934\r
1935 HiiUpdateForm (\r
1936 mCallbackInfo->RegisteredHandle, // HII handle\r
1937 &gIScsiConfigGuid, // Formset GUID\r
1938 FORMID_MAIN_FORM, // Form ID\r
1939 StartOpCodeHandle, // Label for where to insert opcodes\r
1940 EndOpCodeHandle // Replace data\r
1941 );\r
1942\r
1943 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1944 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1945}\r
1946\r
1947/**\r
1948 Callback function when user presses "Add an Attempt".\r
1949\r
1950 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this\r
1951 operation.\r
1952 @retval EFI_SUCCESS The operation is completed successfully.\r
1953\r
1954**/\r
1955EFI_STATUS\r
1956IScsiConfigAddAttempt (\r
1957 VOID\r
1958 )\r
1959{\r
1960 LIST_ENTRY *Entry;\r
1961 ISCSI_NIC_INFO *NicInfo;\r
1962 EFI_STRING_ID PortTitleToken;\r
1963 EFI_STRING_ID PortTitleHelpToken;\r
1964 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
1965 EFI_STATUS Status;\r
1966 VOID *StartOpCodeHandle;\r
1967 EFI_IFR_GUID_LABEL *StartLabel;\r
1968 VOID *EndOpCodeHandle;\r
1969 EFI_IFR_GUID_LABEL *EndLabel;\r
1970\r
1971 Status = IScsiCreateOpCode (\r
1972 MAC_ENTRY_LABEL,\r
1973 &StartOpCodeHandle,\r
1974 &StartLabel,\r
1975 &EndOpCodeHandle,\r
1976 &EndLabel\r
1977 );\r
1978 if (EFI_ERROR (Status)) {\r
1979 return Status;\r
1980 }\r
1981\r
1982 //\r
1983 // Ask user to select a MAC for this attempt.\r
1984 //\r
1985 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
1986 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
1987 IScsiMacAddrToStr (\r
1988 &NicInfo->PermanentAddress,\r
1989 NicInfo->HwAddressSize,\r
1990 NicInfo->VlanId,\r
1991 MacString\r
1992 );\r
1993\r
1994 UnicodeSPrint (mPrivate->PortString, (UINTN)ISCSI_NAME_IFR_MAX_SIZE, L"MAC %s", MacString);\r
1995 PortTitleToken = HiiSetString (\r
1996 mCallbackInfo->RegisteredHandle,\r
1997 0,\r
1998 mPrivate->PortString,\r
1999 NULL\r
2000 );\r
2001 if (PortTitleToken == 0) {\r
2002 Status = EFI_INVALID_PARAMETER;\r
2003 goto Exit;\r
2004 }\r
2005\r
2006 UnicodeSPrint (\r
2007 mPrivate->PortString,\r
2008 (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
2009 L"PFA: Bus %d | Dev %d | Func %d",\r
2010 NicInfo->BusNumber,\r
2011 NicInfo->DeviceNumber,\r
2012 NicInfo->FunctionNumber\r
2013 );\r
2014 PortTitleHelpToken = HiiSetString (mCallbackInfo->RegisteredHandle, 0, mPrivate->PortString, NULL);\r
2015 if (PortTitleHelpToken == 0) {\r
2016 Status = EFI_INVALID_PARAMETER;\r
2017 goto Exit;\r
2018 }\r
2019\r
2020 HiiCreateGotoOpCode (\r
2021 StartOpCodeHandle, // Container for dynamic created opcodes\r
2022 FORMID_ATTEMPT_FORM,\r
2023 PortTitleToken,\r
2024 PortTitleHelpToken,\r
2025 EFI_IFR_FLAG_CALLBACK, // Question flag\r
2026 (UINT16)(KEY_MAC_ENTRY_BASE + NicInfo->NicIndex)\r
2027 );\r
2028 }\r
2029\r
2030 Status = HiiUpdateForm (\r
2031 mCallbackInfo->RegisteredHandle, // HII handle\r
2032 &gIScsiConfigGuid, // Formset GUID\r
2033 FORMID_MAC_FORM, // Form ID\r
2034 StartOpCodeHandle, // Label for where to insert opcodes\r
2035 EndOpCodeHandle // Replace data\r
2036 );\r
2037\r
2038Exit:\r
2039 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
2040 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
2041\r
2042 return Status;\r
2043}\r
2044\r
2045/**\r
2046 Add the attempts by keyword 'iSCSIAddAttempts', you can use this keyword with\r
2047 value 'attempt:1 attempt:2' etc to add one or more attempts once. This is different\r
2048 with IScsiConfigAddAttempt function which is used to add attempt by UI configuration.\r
2049\r
2050 @param[in] AttemptList The new attempt List will be added.\r
2051\r
2052 @retval EFI_SUCCESS The operation to add attempt list successfully.\r
2053 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
2054 @retval EFI_NOT_FOUND Cannot find the corresponding variable.\r
2055 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of\r
2056 resources.\r
2057\r
2058**/\r
2059EFI_STATUS\r
2060IScsiConfigAddAttemptsByKeywords (\r
2061 IN UINT8 *AttemptList\r
2062 )\r
2063{\r
2064 UINT8 Index;\r
2065 UINT8 Number;\r
2066 UINTN TotalNumber;\r
2067 UINT8 Nic;\r
2068 UINT8 *AttemptConfigOrder;\r
2069 UINTN AttemptConfigOrderSize;\r
2070 UINT8 *AttemptConfigOrderTmp;\r
2071 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
2072 ISCSI_NIC_INFO *NicInfo;\r
2073 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
2074 CHAR16 IScsiMode[64];\r
2075 CHAR16 IpMode[64];\r
2076 EFI_STATUS Status;\r
2077\r
2078 Nic = mPrivate->CurrentNic;\r
2079 NicInfo = IScsiGetNicInfoByIndex (Nic);\r
2080 if (NicInfo == NULL) {\r
2081 return EFI_NOT_FOUND;\r
2082 }\r
2083\r
2084 //\r
2085 // The MAC info will be recorded in Config Data.\r
2086 //\r
2087 IScsiMacAddrToStr (\r
2088 &NicInfo->PermanentAddress,\r
2089 NicInfo->HwAddressSize,\r
2090 NicInfo->VlanId,\r
2091 MacString\r
2092 );\r
2093\r
2094 for (Index = 0; Index < PcdGet8 (PcdMaxIScsiAttemptNumber); Index++) {\r
2095 if (AttemptList[Index] == 0) {\r
2096 continue;\r
2097 }\r
2098\r
2099 //\r
2100 // Add the attempt.\r
2101 //\r
2102 Number = AttemptList[Index];\r
2103\r
2104 UnicodeSPrint (\r
2105 mPrivate->PortString,\r
2106 (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
2107 L"Attempt %d",\r
2108 Number\r
2109 );\r
2110\r
2111 GetVariable2 (\r
2112 mPrivate->PortString,\r
2113 &gEfiIScsiInitiatorNameProtocolGuid,\r
2114 (VOID **)&AttemptConfigData,\r
2115 NULL\r
2116 );\r
2117 if ((AttemptConfigData == NULL) || (AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED)) {\r
2118 return EFI_INVALID_PARAMETER;\r
2119 }\r
2120\r
2121 AttemptConfigData->Actived = ISCSI_ACTIVE_ENABLED;\r
2122 AttemptConfigData->NicIndex = NicInfo->NicIndex;\r
2123 UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, ISCSI_MAX_MAC_STRING_LEN);\r
2124\r
2125 //\r
2126 // Generate OUI-format ISID based on MAC address.\r
2127 //\r
2128 CopyMem (AttemptConfigData->SessionConfigData.IsId, &NicInfo->PermanentAddress, 6);\r
2129 AttemptConfigData->SessionConfigData.IsId[0] =\r
2130 (UINT8)(AttemptConfigData->SessionConfigData.IsId[0] & 0x3F);\r
2131\r
2132 //\r
2133 // Configure the iSCSI Mode and IpMode to default.\r
2134 // Add Attempt Help Info.\r
2135 //\r
2136 UnicodeSPrint (IScsiMode, 64, L"Disabled");\r
2137 UnicodeSPrint (IpMode, 64, L"IP4");\r
2138 UnicodeSPrint (\r
2139 mPrivate->PortString,\r
2140 (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
2141 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",\r
2142 MacString,\r
2143 NicInfo->BusNumber,\r
2144 NicInfo->DeviceNumber,\r
2145 NicInfo->FunctionNumber,\r
2146 IScsiMode,\r
2147 IpMode\r
2148 );\r
2149\r
2150 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (\r
2151 mCallbackInfo->RegisteredHandle,\r
2152 0,\r
2153 mPrivate->PortString,\r
2154 NULL\r
2155 );\r
2156 if (AttemptConfigData->AttemptTitleHelpToken == 0) {\r
2157 return EFI_OUT_OF_RESOURCES;\r
2158 }\r
2159\r
2160 //\r
2161 // Get current Attempt order and number.\r
2162 //\r
2163 AttemptConfigOrder = IScsiGetVariableAndSize (\r
2164 L"AttemptOrder",\r
2165 &gIScsiConfigGuid,\r
2166 &AttemptConfigOrderSize\r
2167 );\r
2168 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);\r
2169 TotalNumber++;\r
2170\r
2171 //\r
2172 // Append the new created attempt order to the end.\r
2173 //\r
2174 AttemptConfigOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));\r
2175 if (AttemptConfigOrderTmp == NULL) {\r
2176 if (AttemptConfigOrder != NULL) {\r
2177 FreePool (AttemptConfigOrder);\r
2178 }\r
2179\r
2180 return EFI_OUT_OF_RESOURCES;\r
2181 }\r
2182\r
2183 if (AttemptConfigOrder != NULL) {\r
2184 CopyMem (AttemptConfigOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);\r
2185 FreePool (AttemptConfigOrder);\r
2186 }\r
2187\r
2188 AttemptConfigOrderTmp[TotalNumber - 1] = Number;\r
2189 AttemptConfigOrder = AttemptConfigOrderTmp;\r
2190 AttemptConfigOrderSize = TotalNumber * sizeof (UINT8);\r
2191\r
2192 Status = gRT->SetVariable (\r
2193 L"AttemptOrder",\r
2194 &gIScsiConfigGuid,\r
2195 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
2196 AttemptConfigOrderSize,\r
2197 AttemptConfigOrder\r
2198 );\r
2199 FreePool (AttemptConfigOrder);\r
2200 if (EFI_ERROR (Status)) {\r
2201 return Status;\r
2202 }\r
2203\r
2204 //\r
2205 // Record the attempt in global link list.\r
2206 //\r
2207 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);\r
2208 mPrivate->AttemptCount++;\r
2209 UnicodeSPrint (mPrivate->PortString, (UINTN)ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", AttemptConfigData->AttemptConfigIndex);\r
2210 gRT->SetVariable (\r
2211 mPrivate->PortString,\r
2212 &gEfiIScsiInitiatorNameProtocolGuid,\r
2213 ISCSI_CONFIG_VAR_ATTR,\r
2214 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
2215 AttemptConfigData\r
2216 );\r
2217 }\r
2218\r
2219 return EFI_SUCCESS;\r
2220}\r
2221\r
2222/**\r
2223 Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword.\r
2224\r
2225 @param[in] IfrNvData The IFR NV data.\r
2226\r
2227 @retval EFI_NOT_FOUND Cannot find the corresponding variable.\r
2228 @retval EFI_SUCCESS The operation is completed successfully.\r
2229 @retval EFI_ABORTED This operation is aborted cause of error\r
2230 configuration.\r
2231 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of\r
2232 resources.\r
2233\r
2234**/\r
2235EFI_STATUS\r
2236IScsiConfigDeleteAttempts (\r
2237 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
2238 )\r
2239{\r
2240 EFI_STATUS Status;\r
2241 UINTN Index;\r
2242 UINTN NewIndex;\r
2243 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
2244 UINT8 *AttemptConfigOrder;\r
2245 UINTN AttemptConfigOrderSize;\r
2246 UINT8 *AttemptNewOrder;\r
2247 UINT8 AttemptConfigIndex;\r
2248 UINT32 Attribute;\r
2249 UINTN Total;\r
2250 UINTN NewTotal;\r
2251 LIST_ENTRY *Entry;\r
2252 LIST_ENTRY *NextEntry;\r
2253 ISCSI_SESSION_CONFIG_NVDATA *ConfigData;\r
2254\r
2255 Index = 0;\r
2256\r
2257 AttemptConfigOrder = IScsiGetVariableAndSize (\r
2258 L"AttemptOrder",\r
2259 &gIScsiConfigGuid,\r
2260 &AttemptConfigOrderSize\r
2261 );\r
2262 if ((AttemptConfigOrder == NULL) || (AttemptConfigOrderSize == 0)) {\r
2263 return EFI_NOT_FOUND;\r
2264 }\r
2265\r
2266 AttemptNewOrder = AllocateZeroPool (AttemptConfigOrderSize);\r
2267 if (AttemptNewOrder == NULL) {\r
2268 Status = EFI_OUT_OF_RESOURCES;\r
2269 goto Error;\r
2270 }\r
2271\r
2272 Total = AttemptConfigOrderSize / sizeof (UINT8);\r
2273 NewTotal = Total;\r
2274\r
2275 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {\r
2276 if (IfrNvData->DeleteAttemptList[Index] == 0) {\r
2277 Index++;\r
2278 continue;\r
2279 }\r
2280\r
2281 //\r
2282 // Delete the attempt.\r
2283 //\r
2284\r
2285 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
2286\r
2287 //\r
2288 // Remove this attempt from UI configured attempt list.\r
2289 //\r
2290 RemoveEntryList (&AttemptConfigData->Link);\r
2291 mPrivate->AttemptCount--;\r
2292\r
2293 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
2294 if (mPrivate->MpioCount < 1) {\r
2295 Status = EFI_ABORTED;\r
2296 goto Error;\r
2297 }\r
2298\r
2299 //\r
2300 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.\r
2301 //\r
2302 if (--mPrivate->MpioCount == 0) {\r
2303 mPrivate->EnableMpio = FALSE;\r
2304 }\r
2305 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
2306 if (mPrivate->SinglePathCount < 1) {\r
2307 Status = EFI_ABORTED;\r
2308 goto Error;\r
2309 }\r
2310\r
2311 mPrivate->SinglePathCount--;\r
2312 }\r
2313\r
2314 AttemptConfigIndex = AttemptConfigData->AttemptConfigIndex;\r
2315 FreePool (AttemptConfigData);\r
2316\r
2317 //\r
2318 // Create a new Attempt\r
2319 //\r
2320 AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA));\r
2321 if (AttemptConfigData == NULL) {\r
2322 return EFI_OUT_OF_RESOURCES;\r
2323 }\r
2324\r
2325 ConfigData = &AttemptConfigData->SessionConfigData;\r
2326 ConfigData->TargetPort = ISCSI_WELL_KNOWN_PORT;\r
2327 ConfigData->ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;\r
2328 ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY;\r
2329\r
2330 AttemptConfigData->AuthenticationType = ISCSI_AUTH_TYPE_CHAP;\r
2331 AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI;\r
2332 //\r
2333 // Configure the Attempt index and set variable.\r
2334 //\r
2335 AttemptConfigData->AttemptConfigIndex = AttemptConfigIndex;\r
2336\r
2337 //\r
2338 // Set the attempt name to default.\r
2339 //\r
2340 UnicodeSPrint (\r
2341 mPrivate->PortString,\r
2342 (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
2343 L"Attempt %d",\r
2344 (UINTN)AttemptConfigData->AttemptConfigIndex\r
2345 );\r
2346 UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, ATTEMPT_NAME_SIZE);\r
2347 gRT->SetVariable (\r
2348 mPrivate->PortString,\r
2349 &gEfiIScsiInitiatorNameProtocolGuid,\r
2350 ISCSI_CONFIG_VAR_ATTR,\r
2351 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
2352 AttemptConfigData\r
2353 );\r
2354\r
2355 //\r
2356 // Mark the attempt order in NVR to be deleted - 0.\r
2357 //\r
2358 for (NewIndex = 0; NewIndex < Total; NewIndex++) {\r
2359 if (AttemptConfigOrder[NewIndex] == AttemptConfigData->AttemptConfigIndex) {\r
2360 AttemptConfigOrder[NewIndex] = 0;\r
2361 break;\r
2362 }\r
2363 }\r
2364\r
2365 NewTotal--;\r
2366 if (mCallbackInfo->Current == AttemptConfigData) {\r
2367 mCallbackInfo->Current = NULL;\r
2368 }\r
2369\r
2370 FreePool (AttemptConfigData);\r
2371\r
2372 //\r
2373 // Check next Attempt.\r
2374 //\r
2375 Index++;\r
2376 }\r
2377\r
2378 //\r
2379 // Construct AttemptNewOrder.\r
2380 //\r
2381 for (Index = 0, NewIndex = 0; Index < Total; Index++) {\r
2382 if (AttemptConfigOrder[Index] != 0) {\r
2383 AttemptNewOrder[NewIndex] = AttemptConfigOrder[Index];\r
2384 NewIndex++;\r
2385 }\r
2386 }\r
2387\r
2388 Attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
2389\r
2390 //\r
2391 // Update AttemptOrder in NVR.\r
2392 //\r
2393 Status = gRT->SetVariable (\r
2394 L"AttemptOrder",\r
2395 &gIScsiConfigGuid,\r
2396 Attribute,\r
2397 NewTotal * sizeof (UINT8),\r
2398 AttemptNewOrder\r
2399 );\r
2400\r
2401Error:\r
2402 if (AttemptConfigOrder != NULL) {\r
2403 FreePool (AttemptConfigOrder);\r
2404 }\r
2405\r
2406 if (AttemptNewOrder != NULL) {\r
2407 FreePool (AttemptNewOrder);\r
2408 }\r
2409\r
2410 return Status;\r
2411}\r
2412\r
2413/**\r
2414 Callback function when user presses "Delete Attempts".\r
2415\r
2416 @param[in] IfrNvData The IFR nv data.\r
2417\r
2418 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
2419 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.\r
2420 @retval EFI_SUCCESS The operation is completed successfully.\r
2421\r
2422**/\r
2423EFI_STATUS\r
2424IScsiConfigDisplayDeleteAttempts (\r
2425 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
2426 )\r
2427{\r
2428 UINT8 *AttemptConfigOrder;\r
2429 UINTN AttemptConfigOrderSize;\r
2430 LIST_ENTRY *Entry;\r
2431 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
2432 UINT8 Index;\r
2433 VOID *StartOpCodeHandle;\r
2434 EFI_IFR_GUID_LABEL *StartLabel;\r
2435 VOID *EndOpCodeHandle;\r
2436 EFI_IFR_GUID_LABEL *EndLabel;\r
2437 EFI_STATUS Status;\r
2438\r
2439 Status = IScsiCreateOpCode (\r
2440 DELETE_ENTRY_LABEL,\r
2441 &StartOpCodeHandle,\r
2442 &StartLabel,\r
2443 &EndOpCodeHandle,\r
2444 &EndLabel\r
2445 );\r
2446 if (EFI_ERROR (Status)) {\r
2447 return Status;\r
2448 }\r
2449\r
2450 AttemptConfigOrder = IScsiGetVariableAndSize (\r
2451 L"AttemptOrder",\r
2452 &gIScsiConfigGuid,\r
2453 &AttemptConfigOrderSize\r
2454 );\r
2455 if (AttemptConfigOrder != NULL) {\r
2456 //\r
2457 // Create the check box opcode to be deleted.\r
2458 //\r
2459 Index = 0;\r
2460\r
2461 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
2462 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
2463 IfrNvData->DeleteAttemptList[Index] = 0x00;\r
2464\r
2465 HiiCreateCheckBoxOpCode (\r
2466 StartOpCodeHandle,\r
2467 (EFI_QUESTION_ID)(ATTEMPT_DEL_QUESTION_ID + Index),\r
2468 CONFIGURATION_VARSTORE_ID,\r
2469 (UINT16)(ATTEMPT_DEL_VAR_OFFSET + Index),\r
2470 AttemptConfigData->AttemptTitleToken,\r
2471 AttemptConfigData->AttemptTitleHelpToken,\r
2472 0,\r
2473 0,\r
2474 NULL\r
2475 );\r
2476\r
2477 Index++;\r
2478\r
2479 if (Index == ISCSI_MAX_ATTEMPTS_NUM) {\r
2480 break;\r
2481 }\r
2482 }\r
2483\r
2484 FreePool (AttemptConfigOrder);\r
2485 }\r
2486\r
2487 Status = HiiUpdateForm (\r
2488 mCallbackInfo->RegisteredHandle, // HII handle\r
2489 &gIScsiConfigGuid, // Formset GUID\r
2490 FORMID_DELETE_FORM, // Form ID\r
2491 StartOpCodeHandle, // Label for where to insert opcodes\r
2492 EndOpCodeHandle // Replace data\r
2493 );\r
2494\r
2495 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
2496 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
2497\r
2498 return Status;\r
2499}\r
2500\r
2501/**\r
2502 Callback function when user presses "Change Attempt Order".\r
2503\r
2504 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
2505 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this\r
2506 operation.\r
2507 @retval EFI_SUCCESS The operation is completed successfully.\r
2508\r
2509**/\r
2510EFI_STATUS\r
2511IScsiConfigDisplayOrderAttempts (\r
2512 VOID\r
2513 )\r
2514{\r
2515 EFI_STATUS Status;\r
2516 UINT8 Index;\r
2517 LIST_ENTRY *Entry;\r
2518 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
2519 VOID *StartOpCodeHandle;\r
2520 EFI_IFR_GUID_LABEL *StartLabel;\r
2521 VOID *EndOpCodeHandle;\r
2522 EFI_IFR_GUID_LABEL *EndLabel;\r
2523 VOID *OptionsOpCodeHandle;\r
2524\r
2525 Status = IScsiCreateOpCode (\r
2526 ORDER_ENTRY_LABEL,\r
2527 &StartOpCodeHandle,\r
2528 &StartLabel,\r
2529 &EndOpCodeHandle,\r
2530 &EndLabel\r
2531 );\r
2532 if (EFI_ERROR (Status)) {\r
2533 return Status;\r
2534 }\r
2535\r
2536 ASSERT (StartOpCodeHandle != NULL);\r
2537\r
2538 OptionsOpCodeHandle = NULL;\r
2539\r
2540 //\r
2541 // If no attempt to be ordered, update the original form and exit.\r
2542 //\r
2543 if (mPrivate->AttemptCount == 0) {\r
2544 goto Exit;\r
2545 }\r
2546\r
2547 //\r
2548 // Create Option OpCode.\r
2549 //\r
2550 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2551 if (OptionsOpCodeHandle == NULL) {\r
2552 Status = EFI_OUT_OF_RESOURCES;\r
2553 goto Error;\r
2554 }\r
2555\r
2556 Index = 0;\r
2557\r
2558 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
2559 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
2560 HiiCreateOneOfOptionOpCode (\r
2561 OptionsOpCodeHandle,\r
2562 AttemptConfigData->AttemptTitleToken,\r
2563 0,\r
2564 EFI_IFR_NUMERIC_SIZE_1,\r
2565 AttemptConfigData->AttemptConfigIndex\r
2566 );\r
2567 Index++;\r
2568 }\r
2569\r
2570 ASSERT (Index == mPrivate->AttemptCount);\r
2571\r
2572 HiiCreateOrderedListOpCode (\r
2573 StartOpCodeHandle, // Container for dynamic created opcodes\r
2574 DYNAMIC_ORDERED_LIST_QUESTION_ID, // Question ID\r
2575 CONFIGURATION_VARSTORE_ID, // VarStore ID\r
2576 DYNAMIC_ORDERED_LIST_VAR_OFFSET, // Offset in Buffer Storage\r
2577 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY), // Question prompt text\r
2578 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY), // Question help text\r
2579 0, // Question flag\r
2580 EFI_IFR_UNIQUE_SET, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET\r
2581 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question value\r
2582 ISCSI_MAX_ATTEMPTS_NUM, // Maximum container\r
2583 OptionsOpCodeHandle, // Option Opcode list\r
2584 NULL // Default Opcode is NULL\r
2585 );\r
2586\r
2587Exit:\r
2588 Status = HiiUpdateForm (\r
2589 mCallbackInfo->RegisteredHandle, // HII handle\r
2590 &gIScsiConfigGuid, // Formset GUID\r
2591 FORMID_ORDER_FORM, // Form ID\r
2592 StartOpCodeHandle, // Label for where to insert opcodes\r
2593 EndOpCodeHandle // Replace data\r
2594 );\r
2595\r
2596Error:\r
2597 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
2598 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
2599 if (OptionsOpCodeHandle != NULL) {\r
2600 HiiFreeOpCodeHandle (OptionsOpCodeHandle);\r
2601 }\r
2602\r
2603 return Status;\r
2604}\r
2605\r
2606/**\r
2607 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.\r
2608\r
2609 @param[in] IfrNvData The IFR nv data.\r
2610\r
2611 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this\r
2612 operation.\r
2613 @retval EFI_NOT_FOUND Cannot find the corresponding variable.\r
2614 @retval EFI_SUCCESS The operation is completed successfully.\r
2615\r
2616**/\r
2617EFI_STATUS\r
2618IScsiConfigOrderAttempts (\r
2619 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
2620 )\r
2621{\r
2622 EFI_STATUS Status;\r
2623 UINTN Index;\r
2624 UINTN Indexj;\r
2625 UINT8 AttemptConfigIndex;\r
2626 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
2627 UINT8 *AttemptConfigOrder;\r
2628 UINT8 *AttemptConfigOrderTmp;\r
2629 UINTN AttemptConfigOrderSize;\r
2630\r
2631 AttemptConfigOrder = IScsiGetVariableAndSize (\r
2632 L"AttemptOrder",\r
2633 &gIScsiConfigGuid,\r
2634 &AttemptConfigOrderSize\r
2635 );\r
2636 if (AttemptConfigOrder == NULL) {\r
2637 return EFI_NOT_FOUND;\r
2638 }\r
2639\r
2640 AttemptConfigOrderTmp = AllocateZeroPool (AttemptConfigOrderSize);\r
2641 if (AttemptConfigOrderTmp == NULL) {\r
2642 Status = EFI_OUT_OF_RESOURCES;\r
2643 goto Exit;\r
2644 }\r
2645\r
2646 for (Index = 0; Index < ISCSI_MAX_ATTEMPTS_NUM; Index++) {\r
2647 //\r
2648 // The real content ends with 0.\r
2649 //\r
2650 if (IfrNvData->DynamicOrderedList[Index] == 0) {\r
2651 break;\r
2652 }\r
2653\r
2654 AttemptConfigIndex = IfrNvData->DynamicOrderedList[Index];\r
2655 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex);\r
2656 if (AttemptConfigData == NULL) {\r
2657 Status = EFI_NOT_FOUND;\r
2658 goto Exit;\r
2659 }\r
2660\r
2661 //\r
2662 // Reorder the Attempt List.\r
2663 //\r
2664 RemoveEntryList (&AttemptConfigData->Link);\r
2665 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);\r
2666\r
2667 AttemptConfigOrderTmp[Index] = AttemptConfigIndex;\r
2668\r
2669 //\r
2670 // Mark it to be deleted - 0.\r
2671 //\r
2672 for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) {\r
2673 if (AttemptConfigOrder[Indexj] == AttemptConfigIndex) {\r
2674 AttemptConfigOrder[Indexj] = 0;\r
2675 break;\r
2676 }\r
2677 }\r
2678 }\r
2679\r
2680 //\r
2681 // Adjust the attempt order in NVR.\r
2682 //\r
2683 for ( ; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
2684 for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) {\r
2685 if (AttemptConfigOrder[Indexj] != 0) {\r
2686 AttemptConfigOrderTmp[Index] = AttemptConfigOrder[Indexj];\r
2687 AttemptConfigOrder[Indexj] = 0;\r
2688 continue;\r
2689 }\r
2690 }\r
2691 }\r
2692\r
2693 Status = gRT->SetVariable (\r
2694 L"AttemptOrder",\r
2695 &gIScsiConfigGuid,\r
2696 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
2697 AttemptConfigOrderSize,\r
2698 AttemptConfigOrderTmp\r
2699 );\r
2700\r
2701Exit:\r
2702 if (AttemptConfigOrderTmp != NULL) {\r
2703 FreePool (AttemptConfigOrderTmp);\r
2704 }\r
2705\r
2706 FreePool (AttemptConfigOrder);\r
2707 return Status;\r
2708}\r
2709\r
2710/**\r
2711 Callback function when a user presses "Attempt *" or when a user selects a NIC to\r
2712 create the new attempt.\r
2713\r
2714 @param[in] KeyValue A unique value which is sent to the original\r
2715 exporting driver so that it can identify the type\r
2716 of data to expect.\r
2717 @param[in] IfrNvData The IFR nv data.\r
2718\r
2719 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this\r
2720 operation.\r
2721 @retval EFI_NOT_FOUND Cannot find the corresponding variable.\r
2722 @retval EFI_UNSUPPORTED Can not create more attempts.\r
2723 @retval EFI_SUCCESS The operation is completed successfully.\r
2724\r
2725**/\r
2726EFI_STATUS\r
2727IScsiConfigProcessDefault (\r
2728 IN EFI_QUESTION_ID KeyValue,\r
2729 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
2730 )\r
2731{\r
2732 BOOLEAN NewAttempt;\r
2733 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
2734 UINT8 CurrentAttemptConfigIndex;\r
2735 ISCSI_NIC_INFO *NicInfo;\r
2736 UINT8 NicIndex;\r
2737 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
2738 UINT8 *AttemptConfigOrder;\r
2739 UINTN AttemptConfigOrderSize;\r
2740 UINTN Index;\r
2741 EFI_INPUT_KEY Key;\r
2742\r
2743 AttemptConfigData = NULL;\r
2744 //\r
2745 // Is User creating a new attempt?\r
2746 //\r
2747 NewAttempt = FALSE;\r
2748\r
2749 if ((KeyValue >= KEY_MAC_ENTRY_BASE) &&\r
2750 (KeyValue <= (UINT16)(mPrivate->MaxNic + KEY_MAC_ENTRY_BASE)))\r
2751 {\r
2752 //\r
2753 // User has pressed "Add an Attempt" and then selects a NIC.\r
2754 //\r
2755 NewAttempt = TRUE;\r
2756 } else if ((KeyValue >= KEY_ATTEMPT_ENTRY_BASE) &&\r
2757 (KeyValue < (ISCSI_MAX_ATTEMPTS_NUM + KEY_ATTEMPT_ENTRY_BASE)))\r
2758 {\r
2759 //\r
2760 // User has pressed "Attempt *".\r
2761 //\r
2762 NewAttempt = FALSE;\r
2763 } else {\r
2764 //\r
2765 // Don't process anything.\r
2766 //\r
2767 return EFI_SUCCESS;\r
2768 }\r
2769\r
2770 if (NewAttempt) {\r
2771 //\r
2772 // Determine which NIC user has selected for the new created attempt.\r
2773 //\r
2774 NicIndex = (UINT8)(KeyValue - KEY_MAC_ENTRY_BASE);\r
2775 NicInfo = IScsiGetNicInfoByIndex (NicIndex);\r
2776 if (NicInfo == NULL) {\r
2777 return EFI_NOT_FOUND;\r
2778 }\r
2779\r
2780 //\r
2781 // Create an attempt following the initialized attempt order.\r
2782 //\r
2783 AttemptConfigOrder = IScsiGetVariableAndSize (\r
2784 L"InitialAttemptOrder",\r
2785 &gIScsiConfigGuid,\r
2786 &AttemptConfigOrderSize\r
2787 );\r
2788\r
2789 if (AttemptConfigOrder == NULL) {\r
2790 return EFI_NOT_FOUND;\r
2791 }\r
2792\r
2793 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
2794 UnicodeSPrint (\r
2795 mPrivate->PortString,\r
2796 (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
2797 L"Attempt %d",\r
2798 (UINTN)AttemptConfigOrder[Index]\r
2799 );\r
2800 GetVariable2 (\r
2801 mPrivate->PortString,\r
2802 &gEfiIScsiInitiatorNameProtocolGuid,\r
2803 (VOID **)&AttemptConfigData,\r
2804 NULL\r
2805 );\r
2806 if ((AttemptConfigData == NULL) || (AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED)) {\r
2807 continue;\r
2808 }\r
2809\r
2810 break;\r
2811 }\r
2812\r
2813 if (Index > PcdGet8 (PcdMaxIScsiAttemptNumber)) {\r
2814 CreatePopUp (\r
2815 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2816 &Key,\r
2817 L"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",\r
2818 NULL\r
2819 );\r
2820 return EFI_UNSUPPORTED;\r
2821 }\r
2822\r
2823 if (AttemptConfigOrder != NULL) {\r
2824 FreePool (AttemptConfigOrder);\r
2825 }\r
2826\r
2827 //\r
2828 // Record the MAC info in Config Data.\r
2829 //\r
2830 IScsiMacAddrToStr (\r
2831 &NicInfo->PermanentAddress,\r
2832 NicInfo->HwAddressSize,\r
2833 NicInfo->VlanId,\r
2834 MacString\r
2835 );\r
2836\r
2837 ASSERT (AttemptConfigData != NULL);\r
2838 UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, sizeof (AttemptConfigData->MacString));\r
2839 AttemptConfigData->NicIndex = NicIndex;\r
2840 AttemptConfigData->Actived = ISCSI_ACTIVE_ENABLED;\r
2841\r
2842 //\r
2843 // Generate OUI-format ISID based on MAC address.\r
2844 //\r
2845 CopyMem (AttemptConfigData->SessionConfigData.IsId, &NicInfo->PermanentAddress, 6);\r
2846 AttemptConfigData->SessionConfigData.IsId[0] =\r
2847 (UINT8)(AttemptConfigData->SessionConfigData.IsId[0] & 0x3F);\r
2848\r
2849 //\r
2850 // Add the help info for the new attempt.\r
2851 //\r
2852 UnicodeSPrint (\r
2853 mPrivate->PortString,\r
2854 (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
2855 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d",\r
2856 MacString,\r
2857 NicInfo->BusNumber,\r
2858 NicInfo->DeviceNumber,\r
2859 NicInfo->FunctionNumber\r
2860 );\r
2861\r
2862 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (\r
2863 mCallbackInfo->RegisteredHandle,\r
2864 0,\r
2865 mPrivate->PortString,\r
2866 NULL\r
2867 );\r
2868 if (AttemptConfigData->AttemptTitleHelpToken == 0) {\r
2869 FreePool (AttemptConfigData);\r
2870 return EFI_OUT_OF_RESOURCES;\r
2871 }\r
2872 } else {\r
2873 //\r
2874 // Determine which Attempt user has selected to configure.\r
2875 // Get the attempt configuration data.\r
2876 //\r
2877 CurrentAttemptConfigIndex = (UINT8)(KeyValue - KEY_ATTEMPT_ENTRY_BASE);\r
2878\r
2879 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex);\r
2880 if (AttemptConfigData == NULL) {\r
2881 DEBUG ((DEBUG_ERROR, "Corresponding configuration data can not be retrieved!\n"));\r
2882 return EFI_NOT_FOUND;\r
2883 }\r
2884 }\r
2885\r
2886 //\r
2887 // Clear the old IFR data to avoid sharing it with other attempts.\r
2888 //\r
2889 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
2890 ZeroMem (IfrNvData->CHAPName, sizeof (IfrNvData->CHAPName));\r
2891 ZeroMem (IfrNvData->CHAPSecret, sizeof (IfrNvData->CHAPSecret));\r
2892 ZeroMem (IfrNvData->ReverseCHAPName, sizeof (IfrNvData->ReverseCHAPName));\r
2893 ZeroMem (IfrNvData->ReverseCHAPSecret, sizeof (IfrNvData->ReverseCHAPSecret));\r
2894 }\r
2895\r
2896 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData, IfrNvData);\r
2897\r
2898 //\r
2899 // Update current attempt to be a new created attempt or an existing attempt.\r
2900 //\r
2901 mCallbackInfo->Current = AttemptConfigData;\r
2902\r
2903 return EFI_SUCCESS;\r
2904}\r
2905\r
2906/**\r
2907\r
2908 This function allows the caller to request the current\r
2909 configuration for one or more named elements. The resulting\r
2910 string is in <ConfigAltResp> format. Also, any and all alternative\r
2911 configuration strings shall be appended to the end of the\r
2912 current configuration string. If they are, they must appear\r
2913 after the current configuration. They must contain the same\r
2914 routing (GUID, NAME, PATH) as the current configuration string.\r
2915 They must have an additional description indicating the type of\r
2916 alternative configuration the string represents,\r
2917 "ALTCFG=<StringToken>". That <StringToken> (when\r
2918 converted from Hex UNICODE to binary) is a reference to a\r
2919 string in the associated string pack.\r
2920\r
2921 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2922\r
2923 @param[in] Request A null-terminated Unicode string in\r
2924 <ConfigRequest> format. Note that this\r
2925 includes the routing information as well as\r
2926 the configurable name / value pairs. It is\r
2927 invalid for this string to be in\r
2928 <MultiConfigRequest> format.\r
2929\r
2930 @param[out] Progress On return, points to a character in the\r
2931 Request string. Points to the string's null\r
2932 terminator if request was successful. Points\r
2933 to the most recent "&" before the first\r
2934 failing name / value pair (or the beginning\r
2935 of the string if the failure is in the first\r
2936 name / value pair) if the request was not successful.\r
2937\r
2938 @param[out] Results A null-terminated Unicode string in\r
2939 <ConfigAltResp> format which has all values\r
2940 filled in for the names in the Request string.\r
2941 String to be allocated by the called function.\r
2942\r
2943 @retval EFI_SUCCESS The Results string is filled with the\r
2944 values corresponding to all requested\r
2945 names.\r
2946\r
2947 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
2948 parts of the results that must be\r
2949 stored awaiting possible future\r
2950 protocols.\r
2951\r
2952 @retval EFI_INVALID_PARAMETER For example, passing in a NULL\r
2953 for the Request parameter\r
2954 would result in this type of\r
2955 error. In this case, the\r
2956 Progress parameter would be\r
2957 set to NULL.\r
2958\r
2959 @retval EFI_NOT_FOUND Routing data doesn't match any\r
2960 known driver. Progress set to the\r
2961 first character in the routing header.\r
2962 Note: There is no requirement that the\r
2963 driver validate the routing data. It\r
2964 must skip the <ConfigHdr> in order to\r
2965 process the names.\r
2966\r
2967 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set\r
2968 to most recent "&" before the\r
2969 error or the beginning of the\r
2970 string.\r
2971\r
2972 @retval EFI_INVALID_PARAMETER Unknown name. Progress points\r
2973 to the & before the name in\r
2974 question.\r
2975\r
2976**/\r
2977EFI_STATUS\r
2978EFIAPI\r
2979IScsiFormExtractConfig (\r
2980 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2981 IN CONST EFI_STRING Request,\r
2982 OUT EFI_STRING *Progress,\r
2983 OUT EFI_STRING *Results\r
2984 )\r
2985{\r
2986 EFI_STATUS Status;\r
2987 CHAR8 *InitiatorName;\r
2988 UINTN BufferSize;\r
2989 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
2990 ISCSI_FORM_CALLBACK_INFO *Private;\r
2991 EFI_STRING ConfigRequestHdr;\r
2992 EFI_STRING ConfigRequest;\r
2993 BOOLEAN AllocatedRequest;\r
2994 UINTN Size;\r
2995\r
2996 if ((This == NULL) || (Progress == NULL) || (Results == NULL)) {\r
2997 return EFI_INVALID_PARAMETER;\r
2998 }\r
2999\r
3000 *Progress = Request;\r
3001 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gIScsiConfigGuid, mVendorStorageName)) {\r
3002 return EFI_NOT_FOUND;\r
3003 }\r
3004\r
3005 ConfigRequestHdr = NULL;\r
3006 ConfigRequest = NULL;\r
3007 AllocatedRequest = FALSE;\r
3008 Size = 0;\r
3009\r
3010 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
3011 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
3012 if (IfrNvData == NULL) {\r
3013 return EFI_OUT_OF_RESOURCES;\r
3014 }\r
3015\r
3016 if (Private->Current != NULL) {\r
3017 IScsiConvertAttemptConfigDataToIfrNvData (Private->Current, IfrNvData);\r
3018 }\r
3019\r
3020 //\r
3021 // Extract all AttemptConfigData to Keyword storage of IfrNvData.\r
3022 //\r
3023 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData);\r
3024\r
3025 BufferSize = ISCSI_NAME_MAX_SIZE;\r
3026 InitiatorName = (CHAR8 *)AllocateZeroPool (BufferSize);\r
3027 if (InitiatorName == NULL) {\r
3028 FreePool (IfrNvData);\r
3029 return EFI_OUT_OF_RESOURCES;\r
3030 }\r
3031\r
3032 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
3033 if (EFI_ERROR (Status)) {\r
3034 IfrNvData->InitiatorName[0] = L'\0';\r
3035 } else {\r
3036 AsciiStrToUnicodeStrS (\r
3037 InitiatorName,\r
3038 IfrNvData->InitiatorName,\r
3039 sizeof (IfrNvData->InitiatorName) / sizeof (IfrNvData->InitiatorName[0])\r
3040 );\r
3041 }\r
3042\r
3043 //\r
3044 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().\r
3045 //\r
3046 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
3047 ConfigRequest = Request;\r
3048 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
3049 //\r
3050 // Request has no request element, construct full request string.\r
3051 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
3052 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
3053 //\r
3054 ConfigRequestHdr = HiiConstructConfigHdr (&gIScsiConfigGuid, mVendorStorageName, Private->DriverHandle);\r
3055 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
3056 ConfigRequest = AllocateZeroPool (Size);\r
3057 if (ConfigRequest == NULL) {\r
3058 FreePool (IfrNvData);\r
3059 FreePool (InitiatorName);\r
3060 return EFI_OUT_OF_RESOURCES;\r
3061 }\r
3062\r
3063 AllocatedRequest = TRUE;\r
3064 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
3065 FreePool (ConfigRequestHdr);\r
3066 }\r
3067\r
3068 Status = gHiiConfigRouting->BlockToConfig (\r
3069 gHiiConfigRouting,\r
3070 ConfigRequest,\r
3071 (UINT8 *)IfrNvData,\r
3072 BufferSize,\r
3073 Results,\r
3074 Progress\r
3075 );\r
3076 FreePool (IfrNvData);\r
3077 FreePool (InitiatorName);\r
3078\r
3079 //\r
3080 // Free the allocated config request string.\r
3081 //\r
3082 if (AllocatedRequest) {\r
3083 FreePool (ConfigRequest);\r
3084 ConfigRequest = NULL;\r
3085 }\r
3086\r
3087 //\r
3088 // Set Progress string to the original request string.\r
3089 //\r
3090 if (Request == NULL) {\r
3091 *Progress = NULL;\r
3092 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
3093 *Progress = Request + StrLen (Request);\r
3094 }\r
3095\r
3096 return Status;\r
3097}\r
3098\r
3099/**\r
3100\r
3101 This function applies changes in a driver's configuration.\r
3102 Input is a Configuration, which has the routing data for this\r
3103 driver followed by name / value configuration pairs. The driver\r
3104 must apply those pairs to its configurable storage. If the\r
3105 driver's configuration is stored in a linear block of data\r
3106 and the driver's name / value pairs are in <BlockConfig>\r
3107 format, it may use the ConfigToBlock helper function (above) to\r
3108 simplify the job.\r
3109\r
3110 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
3111\r
3112 @param[in] Configuration A null-terminated Unicode string in\r
3113 <ConfigString> format.\r
3114\r
3115 @param[out] Progress A pointer to a string filled in with the\r
3116 offset of the most recent '&' before the\r
3117 first failing name / value pair (or the\r
3118 beginning of the string if the failure\r
3119 is in the first name / value pair) or\r
3120 the terminating NULL if all was\r
3121 successful.\r
3122\r
3123 @retval EFI_SUCCESS The results have been distributed or are\r
3124 awaiting distribution.\r
3125\r
3126 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
3127 parts of the results that must be\r
3128 stored awaiting possible future\r
3129 protocols.\r
3130\r
3131 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
3132 Results parameter would result\r
3133 in this type of error.\r
3134\r
3135 @retval EFI_NOT_FOUND Target for the specified routing data\r
3136 was not found.\r
3137\r
3138**/\r
3139EFI_STATUS\r
3140EFIAPI\r
3141IScsiFormRouteConfig (\r
3142 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
3143 IN CONST EFI_STRING Configuration,\r
3144 OUT EFI_STRING *Progress\r
3145 )\r
3146{\r
3147 EFI_STATUS Status;\r
3148 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
3149 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
3150 LIST_ENTRY *Entry;\r
3151 LIST_ENTRY *NextEntry;\r
3152 ISCSI_NIC_INFO *NicInfo;\r
3153 EFI_INPUT_KEY Key;\r
3154 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
3155 CHAR8 *InitiatorName;\r
3156 UINT8 *AttemptList;\r
3157 UINTN BufferSize;\r
3158 UINTN OffSet;\r
3159 UINTN Index;\r
3160 UINTN Index2;\r
3161\r
3162 Index = 0;\r
3163 Index2 = 0;\r
3164 NicInfo = NULL;\r
3165 AttemptList = NULL;\r
3166 Status = EFI_SUCCESS;\r
3167\r
3168 if ((This == NULL) || (Configuration == NULL) || (Progress == NULL)) {\r
3169 return EFI_INVALID_PARAMETER;\r
3170 }\r
3171\r
3172 //\r
3173 // Check routing data in <ConfigHdr>.\r
3174 // Note: if only one Storage is used, then this checking could be skipped.\r
3175 //\r
3176 if (!HiiIsConfigHdrMatch (Configuration, &gIScsiConfigGuid, mVendorStorageName)) {\r
3177 *Progress = Configuration;\r
3178 return EFI_NOT_FOUND;\r
3179 }\r
3180\r
3181 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
3182 if (IfrNvData == NULL) {\r
3183 return EFI_OUT_OF_RESOURCES;\r
3184 }\r
3185\r
3186 BufferSize = ISCSI_NAME_MAX_SIZE;\r
3187 InitiatorName = (CHAR8 *)AllocateZeroPool (BufferSize);\r
3188 if (InitiatorName == NULL) {\r
3189 Status = EFI_OUT_OF_RESOURCES;\r
3190 goto Exit;\r
3191 }\r
3192\r
3193 //\r
3194 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().\r
3195 //\r
3196 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
3197 Status = gHiiConfigRouting->ConfigToBlock (\r
3198 gHiiConfigRouting,\r
3199 Configuration,\r
3200 (UINT8 *)IfrNvData,\r
3201 &BufferSize,\r
3202 Progress\r
3203 );\r
3204 if (EFI_ERROR (Status)) {\r
3205 goto Exit;\r
3206 }\r
3207\r
3208 if (IfrNvData->InitiatorName[0] != L'\0') {\r
3209 UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, InitiatorName, ISCSI_NAME_MAX_SIZE);\r
3210 BufferSize = AsciiStrSize (InitiatorName);\r
3211\r
3212 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
3213 if (EFI_ERROR (Status)) {\r
3214 CreatePopUp (\r
3215 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3216 &Key,\r
3217 L"Invalid iSCSI Name!",\r
3218 NULL\r
3219 );\r
3220 goto Exit;\r
3221 }\r
3222 } else {\r
3223 Status = IScsiGetValue (Configuration, L"&OFFSET=", &OffSet);\r
3224 if (EFI_ERROR (Status)) {\r
3225 goto Exit;\r
3226 }\r
3227\r
3228 if (OffSet >= ATTEMPT_MAC_ADDR_VAR_OFFSET) {\r
3229 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
3230 if (EFI_ERROR (Status)) {\r
3231 CreatePopUp (\r
3232 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3233 &Key,\r
3234 L"Error: please configure iSCSI initiator name first!",\r
3235 NULL\r
3236 );\r
3237 goto Exit;\r
3238 }\r
3239 } else {\r
3240 goto Exit;\r
3241 }\r
3242\r
3243 if (IfrNvData->ISCSIAddAttemptList[0] != L'\0') {\r
3244 Status = IScsiGetAttemptIndexList (IfrNvData->ISCSIAddAttemptList, IfrNvData->AddAttemptList, TRUE);\r
3245 if (EFI_ERROR (Status)) {\r
3246 CreatePopUp (\r
3247 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3248 &Key,\r
3249 L"Error: The add attempt list is invalid",\r
3250 NULL\r
3251 );\r
3252 goto Exit;\r
3253 }\r
3254\r
3255 Status = IScsiConfigAddAttemptsByKeywords (IfrNvData->AddAttemptList);\r
3256 if (EFI_ERROR (Status)) {\r
3257 goto Exit;\r
3258 }\r
3259 } else if (IfrNvData->ISCSIDeleteAttemptList[0] != L'\0') {\r
3260 AttemptList = (UINT8 *)AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM + 1) * sizeof (UINT8));\r
3261 if (AttemptList == NULL) {\r
3262 Status = EFI_OUT_OF_RESOURCES;\r
3263 goto Exit;\r
3264 }\r
3265\r
3266 Status = IScsiGetAttemptIndexList (IfrNvData->ISCSIDeleteAttemptList, AttemptList, FALSE);\r
3267 if (EFI_ERROR (Status)) {\r
3268 CreatePopUp (\r
3269 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3270 &Key,\r
3271 L"Error: The delete attempt list is invalid",\r
3272 NULL\r
3273 );\r
3274 goto Exit;\r
3275 }\r
3276\r
3277 //\r
3278 // Mark the attempt which will be delete in the global list.\r
3279 //\r
3280 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {\r
3281 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
3282 while (AttemptList[Index] != 0) {\r
3283 if (AttemptConfigData->AttemptConfigIndex == AttemptList[Index]) {\r
3284 IfrNvData->DeleteAttemptList[Index2] = 1;\r
3285 break;\r
3286 }\r
3287\r
3288 Index++;\r
3289 }\r
3290\r
3291 Index2++;\r
3292 Index = 0;\r
3293 }\r
3294\r
3295 Status = IScsiConfigDeleteAttempts (IfrNvData);\r
3296 if (EFI_ERROR (Status)) {\r
3297 goto Exit;\r
3298 }\r
3299\r
3300 FreePool (AttemptList);\r
3301 } else if (IfrNvData->ISCSIAttemptOrder[0] != L'\0') {\r
3302 Status = IScsiGetAttemptIndexList (IfrNvData->ISCSIAttemptOrder, IfrNvData->DynamicOrderedList, FALSE);\r
3303 if (EFI_ERROR (Status)) {\r
3304 CreatePopUp (\r
3305 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3306 &Key,\r
3307 L"Error: The new attempt order list is invalid",\r
3308 NULL\r
3309 );\r
3310 goto Exit;\r
3311 }\r
3312\r
3313 Status = IScsiConfigOrderAttempts (IfrNvData);\r
3314 if (EFI_ERROR (Status)) {\r
3315 goto Exit;\r
3316 }\r
3317 } else if (IfrNvData->ISCSIMacAddr[0] != L'\0') {\r
3318 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
3319 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
3320 IScsiMacAddrToStr (\r
3321 &NicInfo->PermanentAddress,\r
3322 NicInfo->HwAddressSize,\r
3323 NicInfo->VlanId,\r
3324 MacString\r
3325 );\r
3326 if (!StrCmp (MacString, IfrNvData->ISCSIMacAddr)) {\r
3327 mPrivate->CurrentNic = NicInfo->NicIndex;\r
3328 break;\r
3329 }\r
3330 }\r
3331\r
3332 if ((NicInfo == NULL) || (NicInfo->NicIndex == 0)) {\r
3333 Status = EFI_NOT_FOUND;\r
3334 goto Exit;\r
3335 }\r
3336 } else {\r
3337 Status = IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData, OffSet);\r
3338 if (EFI_ERROR (Status)) {\r
3339 goto Exit;\r
3340 }\r
3341 }\r
3342 }\r
3343\r
3344 IScsiConfigUpdateAttempt ();\r
3345\r
3346Exit:\r
3347 if (InitiatorName != NULL) {\r
3348 FreePool (InitiatorName);\r
3349 }\r
3350\r
3351 if (IfrNvData != NULL) {\r
3352 FreePool (IfrNvData);\r
3353 }\r
3354\r
3355 return Status;\r
3356}\r
3357\r
3358/**\r
3359\r
3360 This function is called to provide results data to the driver.\r
3361 This data consists of a unique key that is used to identify\r
3362 which data is either being passed back or being asked for.\r
3363\r
3364 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
3365 @param[in] Action Specifies the type of action taken by the browser.\r
3366 @param[in] QuestionId A unique value which is sent to the original\r
3367 exporting driver so that it can identify the type\r
3368 of data to expect. The format of the data tends to\r
3369 vary based on the opcode that generated the callback.\r
3370 @param[in] Type The type of value for the question.\r
3371 @param[in, out] Value A pointer to the data being sent to the original\r
3372 exporting driver.\r
3373 @param[out] ActionRequest On return, points to the action requested by the\r
3374 callback function.\r
3375\r
3376 @retval EFI_SUCCESS The callback successfully handled the action.\r
3377 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
3378 variable and its data.\r
3379 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
3380 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
3381 callback.\r
3382**/\r
3383EFI_STATUS\r
3384EFIAPI\r
3385IScsiFormCallback (\r
3386 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
3387 IN EFI_BROWSER_ACTION Action,\r
3388 IN EFI_QUESTION_ID QuestionId,\r
3389 IN UINT8 Type,\r
3390 IN OUT EFI_IFR_TYPE_VALUE *Value,\r
3391 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
3392 )\r
3393{\r
3394 ISCSI_FORM_CALLBACK_INFO *Private;\r
3395 UINTN BufferSize;\r
3396 CHAR8 *IScsiName;\r
3397 CHAR8 IpString[ISCSI_NAME_MAX_SIZE];\r
3398 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];\r
3399 UINT64 Lun;\r
3400 EFI_IP_ADDRESS HostIp;\r
3401 EFI_IP_ADDRESS SubnetMask;\r
3402 EFI_IP_ADDRESS Gateway;\r
3403 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
3404 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData;\r
3405 EFI_STATUS Status;\r
3406 EFI_INPUT_KEY Key;\r
3407 ISCSI_NIC_INFO *NicInfo;\r
3408\r
3409 NicInfo = NULL;\r
3410\r
3411 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {\r
3412 //\r
3413 // Do nothing for UEFI OPEN/CLOSE Action\r
3414 //\r
3415 return EFI_SUCCESS;\r
3416 }\r
3417\r
3418 if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {\r
3419 //\r
3420 // All other type return unsupported.\r
3421 //\r
3422 return EFI_UNSUPPORTED;\r
3423 }\r
3424\r
3425 if ((Value == NULL) || (ActionRequest == NULL)) {\r
3426 return EFI_INVALID_PARAMETER;\r
3427 }\r
3428\r
3429 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
3430\r
3431 //\r
3432 // Retrieve uncommitted data from Browser\r
3433 //\r
3434\r
3435 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
3436 IfrNvData = AllocateZeroPool (BufferSize);\r
3437 if (IfrNvData == NULL) {\r
3438 return EFI_OUT_OF_RESOURCES;\r
3439 }\r
3440\r
3441 IScsiName = (CHAR8 *)AllocateZeroPool (ISCSI_NAME_MAX_SIZE);\r
3442 if (IScsiName == NULL) {\r
3443 FreePool (IfrNvData);\r
3444 return EFI_OUT_OF_RESOURCES;\r
3445 }\r
3446\r
3447 Status = EFI_SUCCESS;\r
3448\r
3449 ZeroMem (&OldIfrNvData, BufferSize);\r
3450\r
3451 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *)IfrNvData);\r
3452\r
3453 CopyMem (&OldIfrNvData, IfrNvData, BufferSize);\r
3454\r
3455 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
3456 switch (QuestionId) {\r
3457 case KEY_ADD_ATTEMPT:\r
3458 //\r
3459 // Check whether iSCSI initiator name is configured already.\r
3460 //\r
3461 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;\r
3462 Status = gIScsiInitiatorName.Get (\r
3463 &gIScsiInitiatorName,\r
3464 &mPrivate->InitiatorNameLength,\r
3465 mPrivate->InitiatorName\r
3466 );\r
3467 if (EFI_ERROR (Status)) {\r
3468 CreatePopUp (\r
3469 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3470 &Key,\r
3471 L"Error: please configure iSCSI initiator name first!",\r
3472 NULL\r
3473 );\r
3474 break;\r
3475 }\r
3476\r
3477 Status = IScsiConfigAddAttempt ();\r
3478 break;\r
3479\r
3480 case KEY_DELETE_ATTEMPT:\r
3481 CopyMem (\r
3482 OldIfrNvData.DeleteAttemptList,\r
3483 IfrNvData->DeleteAttemptList,\r
3484 sizeof (IfrNvData->DeleteAttemptList)\r
3485 );\r
3486 Status = IScsiConfigDisplayDeleteAttempts (IfrNvData);\r
3487 break;\r
3488\r
3489 case KEY_ORDER_ATTEMPT_CONFIG:\r
3490 //\r
3491 // Order the attempt according to user input.\r
3492 //\r
3493 CopyMem (\r
3494 OldIfrNvData.DynamicOrderedList,\r
3495 IfrNvData->DynamicOrderedList,\r
3496 sizeof (IfrNvData->DynamicOrderedList)\r
3497 );\r
3498 IScsiConfigDisplayOrderAttempts ();\r
3499 break;\r
3500\r
3501 default:\r
3502 Status = IScsiConfigProcessDefault (QuestionId, IfrNvData);\r
3503 break;\r
3504 }\r
3505 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
3506 switch (QuestionId) {\r
3507 case KEY_INITIATOR_NAME:\r
3508 UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, IScsiName, ISCSI_NAME_MAX_SIZE);\r
3509 BufferSize = AsciiStrSize (IScsiName);\r
3510\r
3511 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);\r
3512 if (EFI_ERROR (Status)) {\r
3513 CreatePopUp (\r
3514 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3515 &Key,\r
3516 L"Invalid iSCSI Name!",\r
3517 NULL\r
3518 );\r
3519 }\r
3520\r
3521 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
3522 break;\r
3523\r
3524 case KEY_SAVE_ATTEMPT_CONFIG:\r
3525 Status = IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData, Private->Current);\r
3526 if (EFI_ERROR (Status)) {\r
3527 break;\r
3528 }\r
3529\r
3530 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
3531 break;\r
3532\r
3533 case KEY_SAVE_ORDER_CHANGES:\r
3534 //\r
3535 // Sync the Attempt Order to NVR.\r
3536 //\r
3537 Status = IScsiConfigOrderAttempts (IfrNvData);\r
3538 if (EFI_ERROR (Status)) {\r
3539 break;\r
3540 }\r
3541\r
3542 IScsiConfigUpdateAttempt ();\r
3543 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
3544 break;\r
3545\r
3546 case KEY_IGNORE_ORDER_CHANGES:\r
3547 CopyMem (\r
3548 IfrNvData->DynamicOrderedList,\r
3549 OldIfrNvData.DynamicOrderedList,\r
3550 sizeof (IfrNvData->DynamicOrderedList)\r
3551 );\r
3552 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
3553 break;\r
3554\r
3555 case KEY_SAVE_DELETE_ATTEMPT:\r
3556 //\r
3557 // Delete the Attempt Order from NVR\r
3558 //\r
3559 Status = IScsiConfigDeleteAttempts (IfrNvData);\r
3560 if (EFI_ERROR (Status)) {\r
3561 break;\r
3562 }\r
3563\r
3564 IScsiConfigUpdateAttempt ();\r
3565 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
3566 break;\r
3567\r
3568 case KEY_IGNORE_DELETE_ATTEMPT:\r
3569 CopyMem (\r
3570 IfrNvData->DeleteAttemptList,\r
3571 OldIfrNvData.DeleteAttemptList,\r
3572 sizeof (IfrNvData->DeleteAttemptList)\r
3573 );\r
3574 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
3575 break;\r
3576\r
3577 case KEY_IP_MODE:\r
3578 switch (Value->u8) {\r
3579 case IP_MODE_IP6:\r
3580 NicInfo = IScsiGetNicInfoByIndex (Private->Current->NicIndex);\r
3581 if (NicInfo == NULL) {\r
3582 break;\r
3583 }\r
3584\r
3585 if (!NicInfo->Ipv6Available) {\r
3586 //\r
3587 // Current NIC doesn't Support IPv6, hence use IPv4.\r
3588 //\r
3589 IfrNvData->IpMode = IP_MODE_IP4;\r
3590\r
3591 CreatePopUp (\r
3592 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3593 &Key,\r
3594 L"Current NIC doesn't Support IPv6!",\r
3595 NULL\r
3596 );\r
3597 }\r
3598\r
3599 case IP_MODE_IP4:\r
3600 ZeroMem (IfrNvData->LocalIp, sizeof (IfrNvData->LocalIp));\r
3601 ZeroMem (IfrNvData->SubnetMask, sizeof (IfrNvData->SubnetMask));\r
3602 ZeroMem (IfrNvData->Gateway, sizeof (IfrNvData->Gateway));\r
3603 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));\r
3604 Private->Current->AutoConfigureMode = 0;\r
3605 ZeroMem (&Private->Current->SessionConfigData.LocalIp, sizeof (EFI_IP_ADDRESS));\r
3606 ZeroMem (&Private->Current->SessionConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
3607 ZeroMem (&Private->Current->SessionConfigData.Gateway, sizeof (EFI_IP_ADDRESS));\r
3608 ZeroMem (&Private->Current->SessionConfigData.TargetIp, sizeof (EFI_IP_ADDRESS));\r
3609\r
3610 break;\r
3611 }\r
3612\r
3613 break;\r
3614\r
3615 case KEY_LOCAL_IP:\r
3616 Status = NetLibStrToIp4 (IfrNvData->LocalIp, &HostIp.v4);\r
3617 if (EFI_ERROR (Status) ||\r
3618 ((Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) &&\r
3619 !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), NTOHL (*(UINT32 *)Private->Current->SessionConfigData.SubnetMask.Addr))))\r
3620 {\r
3621 CreatePopUp (\r
3622 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3623 &Key,\r
3624 L"Invalid IP address!",\r
3625 NULL\r
3626 );\r
3627\r
3628 Status = EFI_INVALID_PARAMETER;\r
3629 } else {\r
3630 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
3631 }\r
3632\r
3633 break;\r
3634\r
3635 case KEY_SUBNET_MASK:\r
3636 Status = NetLibStrToIp4 (IfrNvData->SubnetMask, &SubnetMask.v4);\r
3637 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
3638 CreatePopUp (\r
3639 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3640 &Key,\r
3641 L"Invalid Subnet Mask!",\r
3642 NULL\r
3643 );\r
3644\r
3645 Status = EFI_INVALID_PARAMETER;\r
3646 } else {\r
3647 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
3648 }\r
3649\r
3650 break;\r
3651\r
3652 case KEY_GATE_WAY:\r
3653 Status = NetLibStrToIp4 (IfrNvData->Gateway, &Gateway.v4);\r
3654 if (EFI_ERROR (Status) ||\r
3655 ((Gateway.Addr[0] != 0) &&\r
3656 (Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) &&\r
3657 !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL (*(UINT32 *)Private->Current->SessionConfigData.SubnetMask.Addr))))\r
3658 {\r
3659 CreatePopUp (\r
3660 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3661 &Key,\r
3662 L"Invalid Gateway!",\r
3663 NULL\r
3664 );\r
3665 Status = EFI_INVALID_PARAMETER;\r
3666 } else {\r
3667 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
3668 }\r
3669\r
3670 break;\r
3671\r
3672 case KEY_TARGET_IP:\r
3673 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, IpString, sizeof (IpString));\r
3674 Status = IScsiAsciiStrToIp (IpString, IfrNvData->IpMode, &HostIp);\r
3675 if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, IfrNvData->IpMode)) {\r
3676 //\r
3677 // The target is expressed in URL format or an invalid Ip address, just save.\r
3678 //\r
3679 Private->Current->SessionConfigData.DnsMode = TRUE;\r
3680 ZeroMem (&Private->Current->SessionConfigData.TargetIp, sizeof (Private->Current->SessionConfigData.TargetIp));\r
3681 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, Private->Current->SessionConfigData.TargetUrl, ISCSI_NAME_MAX_SIZE);\r
3682 } else {\r
3683 Private->Current->SessionConfigData.DnsMode = FALSE;\r
3684 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp));\r
3685 }\r
3686\r
3687 break;\r
3688\r
3689 case KEY_TARGET_NAME:\r
3690 UnicodeStrToAsciiStrS (IfrNvData->TargetName, IScsiName, ISCSI_NAME_MAX_SIZE);\r
3691 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));\r
3692 if (EFI_ERROR (Status)) {\r
3693 CreatePopUp (\r
3694 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3695 &Key,\r
3696 L"Invalid iSCSI Name!",\r
3697 NULL\r
3698 );\r
3699 } else {\r
3700 AsciiStrCpyS (Private->Current->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName);\r
3701 }\r
3702\r
3703 break;\r
3704\r
3705 case KEY_DHCP_ENABLE:\r
3706 if (IfrNvData->InitiatorInfoFromDhcp == 0) {\r
3707 IfrNvData->TargetInfoFromDhcp = 0;\r
3708 }\r
3709\r
3710 break;\r
3711\r
3712 case KEY_BOOT_LUN:\r
3713 UnicodeStrToAsciiStrS (IfrNvData->BootLun, LunString, sizeof (LunString));\r
3714 Status = IScsiAsciiStrToLun (LunString, (UINT8 *)&Lun);\r
3715 if (EFI_ERROR (Status)) {\r
3716 CreatePopUp (\r
3717 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3718 &Key,\r
3719 L"Invalid LUN string!",\r
3720 NULL\r
3721 );\r
3722 } else {\r
3723 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
3724 }\r
3725\r
3726 break;\r
3727\r
3728 case KEY_AUTH_TYPE:\r
3729 switch (Value->u8) {\r
3730 case ISCSI_AUTH_TYPE_CHAP:\r
3731 IfrNvData->CHAPType = ISCSI_CHAP_UNI;\r
3732 break;\r
3733 default:\r
3734 break;\r
3735 }\r
3736\r
3737 break;\r
3738\r
3739 case KEY_CHAP_NAME:\r
3740 UnicodeStrToAsciiStrS (\r
3741 IfrNvData->CHAPName,\r
3742 Private->Current->AuthConfigData.CHAP.CHAPName,\r
3743 sizeof (Private->Current->AuthConfigData.CHAP.CHAPName)\r
3744 );\r
3745 break;\r
3746\r
3747 case KEY_CHAP_SECRET:\r
3748 UnicodeStrToAsciiStrS (\r
3749 IfrNvData->CHAPSecret,\r
3750 Private->Current->AuthConfigData.CHAP.CHAPSecret,\r
3751 sizeof (Private->Current->AuthConfigData.CHAP.CHAPSecret)\r
3752 );\r
3753 break;\r
3754\r
3755 case KEY_REVERSE_CHAP_NAME:\r
3756 UnicodeStrToAsciiStrS (\r
3757 IfrNvData->ReverseCHAPName,\r
3758 Private->Current->AuthConfigData.CHAP.ReverseCHAPName,\r
3759 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPName)\r
3760 );\r
3761 break;\r
3762\r
3763 case KEY_REVERSE_CHAP_SECRET:\r
3764 UnicodeStrToAsciiStrS (\r
3765 IfrNvData->ReverseCHAPSecret,\r
3766 Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret,\r
3767 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret)\r
3768 );\r
3769 break;\r
3770\r
3771 case KEY_CONFIG_ISID:\r
3772 IScsiParseIsIdFromString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);\r
3773 IScsiConvertIsIdToString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);\r
3774\r
3775 break;\r
3776\r
3777 default:\r
3778 break;\r
3779 }\r
3780 }\r
3781\r
3782 if (!EFI_ERROR (Status)) {\r
3783 //\r
3784 // Pass changed uncommitted data back to Form Browser.\r
3785 //\r
3786 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
3787 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *)IfrNvData, NULL);\r
3788 }\r
3789\r
3790 FreePool (IfrNvData);\r
3791 FreePool (IScsiName);\r
3792\r
3793 return Status;\r
3794}\r
3795\r
3796/**\r
3797 Initialize the iSCSI configuration form.\r
3798\r
3799 @param[in] DriverBindingHandle The iSCSI driverbinding handle.\r
3800\r
3801 @retval EFI_SUCCESS The iSCSI configuration form is initialized.\r
3802 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
3803\r
3804**/\r
3805EFI_STATUS\r
3806IScsiConfigFormInit (\r
3807 IN EFI_HANDLE DriverBindingHandle\r
3808 )\r
3809{\r
3810 EFI_STATUS Status;\r
3811 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;\r
3812\r
3813 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *)AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO));\r
3814 if (CallbackInfo == NULL) {\r
3815 return EFI_OUT_OF_RESOURCES;\r
3816 }\r
3817\r
3818 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;\r
3819 CallbackInfo->Current = NULL;\r
3820\r
3821 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;\r
3822 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;\r
3823 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;\r
3824\r
3825 //\r
3826 // Install Device Path Protocol and Config Access protocol to driver handle.\r
3827 //\r
3828 Status = gBS->InstallMultipleProtocolInterfaces (\r
3829 &CallbackInfo->DriverHandle,\r
3830 &gEfiDevicePathProtocolGuid,\r
3831 &mIScsiHiiVendorDevicePath,\r
3832 &gEfiHiiConfigAccessProtocolGuid,\r
3833 &CallbackInfo->ConfigAccess,\r
3834 NULL\r
3835 );\r
3836 ASSERT_EFI_ERROR (Status);\r
3837\r
3838 //\r
3839 // Publish our HII data.\r
3840 //\r
3841 CallbackInfo->RegisteredHandle = HiiAddPackages (\r
3842 &gIScsiConfigGuid,\r
3843 CallbackInfo->DriverHandle,\r
3844 IScsiDxeStrings,\r
3845 IScsiConfigVfrBin,\r
3846 NULL\r
3847 );\r
3848 if (CallbackInfo->RegisteredHandle == NULL) {\r
3849 gBS->UninstallMultipleProtocolInterfaces (\r
3850 CallbackInfo->DriverHandle,\r
3851 &gEfiDevicePathProtocolGuid,\r
3852 &mIScsiHiiVendorDevicePath,\r
3853 &gEfiHiiConfigAccessProtocolGuid,\r
3854 &CallbackInfo->ConfigAccess,\r
3855 NULL\r
3856 );\r
3857 FreePool (CallbackInfo);\r
3858 return EFI_OUT_OF_RESOURCES;\r
3859 }\r
3860\r
3861 mCallbackInfo = CallbackInfo;\r
3862\r
3863 return EFI_SUCCESS;\r
3864}\r
3865\r
3866/**\r
3867 Unload the iSCSI configuration form, this includes: delete all the iSCSI\r
3868 configuration entries, uninstall the form callback protocol, and\r
3869 free the resources used.\r
3870\r
3871 @param[in] DriverBindingHandle The iSCSI driverbinding handle.\r
3872\r
3873 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.\r
3874 @retval Others Failed to unload the form.\r
3875\r
3876**/\r
3877EFI_STATUS\r
3878IScsiConfigFormUnload (\r
3879 IN EFI_HANDLE DriverBindingHandle\r
3880 )\r
3881{\r
3882 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
3883 ISCSI_NIC_INFO *NicInfo;\r
3884 LIST_ENTRY *Entry;\r
3885 EFI_STATUS Status;\r
3886\r
3887 while (!IsListEmpty (&mPrivate->AttemptConfigs)) {\r
3888 Entry = NetListRemoveHead (&mPrivate->AttemptConfigs);\r
3889 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
3890 FreePool (AttemptConfigData);\r
3891 mPrivate->AttemptCount--;\r
3892 }\r
3893\r
3894 ASSERT (mPrivate->AttemptCount == 0);\r
3895\r
3896 while (!IsListEmpty (&mPrivate->NicInfoList)) {\r
3897 Entry = NetListRemoveHead (&mPrivate->NicInfoList);\r
3898 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
3899 FreePool (NicInfo);\r
3900 mPrivate->NicCount--;\r
3901 }\r
3902\r
3903 ASSERT (mPrivate->NicCount == 0);\r
3904\r
3905 FreePool (mPrivate);\r
3906 mPrivate = NULL;\r
3907\r
3908 //\r
3909 // Remove HII package list.\r
3910 //\r
3911 HiiRemovePackages (mCallbackInfo->RegisteredHandle);\r
3912\r
3913 //\r
3914 // Uninstall Device Path Protocol and Config Access protocol.\r
3915 //\r
3916 Status = gBS->UninstallMultipleProtocolInterfaces (\r
3917 mCallbackInfo->DriverHandle,\r
3918 &gEfiDevicePathProtocolGuid,\r
3919 &mIScsiHiiVendorDevicePath,\r
3920 &gEfiHiiConfigAccessProtocolGuid,\r
3921 &mCallbackInfo->ConfigAccess,\r
3922 NULL\r
3923 );\r
3924\r
3925 FreePool (mCallbackInfo);\r
3926\r
3927 return Status;\r
3928}\r