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