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