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