]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - NetworkPkg/IScsiDxe/IScsiConfig.c
NetworkPkg: Remove some clarification from IScsiDxe.inf
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiConfig.c
... / ...
CommitLineData
1/** @file\r
2 Helper functions for configuring or getting the parameters relating to iSCSI.\r
3\r
4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
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
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
32 ISCSI_CONFIG_GUID\r
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
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
171 } else if (IpMode == IP_MODE_IP6) {\r
172 return NetIp6IsValidUnicast (&Ip->v6);\r
173 } else {\r
174 DEBUG ((DEBUG_ERROR, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode));\r
175 return FALSE;\r
176 }\r
177}\r
178\r
179/**\r
180 Parse IsId in string format and convert it to binary.\r
181\r
182 @param[in] String The buffer of the string to be parsed.\r
183 @param[in, out] IsId The buffer to store IsId.\r
184\r
185 @retval EFI_SUCCESS The operation finished successfully.\r
186 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
187\r
188**/\r
189EFI_STATUS\r
190IScsiParseIsIdFromString (\r
191 IN CONST CHAR16 *String,\r
192 IN OUT UINT8 *IsId\r
193 )\r
194{\r
195 UINT8 Index;\r
196 CHAR16 *IsIdStr;\r
197 CHAR16 TempStr[3];\r
198 UINTN NodeVal;\r
199 CHAR16 PortString[ISCSI_NAME_IFR_MAX_SIZE];\r
200 EFI_INPUT_KEY Key;\r
201\r
202 if ((String == NULL) || (IsId == NULL)) {\r
203 return EFI_INVALID_PARAMETER;\r
204 }\r
205\r
206 IsIdStr = (CHAR16 *) String;\r
207\r
208 if (StrLen (IsIdStr) != 6 && StrLen (IsIdStr) != 12) {\r
209 UnicodeSPrint (\r
210 PortString,\r
211 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
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
213 );\r
214\r
215 CreatePopUp (\r
216 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
217 &Key,\r
218 PortString,\r
219 NULL\r
220 );\r
221\r
222 return EFI_INVALID_PARAMETER;\r
223 }\r
224\r
225 if (StrLen (IsIdStr) == 12) {\r
226 IsIdStr += 6;\r
227 }\r
228\r
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
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
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
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
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
523 BOOLEAN DnsMode;\r
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
531 DnsMode = SessionConfigData->DnsMode;\r
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
544 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));\r
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
550 } else if (IfrNvData->IpMode == IP_MODE_IP6) {\r
551 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));\r
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
556 }\r
557\r
558 AsciiStrToUnicodeStrS (\r
559 SessionConfigData->TargetName,\r
560 IfrNvData->TargetName,\r
561 sizeof (IfrNvData->TargetName) / sizeof (IfrNvData->TargetName[0])\r
562 );\r
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
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
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
606 }\r
607\r
608 //\r
609 // Other parameters.\r
610 //\r
611 AsciiStrToUnicodeStrS (\r
612 Attempt->AttemptName,\r
613 IfrNvData->AttemptName,\r
614 sizeof (IfrNvData->AttemptName) / sizeof (IfrNvData->AttemptName[0])\r
615 );\r
616}\r
617\r
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
636 ISCSI_NIC_INFO *NicInfo;\r
637 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
638 EFI_IP_ADDRESS Ip;\r
639 UINTN Index;\r
640 UINTN StringLen;\r
641\r
642 NicInfo = NULL;\r
643 ZeroMem (AttemptNameList, sizeof (AttemptNameList));\r
644\r
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
652\r
653 ASSERT ((Attempt->AttemptConfigIndex > 0) && (Attempt->AttemptConfigIndex <= FixedPcdGet8 (PcdMaxIScsiAttemptNumber)));\r
654 Index = Attempt->AttemptConfigIndex - 1;\r
655\r
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
664\r
665 StringLen = StrLen (AttemptNameList);\r
666 ASSERT (StringLen > 2);\r
667 *(AttemptNameList + StringLen - 2) = L':';\r
668 *(AttemptNameList + StringLen) = L' ';\r
669\r
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
674 );\r
675\r
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
704 AsciiStrToUnicodeStrS (\r
705 SessionConfigData->TargetName,\r
706 IfrNvData->Keyword[Index].ISCSITargetName,\r
707 ISCSI_NAME_MAX_SIZE\r
708 );\r
709\r
710 if (SessionConfigData->DnsMode) {\r
711 AsciiStrToUnicodeStrS (\r
712 SessionConfigData->TargetUrl,\r
713 IfrNvData->Keyword[Index].ISCSITargetIpAddress,\r
714 sizeof (IfrNvData->Keyword[Index].ISCSITargetIpAddress) / sizeof (IfrNvData->Keyword[Index].ISCSITargetIpAddress[0])\r
715 );\r
716 }\r
717\r
718 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->Keyword[Index].ISCSILun);\r
719 IScsiConvertIsIdToString (IfrNvData->Keyword[Index].ISCSIIsId, SessionConfigData->IsId);\r
720\r
721 IfrNvData->ISCSIAuthenticationMethod[Index] = Attempt->AuthenticationType;\r
722\r
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
731\r
732 AsciiStrToUnicodeStrS (\r
733 AuthConfigData->CHAPSecret,\r
734 IfrNvData->Keyword[Index].ISCSIChapSecret,\r
735 ISCSI_CHAP_SECRET_STORAGE\r
736 );\r
737\r
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
750 }\r
751 CopyMem(IfrNvData->ISCSIDisplayAttemptList, AttemptNameList, ATTEMPT_NAME_LIST_SIZE);\r
752\r
753 ZeroMem (IfrNvData->ISCSIMacAddr, sizeof (IfrNvData->ISCSIMacAddr));\r
754 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
755 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
756 IScsiMacAddrToStr (\r
757 &NicInfo->PermanentAddress,\r
758 NicInfo->HwAddressSize,\r
759 NicInfo->VlanId,\r
760 MacString\r
761 );\r
762 CopyMem (\r
763 IfrNvData->ISCSIMacAddr + StrLen (IfrNvData->ISCSIMacAddr),\r
764 MacString,\r
765 StrLen (MacString) * sizeof (CHAR16)\r
766 );\r
767\r
768 *(IfrNvData->ISCSIMacAddr + StrLen (IfrNvData->ISCSIMacAddr)) = L'/';\r
769 }\r
770\r
771 StringLen = StrLen (IfrNvData->ISCSIMacAddr);\r
772 if (StringLen > 0) {\r
773 *(IfrNvData->ISCSIMacAddr + StringLen - 1) = L'\0';\r
774 }\r
775 }\r
776}\r
777\r
778/**\r
779 Convert the IFR data to iSCSI configuration data.\r
780\r
781 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.\r
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
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
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
809 UINT8 *AttemptConfigOrder;\r
810 UINTN AttemptConfigOrderSize;\r
811 UINT8 *AttemptOrderTmp;\r
812 UINTN TotalNumber;\r
813 EFI_STATUS Status;\r
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
854\r
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
875\r
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
884\r
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
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
913 }\r
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
929 }\r
930\r
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
964 AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));\r
965 if (AttemptName1 == NULL) {\r
966 return EFI_OUT_OF_RESOURCES;\r
967 }\r
968\r
969 AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));\r
970 if (AttemptName2 == NULL) {\r
971 FreePool (AttemptName1);\r
972 return EFI_OUT_OF_RESOURCES;\r
973 }\r
974\r
975 AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_SIZE);\r
976 AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_SIZE);\r
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
998 //\r
999 // Update the iSCSI Mode data and record it in attempt help info.\r
1000 //\r
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
1027 AsciiStrToUnicodeStrS (Attempt->MacString, MacString, ISCSI_MAX_MAC_STRING_LEN);\r
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
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
1121 } else if (ExistAttempt == NULL) {\r
1122 //\r
1123 // When a new attempt is created, pointer of the attempt is saved to\r
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
1128\r
1129 //\r
1130 // Save current order number for this attempt.\r
1131 //\r
1132 AttemptConfigOrder = IScsiGetVariableAndSize (\r
1133 L"AttemptOrder",\r
1134 &gIScsiConfigGuid,\r
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
1163 &gIScsiConfigGuid,\r
1164 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
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
1178\r
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
1188\r
1189 IScsiConfigUpdateAttempt ();\r
1190 }\r
1191 Attempt->SessionConfigData.Enabled = IfrNvData->Enabled;\r
1192\r
1193 //\r
1194 // Record the user configuration information in NVR.\r
1195 //\r
1196 UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", Attempt->AttemptConfigIndex);\r
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
1210 Convert the IFR data configured by keyword to iSCSI configuration data.\r
1211\r
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
1214\r
1215 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.\r
1216 @retval EFI_SUCCESS The operation is completed successfully.\r
1217\r
1218**/\r
1219EFI_STATUS\r
1220IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (\r
1221 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData,\r
1222 IN UINTN OffSet\r
1223 )\r
1224{\r
1225 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;\r
1226 UINT8 AttemptIndex;\r
1227 UINT8 Index;\r
1228 UINT8 ChapSecretLen;\r
1229 UINT8 ReverseChapSecretLen;\r
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
1242\r
1243 Attempt = NULL;\r
1244 ZeroMem (IScsiName, sizeof (IScsiName));\r
1245\r
1246 if (OffSet < ATTEMPT_BOOTENABLE_VAR_OFFSET) {\r
1247 return EFI_SUCCESS;\r
1248\r
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
1269\r
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
1275\r
1276 AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_SIZE);\r
1277 AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_SIZE);\r
1278\r
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
1286\r
1287 CreatePopUp (\r
1288 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1289 &Key,\r
1290 mPrivate->PortString,\r
1291 NULL\r
1292 );\r
1293\r
1294 FreePool (AttemptName1);\r
1295 FreePool (AttemptName2);\r
1296 }\r
1297 }\r
1298\r
1299 if (IfrNvData->Enabled == ISCSI_DISABLED &&\r
1300 Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
1301\r
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
1309\r
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
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
1388 }\r
1389 Attempt->SessionConfigData.ConnectRetryCount = IfrNvData->ISCSIConnectRetry[AttemptIndex - 1];\r
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
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
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
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
1665 if (IfrNvData->Keyword[Index].ISCSIChapUsername[0] == L'\0') {\r
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
1687 ChapSecretLen = (UINT8)StrLen (IfrNvData->Keyword[Index].ISCSIChapSecret);\r
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
1695 if ((ChapSecretLen < ISCSI_CHAP_SECRET_MIN_LEN) || (ChapSecretLen > ISCSI_CHAP_SECRET_MAX_LEN)) {\r
1696 CreatePopUp (\r
1697 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1698 &Key,\r
1699 L"The Chap Secret minimum length is 12 bytes and the maximum length is 16 bytes.",\r
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
1723 if (IfrNvData->Keyword[Index].ISCSIReverseChapUsername[0] == L'\0') {\r
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
1745 ReverseChapSecretLen = (UINT8)StrLen (IfrNvData->Keyword[Index].ISCSIReverseChapSecret);\r
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
1753 if ((ReverseChapSecretLen < ISCSI_CHAP_SECRET_MIN_LEN) || (ReverseChapSecretLen > ISCSI_CHAP_SECRET_MAX_LEN)) {\r
1754 CreatePopUp (\r
1755 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1756 &Key,\r
1757 L"The Reverse CHAP Secret minimum length is 12 bytes and the maximum length is 16 bytes.",\r
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
1780 ASSERT (Attempt != NULL);\r
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
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
2006 UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"MAC %s", MacString);\r
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
2044 &gIScsiConfigGuid, // Formset GUID\r
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
2057/**\r
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
2069\r
2070**/\r
2071EFI_STATUS\r
2072IScsiConfigAddAttemptsByKeywords (\r
2073 IN UINT8 *AttemptList\r
2074 )\r
2075{\r
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
2089\r
2090 Nic = mPrivate->CurrentNic;\r
2091 NicInfo = IScsiGetNicInfoByIndex (Nic);\r
2092 if (NicInfo == NULL) {\r
2093 return EFI_NOT_FOUND;\r
2094 }\r
2095\r
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
2201\r
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
2212 }\r
2213\r
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
2227\r
2228 }\r
2229\r
2230 return EFI_SUCCESS;\r
2231}\r
2232\r
2233/**\r
2234 Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword.\r
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
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
2267\r
2268 AttemptConfigOrder = IScsiGetVariableAndSize (\r
2269 L"AttemptOrder",\r
2270 &gIScsiConfigGuid,\r
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
2279 Status = EFI_OUT_OF_RESOURCES;\r
2280 goto Error;\r
2281 }\r
2282\r
2283 Total = AttemptConfigOrderSize / sizeof (UINT8);\r
2284 NewTotal = Total;\r
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
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
2350\r
2351 //\r
2352 // Set the attempt name to default.\r
2353 //\r
2354 UnicodeSPrint (\r
2355 mPrivate->PortString,\r
2356 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
2357 L"Attempt %d",\r
2358 (UINTN) AttemptConfigData->AttemptConfigIndex\r
2359 );\r
2360 UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, ATTEMPT_NAME_SIZE);\r
2361 gRT->SetVariable (\r
2362 mPrivate->PortString,\r
2363 &gEfiIScsiInitiatorNameProtocolGuid,\r
2364 ISCSI_CONFIG_VAR_ATTR,\r
2365 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
2366 AttemptConfigData\r
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
2380 if (mCallbackInfo->Current == AttemptConfigData) {\r
2381 mCallbackInfo->Current = NULL;\r
2382 }\r
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
2401 Attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
2402\r
2403 //\r
2404 // Update AttemptOrder in NVR.\r
2405 //\r
2406 Status = gRT->SetVariable (\r
2407 L"AttemptOrder",\r
2408 &gIScsiConfigGuid,\r
2409 Attribute,\r
2410 NewTotal * sizeof (UINT8),\r
2411 AttemptNewOrder\r
2412 );\r
2413\r
2414Error:\r
2415 if (AttemptConfigOrder != NULL) {\r
2416 FreePool (AttemptConfigOrder);\r
2417 }\r
2418\r
2419 if (AttemptNewOrder != NULL) {\r
2420 FreePool (AttemptNewOrder);\r
2421 }\r
2422\r
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
2467 &gIScsiConfigGuid,\r
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
2504 &gIScsiConfigGuid, // Formset GUID\r
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
2551 ASSERT (StartOpCodeHandle != NULL);\r
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
2605 &gIScsiConfigGuid, // Formset GUID\r
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
2621/**\r
2622 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.\r
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
2648 &gIScsiConfigGuid,\r
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
2710 &gIScsiConfigGuid,\r
2711 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
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
2738 @retval EFI_UNSUPPORTED Can not create more attempts.\r
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
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
2756 UINTN Index;\r
2757 EFI_INPUT_KEY Key;\r
2758\r
2759 AttemptConfigData = NULL;\r
2760 //\r
2761 // Is User creating a new attempt?\r
2762 //\r
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
2794\r
2795 //\r
2796 // Create an attempt following the initialized attempt order.\r
2797 //\r
2798 AttemptConfigOrder = IScsiGetVariableAndSize (\r
2799 L"InitialAttemptOrder",\r
2800 &gIScsiConfigGuid,\r
2801 &AttemptConfigOrderSize\r
2802 );\r
2803\r
2804 if (AttemptConfigOrder == NULL) {\r
2805 return EFI_NOT_FOUND;\r
2806 }\r
2807\r
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
2823 }\r
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
2836 }\r
2837\r
2838 if (AttemptConfigOrder != NULL) {\r
2839 FreePool (AttemptConfigOrder);\r
2840 }\r
2841\r
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
2852 ASSERT (AttemptConfigData != NULL);\r
2853 UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, sizeof (AttemptConfigData->MacString));\r
2854 AttemptConfigData->NicIndex = NicIndex;\r
2855 AttemptConfigData->Actived = ISCSI_ACTIVE_ENABLED;\r
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
2885 return EFI_OUT_OF_RESOURCES;\r
2886 }\r
2887\r
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
2914 //\r
2915 // Update current attempt to be a new created attempt or an existing attempt.\r
2916 //\r
2917 mCallbackInfo->Current = AttemptConfigData;\r
2918\r
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
3018 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gIScsiConfigGuid, mVendorStorageName)) {\r
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
3032\r
3033\r
3034 if (Private->Current!= NULL) {\r
3035 IScsiConvertAttemptConfigDataToIfrNvData (Private->Current, IfrNvData);\r
3036 }\r
3037\r
3038 //\r
3039 // Extract all AttemptConfigData to Keyword stroage of IfrNvData.\r
3040 //\r
3041 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData);\r
3042\r
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
3054 AsciiStrToUnicodeStrS (\r
3055 InitiatorName,\r
3056 IfrNvData->InitiatorName,\r
3057 sizeof (IfrNvData->InitiatorName) / sizeof (IfrNvData->InitiatorName[0])\r
3058 );\r
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
3072 ConfigRequestHdr = HiiConstructConfigHdr (&gIScsiConfigGuid, mVendorStorageName, Private->DriverHandle);\r
3073 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
3074 ConfigRequest = AllocateZeroPool (Size);\r
3075 if (ConfigRequest == NULL) {\r
3076 FreePool (IfrNvData);\r
3077 FreePool (InitiatorName);\r
3078 return EFI_OUT_OF_RESOURCES;\r
3079 }\r
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
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
3183 Status = EFI_SUCCESS;\r
3184\r
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
3193 if (!HiiIsConfigHdrMatch (Configuration, &gIScsiConfigGuid, mVendorStorageName)) {\r
3194 *Progress = Configuration;\r
3195 return EFI_NOT_FOUND;\r
3196 }\r
3197\r
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
3240 Status = IScsiGetValue (Configuration, L"&OFFSET=", &OffSet);\r
3241 if (EFI_ERROR (Status)) {\r
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
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
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
3364Exit:\r
3365 if (InitiatorName != NULL) {\r
3366 FreePool (InitiatorName);\r
3367 }\r
3368\r
3369 if (IfrNvData != NULL) {\r
3370 FreePool (IfrNvData);\r
3371 }\r
3372\r
3373 return Status;\r
3374}\r
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
3415 CHAR8 IpString[ISCSI_NAME_MAX_SIZE];\r
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
3424 EFI_INPUT_KEY Key;\r
3425 ISCSI_NIC_INFO *NicInfo;\r
3426\r
3427 NicInfo = NULL;\r
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
3436 if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {\r
3437 //\r
3438 // All other type return unsupported.\r
3439 //\r
3440 return EFI_UNSUPPORTED;\r
3441 }\r
3442\r
3443 if ((Value == NULL) || (ActionRequest == NULL)) {\r
3444 return EFI_INVALID_PARAMETER;\r
3445 }\r
3446\r
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
3472\r
3473 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
3474 switch (QuestionId) {\r
3475 case KEY_ADD_ATTEMPT:\r
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
3495 Status = IScsiConfigAddAttempt ();\r
3496 break;\r
3497\r
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
3506\r
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
3524 switch (QuestionId) {\r
3525 case KEY_INITIATOR_NAME:\r
3526 UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, IScsiName, ISCSI_NAME_MAX_SIZE);\r
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
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
3544 if (EFI_ERROR (Status)) {\r
3545 break;\r
3546 }\r
3547\r
3548 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
3549 break;\r
3550\r
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
3561 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
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
3570 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
3571 break;\r
3572\r
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
3580 }\r
3581\r
3582 IScsiConfigUpdateAttempt ();\r
3583 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
3584 break;\r
3585\r
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
3593 break;\r
3594\r
3595 case KEY_IP_MODE:\r
3596 switch (Value->u8) {\r
3597 case IP_MODE_IP6:\r
3598 NicInfo = IScsiGetNicInfoByIndex (Private->Current->NicIndex);\r
3599 if(NicInfo == NULL) {\r
3600 break;\r
3601 }\r
3602\r
3603 if(!NicInfo->Ipv6Available) {\r
3604 //\r
3605 // Current NIC doesn't Support IPv6, hence use IPv4.\r
3606 //\r
3607 IfrNvData->IpMode = IP_MODE_IP4;\r
3608\r
3609 CreatePopUp (\r
3610 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3611 &Key,\r
3612 L"Current NIC doesn't Support IPv6!",\r
3613 NULL\r
3614 );\r
3615 }\r
3616\r
3617 case IP_MODE_IP4:\r
3618 ZeroMem (IfrNvData->LocalIp, sizeof (IfrNvData->LocalIp));\r
3619 ZeroMem (IfrNvData->SubnetMask, sizeof (IfrNvData->SubnetMask));\r
3620 ZeroMem (IfrNvData->Gateway, sizeof (IfrNvData->Gateway));\r
3621 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));\r
3622 Private->Current->AutoConfigureMode = 0;\r
3623 ZeroMem (&Private->Current->SessionConfigData.LocalIp, sizeof (EFI_IP_ADDRESS));\r
3624 ZeroMem (&Private->Current->SessionConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
3625 ZeroMem (&Private->Current->SessionConfigData.Gateway, sizeof (EFI_IP_ADDRESS));\r
3626 ZeroMem (&Private->Current->SessionConfigData.TargetIp, sizeof (EFI_IP_ADDRESS));\r
3627\r
3628 break;\r
3629 }\r
3630\r
3631 break;\r
3632\r
3633 case KEY_LOCAL_IP:\r
3634 Status = NetLibStrToIp4 (IfrNvData->LocalIp, &HostIp.v4);\r
3635 if (EFI_ERROR (Status) ||\r
3636 ((Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) &&\r
3637 !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), NTOHL(*(UINT32*)Private->Current->SessionConfigData.SubnetMask.Addr)))) {\r
3638 CreatePopUp (\r
3639 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3640 &Key,\r
3641 L"Invalid IP address!",\r
3642 NULL\r
3643 );\r
3644\r
3645 Status = EFI_INVALID_PARAMETER;\r
3646 } else {\r
3647 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
3648 }\r
3649\r
3650 break;\r
3651\r
3652 case KEY_SUBNET_MASK:\r
3653 Status = NetLibStrToIp4 (IfrNvData->SubnetMask, &SubnetMask.v4);\r
3654 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
3655 CreatePopUp (\r
3656 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3657 &Key,\r
3658 L"Invalid Subnet Mask!",\r
3659 NULL\r
3660 );\r
3661\r
3662 Status = EFI_INVALID_PARAMETER;\r
3663 } else {\r
3664 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
3665 }\r
3666\r
3667 break;\r
3668\r
3669 case KEY_GATE_WAY:\r
3670 Status = NetLibStrToIp4 (IfrNvData->Gateway, &Gateway.v4);\r
3671 if (EFI_ERROR (Status) ||\r
3672 ((Gateway.Addr[0] != 0) &&\r
3673 (Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) &&\r
3674 !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL(*(UINT32*)Private->Current->SessionConfigData.SubnetMask.Addr)))) {\r
3675 CreatePopUp (\r
3676 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3677 &Key,\r
3678 L"Invalid Gateway!",\r
3679 NULL\r
3680 );\r
3681 Status = EFI_INVALID_PARAMETER;\r
3682 } else {\r
3683 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
3684 }\r
3685\r
3686 break;\r
3687\r
3688 case KEY_TARGET_IP:\r
3689 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, IpString, sizeof (IpString));\r
3690 Status = IScsiAsciiStrToIp (IpString, IfrNvData->IpMode, &HostIp);\r
3691 if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, IfrNvData->IpMode)) {\r
3692 //\r
3693 // The target is expressed in URL format or an invalid Ip address, just save.\r
3694 //\r
3695 Private->Current->SessionConfigData.DnsMode = TRUE;\r
3696 ZeroMem (&Private->Current->SessionConfigData.TargetIp, sizeof (Private->Current->SessionConfigData.TargetIp));\r
3697 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, Private->Current->SessionConfigData.TargetUrl, ISCSI_NAME_MAX_SIZE);\r
3698 } else {\r
3699 Private->Current->SessionConfigData.DnsMode = FALSE;\r
3700 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp));\r
3701 }\r
3702\r
3703 break;\r
3704\r
3705 case KEY_TARGET_NAME:\r
3706 UnicodeStrToAsciiStrS (IfrNvData->TargetName, IScsiName, ISCSI_NAME_MAX_SIZE);\r
3707 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));\r
3708 if (EFI_ERROR (Status)) {\r
3709 CreatePopUp (\r
3710 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3711 &Key,\r
3712 L"Invalid iSCSI Name!",\r
3713 NULL\r
3714 );\r
3715 } else {\r
3716 AsciiStrCpyS (Private->Current->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName);\r
3717 }\r
3718\r
3719 break;\r
3720\r
3721 case KEY_DHCP_ENABLE:\r
3722 if (IfrNvData->InitiatorInfoFromDhcp == 0) {\r
3723 IfrNvData->TargetInfoFromDhcp = 0;\r
3724 }\r
3725\r
3726 break;\r
3727\r
3728 case KEY_BOOT_LUN:\r
3729 UnicodeStrToAsciiStrS (IfrNvData->BootLun, LunString, sizeof (LunString));\r
3730 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);\r
3731 if (EFI_ERROR (Status)) {\r
3732 CreatePopUp (\r
3733 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
3734 &Key,\r
3735 L"Invalid LUN string!",\r
3736 NULL\r
3737 );\r
3738 } else {\r
3739 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
3740 }\r
3741\r
3742 break;\r
3743\r
3744 case KEY_AUTH_TYPE:\r
3745 switch (Value->u8) {\r
3746 case ISCSI_AUTH_TYPE_CHAP:\r
3747 IfrNvData->CHAPType = ISCSI_CHAP_UNI;\r
3748 break;\r
3749 default:\r
3750 break;\r
3751 }\r
3752\r
3753 break;\r
3754\r
3755 case KEY_CHAP_NAME:\r
3756 UnicodeStrToAsciiStrS (\r
3757 IfrNvData->CHAPName,\r
3758 Private->Current->AuthConfigData.CHAP.CHAPName,\r
3759 sizeof (Private->Current->AuthConfigData.CHAP.CHAPName)\r
3760 );\r
3761 break;\r
3762\r
3763 case KEY_CHAP_SECRET:\r
3764 UnicodeStrToAsciiStrS (\r
3765 IfrNvData->CHAPSecret,\r
3766 Private->Current->AuthConfigData.CHAP.CHAPSecret,\r
3767 sizeof (Private->Current->AuthConfigData.CHAP.CHAPSecret)\r
3768 );\r
3769 break;\r
3770\r
3771 case KEY_REVERSE_CHAP_NAME:\r
3772 UnicodeStrToAsciiStrS (\r
3773 IfrNvData->ReverseCHAPName,\r
3774 Private->Current->AuthConfigData.CHAP.ReverseCHAPName,\r
3775 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPName)\r
3776 );\r
3777 break;\r
3778\r
3779 case KEY_REVERSE_CHAP_SECRET:\r
3780 UnicodeStrToAsciiStrS (\r
3781 IfrNvData->ReverseCHAPSecret,\r
3782 Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret,\r
3783 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret)\r
3784 );\r
3785 break;\r
3786\r
3787 case KEY_CONFIG_ISID:\r
3788 IScsiParseIsIdFromString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);\r
3789 IScsiConvertIsIdToString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);\r
3790\r
3791 break;\r
3792\r
3793 default:\r
3794 break;\r
3795 }\r
3796 }\r
3797\r
3798 if (!EFI_ERROR (Status)) {\r
3799 //\r
3800 // Pass changed uncommitted data back to Form Browser.\r
3801 //\r
3802 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
3803 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);\r
3804 }\r
3805\r
3806 FreePool (IfrNvData);\r
3807 FreePool (IScsiName);\r
3808\r
3809 return Status;\r
3810}\r
3811\r
3812\r
3813/**\r
3814 Initialize the iSCSI configuration form.\r
3815\r
3816 @param[in] DriverBindingHandle The iSCSI driverbinding handle.\r
3817\r
3818 @retval EFI_SUCCESS The iSCSI configuration form is initialized.\r
3819 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
3820\r
3821**/\r
3822EFI_STATUS\r
3823IScsiConfigFormInit (\r
3824 IN EFI_HANDLE DriverBindingHandle\r
3825 )\r
3826{\r
3827 EFI_STATUS Status;\r
3828 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;\r
3829\r
3830 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO));\r
3831 if (CallbackInfo == NULL) {\r
3832 return EFI_OUT_OF_RESOURCES;\r
3833 }\r
3834\r
3835 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;\r
3836 CallbackInfo->Current = NULL;\r
3837\r
3838 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;\r
3839 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;\r
3840 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;\r
3841\r
3842 //\r
3843 // Install Device Path Protocol and Config Access protocol to driver handle.\r
3844 //\r
3845 Status = gBS->InstallMultipleProtocolInterfaces (\r
3846 &CallbackInfo->DriverHandle,\r
3847 &gEfiDevicePathProtocolGuid,\r
3848 &mIScsiHiiVendorDevicePath,\r
3849 &gEfiHiiConfigAccessProtocolGuid,\r
3850 &CallbackInfo->ConfigAccess,\r
3851 NULL\r
3852 );\r
3853 ASSERT_EFI_ERROR (Status);\r
3854\r
3855 //\r
3856 // Publish our HII data.\r
3857 //\r
3858 CallbackInfo->RegisteredHandle = HiiAddPackages (\r
3859 &gIScsiConfigGuid,\r
3860 CallbackInfo->DriverHandle,\r
3861 IScsiDxeStrings,\r
3862 IScsiConfigVfrBin,\r
3863 NULL\r
3864 );\r
3865 if (CallbackInfo->RegisteredHandle == NULL) {\r
3866 gBS->UninstallMultipleProtocolInterfaces (\r
3867 &CallbackInfo->DriverHandle,\r
3868 &gEfiDevicePathProtocolGuid,\r
3869 &mIScsiHiiVendorDevicePath,\r
3870 &gEfiHiiConfigAccessProtocolGuid,\r
3871 &CallbackInfo->ConfigAccess,\r
3872 NULL\r
3873 );\r
3874 FreePool(CallbackInfo);\r
3875 return EFI_OUT_OF_RESOURCES;\r
3876 }\r
3877\r
3878 mCallbackInfo = CallbackInfo;\r
3879\r
3880 return EFI_SUCCESS;\r
3881}\r
3882\r
3883\r
3884/**\r
3885 Unload the iSCSI configuration form, this includes: delete all the iSCSI\r
3886 configuration entries, uninstall the form callback protocol, and\r
3887 free the resources used.\r
3888\r
3889 @param[in] DriverBindingHandle The iSCSI driverbinding handle.\r
3890\r
3891 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.\r
3892 @retval Others Failed to unload the form.\r
3893\r
3894**/\r
3895EFI_STATUS\r
3896IScsiConfigFormUnload (\r
3897 IN EFI_HANDLE DriverBindingHandle\r
3898 )\r
3899{\r
3900 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
3901 ISCSI_NIC_INFO *NicInfo;\r
3902 LIST_ENTRY *Entry;\r
3903 EFI_STATUS Status;\r
3904\r
3905 while (!IsListEmpty (&mPrivate->AttemptConfigs)) {\r
3906 Entry = NetListRemoveHead (&mPrivate->AttemptConfigs);\r
3907 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
3908 FreePool (AttemptConfigData);\r
3909 mPrivate->AttemptCount--;\r
3910 }\r
3911\r
3912 ASSERT (mPrivate->AttemptCount == 0);\r
3913\r
3914 while (!IsListEmpty (&mPrivate->NicInfoList)) {\r
3915 Entry = NetListRemoveHead (&mPrivate->NicInfoList);\r
3916 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
3917 FreePool (NicInfo);\r
3918 mPrivate->NicCount--;\r
3919 }\r
3920\r
3921 ASSERT (mPrivate->NicCount == 0);\r
3922\r
3923 FreePool (mPrivate);\r
3924 mPrivate = NULL;\r
3925\r
3926 //\r
3927 // Remove HII package list.\r
3928 //\r
3929 HiiRemovePackages (mCallbackInfo->RegisteredHandle);\r
3930\r
3931 //\r
3932 // Uninstall Device Path Protocol and Config Access protocol.\r
3933 //\r
3934 Status = gBS->UninstallMultipleProtocolInterfaces (\r
3935 mCallbackInfo->DriverHandle,\r
3936 &gEfiDevicePathProtocolGuid,\r
3937 &mIScsiHiiVendorDevicePath,\r
3938 &gEfiHiiConfigAccessProtocolGuid,\r
3939 &mCallbackInfo->ConfigAccess,\r
3940 NULL\r
3941 );\r
3942\r
3943 FreePool (mCallbackInfo);\r
3944\r
3945 return Status;\r
3946}\r