]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IScsiDxe/IScsiConfig.c
NetworkPkg/IScsiDxe: rebase to ARRAY_SIZE()
[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
b9679cd7 4Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
4c5a5e0c 5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "IScsiImpl.h"\r
16\r
4c5a5e0c 17CHAR16 mVendorStorageName[] = L"ISCSI_CONFIG_IFR_NVDATA";\r
18BOOLEAN mIScsiDeviceListUpdated = FALSE;\r
19UINTN mNumberOfIScsiDevices = 0;\r
20ISCSI_FORM_CALLBACK_INFO *mCallbackInfo = NULL;\r
21\r
22HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath = {\r
23 {\r
24 {\r
25 HARDWARE_DEVICE_PATH,\r
26 HW_VENDOR_DP,\r
27 {\r
28 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
29 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
30 }\r
31 },\r
9bdc6592 32 ISCSI_CONFIG_GUID\r
4c5a5e0c 33 },\r
34 {\r
35 END_DEVICE_PATH_TYPE,\r
36 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
37 { \r
38 (UINT8) (END_DEVICE_PATH_LENGTH),\r
39 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
40 }\r
41 }\r
42};\r
43\r
44\r
45/**\r
46 Convert the IP address into a dotted string.\r
47\r
48 @param[in] Ip The IP address.\r
49 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.\r
50 @param[out] Str The formatted IP string.\r
51\r
52**/\r
53VOID\r
54IScsiIpToStr (\r
55 IN EFI_IP_ADDRESS *Ip,\r
56 IN BOOLEAN Ipv6Flag,\r
57 OUT CHAR16 *Str\r
58 )\r
59{\r
60 EFI_IPv4_ADDRESS *Ip4;\r
61 EFI_IPv6_ADDRESS *Ip6;\r
62 UINTN Index;\r
63 BOOLEAN Short;\r
64 UINTN Number;\r
65 CHAR16 FormatString[8];\r
66\r
67 if (!Ipv6Flag) {\r
68 Ip4 = &Ip->v4;\r
69\r
70 UnicodeSPrint (\r
71 Str,\r
72 (UINTN) 2 * IP4_STR_MAX_SIZE,\r
73 L"%d.%d.%d.%d",\r
74 (UINTN) Ip4->Addr[0],\r
75 (UINTN) Ip4->Addr[1],\r
76 (UINTN) Ip4->Addr[2],\r
77 (UINTN) Ip4->Addr[3]\r
78 );\r
79\r
80 return ;\r
81 }\r
82\r
83 Ip6 = &Ip->v6;\r
84 Short = FALSE;\r
85\r
86 for (Index = 0; Index < 15; Index = Index + 2) {\r
87 if (!Short &&\r
88 Index % 2 == 0 &&\r
89 Ip6->Addr[Index] == 0 &&\r
90 Ip6->Addr[Index + 1] == 0\r
91 ) {\r
92 //\r
93 // Deal with the case of ::.\r
94 //\r
95 if (Index == 0) {\r
96 *Str = L':';\r
97 *(Str + 1) = L':';\r
98 Str = Str + 2;\r
99 } else {\r
100 *Str = L':';\r
101 Str = Str + 1;\r
102 }\r
103\r
104 while ((Index < 15) && (Ip6->Addr[Index] == 0) && (Ip6->Addr[Index + 1] == 0)) {\r
105 Index = Index + 2;\r
106 }\r
107\r
108 Short = TRUE;\r
109\r
110 if (Index == 16) {\r
111 //\r
112 // :: is at the end of the address.\r
113 //\r
114 *Str = L'\0';\r
115 break;\r
116 }\r
117 }\r
118\r
119 ASSERT (Index < 15);\r
120\r
121 if (Ip6->Addr[Index] == 0) {\r
122 Number = UnicodeSPrint (Str, 2 * IP_STR_MAX_SIZE, L"%x:", (UINTN) Ip6->Addr[Index + 1]);\r
123 } else {\r
124 if (Ip6->Addr[Index + 1] < 0x10) {\r
125 CopyMem (FormatString, L"%x0%x:", StrSize (L"%x0%x:"));\r
126 } else {\r
127 CopyMem (FormatString, L"%x%x:", StrSize (L"%x%x:"));\r
128 }\r
129\r
130 Number = UnicodeSPrint (\r
131 Str,\r
132 2 * IP_STR_MAX_SIZE,\r
133 (CONST CHAR16 *) FormatString,\r
134 (UINTN) Ip6->Addr[Index],\r
135 (UINTN) Ip6->Addr[Index + 1]\r
136 );\r
137 }\r
138\r
139 Str = Str + Number;\r
140\r
141 if (Index + 2 == 16) {\r
142 *Str = L'\0';\r
143 if (*(Str - 1) == L':') {\r
144 *(Str - 1) = L'\0';\r
145 }\r
146 }\r
147 }\r
148}\r
149\r
150/**\r
151 Check whether the input IP address is valid.\r
152\r
153 @param[in] Ip The IP address.\r
154 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.\r
155\r
156 @retval TRUE The input IP address is valid.\r
157 @retval FALSE Otherwise\r
158\r
159**/\r
160BOOLEAN\r
161IpIsUnicast (\r
162 IN EFI_IP_ADDRESS *Ip,\r
163 IN UINT8 IpMode\r
164 )\r
165{\r
166 if (IpMode == IP_MODE_IP4) {\r
167 return NetIp4IsUnicast (NTOHL (Ip->Addr[0]), 0);\r
168 } else if (IpMode == IP_MODE_IP6) {\r
169 return NetIp6IsValidUnicast (&Ip->v6);\r
170 } else {\r
171 DEBUG ((DEBUG_ERROR, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode));\r
172 return FALSE;\r
173 }\r
174}\r
175\r
176/**\r
177 Parse IsId in string format and convert it to binary.\r
178\r
179 @param[in] String The buffer of the string to be parsed.\r
180 @param[in, out] IsId The buffer to store IsId.\r
181\r
182 @retval EFI_SUCCESS The operation finished successfully.\r
183 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
184\r
185**/\r
186EFI_STATUS\r
187IScsiParseIsIdFromString (\r
188 IN CONST CHAR16 *String,\r
189 IN OUT UINT8 *IsId\r
190 )\r
191{\r
192 UINT8 Index;\r
193 CHAR16 *IsIdStr;\r
194 CHAR16 TempStr[3];\r
195 UINTN NodeVal;\r
196 CHAR16 PortString[ISCSI_NAME_IFR_MAX_SIZE];\r
197 EFI_INPUT_KEY Key;\r
198\r
199 if ((String == NULL) || (IsId == NULL)) {\r
200 return EFI_INVALID_PARAMETER;\r
201 }\r
202\r
203 IsIdStr = (CHAR16 *) String;\r
204\r
205 if (StrLen (IsIdStr) != 6) {\r
206 UnicodeSPrint (\r
207 PortString,\r
208 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
209 L"Error! Input is incorrect, please input 6 hex numbers!\n"\r
210 );\r
211\r
212 CreatePopUp (\r
213 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
214 &Key,\r
215 PortString,\r
216 NULL\r
217 );\r
218\r
219 return EFI_INVALID_PARAMETER;\r
220 }\r
221\r
222 for (Index = 3; Index < 6; Index++) {\r
223 CopyMem (TempStr, IsIdStr, sizeof (TempStr));\r
224 TempStr[2] = L'\0';\r
225\r
226 //\r
227 // Convert the string to IsId. StrHexToUintn stops at the first character\r
228 // that is not a valid hex character, '\0' here.\r
229 //\r
230 NodeVal = StrHexToUintn (TempStr);\r
231\r
232 IsId[Index] = (UINT8) NodeVal;\r
233\r
234 IsIdStr = IsIdStr + 2;\r
235 }\r
236\r
237 return EFI_SUCCESS;\r
238}\r
239\r
240/**\r
241 Convert IsId from binary to string format.\r
242\r
243 @param[out] String The buffer to store the converted string.\r
244 @param[in] IsId The buffer to store IsId.\r
245\r
246 @retval EFI_SUCCESS The string converted successfully.\r
247 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
248\r
249**/\r
250EFI_STATUS\r
251IScsiConvertIsIdToString (\r
252 OUT CHAR16 *String,\r
253 IN UINT8 *IsId\r
254 )\r
255{\r
256 UINT8 Index;\r
257 UINTN Number;\r
258\r
259 if ((String == NULL) || (IsId == NULL)) {\r
260 return EFI_INVALID_PARAMETER;\r
261 }\r
262\r
263 for (Index = 0; Index < 6; Index++) {\r
264 if (IsId[Index] <= 0xF) {\r
265 Number = UnicodeSPrint (\r
266 String,\r
267 2 * ISID_CONFIGURABLE_STORAGE,\r
268 L"0%X",\r
269 (UINTN) IsId[Index]\r
270 );\r
271 } else {\r
272 Number = UnicodeSPrint (\r
273 String,\r
274 2 * ISID_CONFIGURABLE_STORAGE,\r
275 L"%X",\r
276 (UINTN) IsId[Index]\r
277 );\r
278\r
279 }\r
280\r
281 String = String + Number;\r
282 }\r
283\r
284 *String = L'\0';\r
285\r
286 return EFI_SUCCESS;\r
287}\r
288\r
289/**\r
290 Get the attempt config data from global structure by the ConfigIndex.\r
291\r
292 @param[in] AttemptConfigIndex The unique index indicates the attempt.\r
293\r
294 @return Pointer to the attempt config data.\r
295 @retval NULL The attempt configuration data cannot be found.\r
296\r
297**/\r
298ISCSI_ATTEMPT_CONFIG_NVDATA *\r
299IScsiConfigGetAttemptByConfigIndex (\r
300 IN UINT8 AttemptConfigIndex\r
301 )\r
302{\r
303 LIST_ENTRY *Entry;\r
304 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;\r
305\r
306 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
307 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
308 if (Attempt->AttemptConfigIndex == AttemptConfigIndex) {\r
309 return Attempt;\r
310 }\r
311 }\r
312\r
313 return NULL;\r
314}\r
315\r
316\r
317/**\r
318 Get the existing attempt config data from global structure by the NicIndex.\r
319\r
320 @param[in] NewAttempt The created new attempt\r
321 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or\r
322 Enabled for MPIO.\r
323\r
324 @return Pointer to the existing attempt config data which\r
325 has the same NICIndex as the new created attempt.\r
326 @retval NULL The attempt with NicIndex does not exist.\r
327\r
328**/\r
329ISCSI_ATTEMPT_CONFIG_NVDATA *\r
330IScsiConfigGetAttemptByNic (\r
331 IN ISCSI_ATTEMPT_CONFIG_NVDATA *NewAttempt,\r
332 IN UINT8 IScsiMode\r
333 )\r
334{\r
335 LIST_ENTRY *Entry;\r
336 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;\r
337\r
338 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
339 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
340 if (Attempt != NewAttempt && Attempt->NicIndex == NewAttempt->NicIndex &&\r
341 Attempt->SessionConfigData.Enabled == IScsiMode) {\r
342 return Attempt;\r
343 }\r
344 }\r
345\r
346 return NULL;\r
347}\r
348\r
349\r
350/**\r
351 Convert the iSCSI configuration data into the IFR data.\r
352\r
353 @param[in] Attempt The iSCSI attempt config data.\r
354 @param[in, out] IfrNvData The IFR nv data.\r
355\r
356**/\r
357VOID\r
358IScsiConvertAttemptConfigDataToIfrNvData (\r
359 IN ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt,\r
360 IN OUT ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
361 )\r
362{\r
363 ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData;\r
364 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;\r
365 EFI_IP_ADDRESS Ip;\r
366\r
367 //\r
368 // Normal session configuration parameters.\r
369 //\r
370 SessionConfigData = &Attempt->SessionConfigData;\r
371 IfrNvData->Enabled = SessionConfigData->Enabled;\r
372 IfrNvData->IpMode = SessionConfigData->IpMode;\r
373\r
374 IfrNvData->InitiatorInfoFromDhcp = SessionConfigData->InitiatorInfoFromDhcp;\r
375 IfrNvData->TargetInfoFromDhcp = SessionConfigData->TargetInfoFromDhcp;\r
376 IfrNvData->TargetPort = SessionConfigData->TargetPort;\r
377\r
378 if (IfrNvData->IpMode == IP_MODE_IP4) {\r
379 CopyMem (&Ip.v4, &SessionConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));\r
380 IScsiIpToStr (&Ip, FALSE, IfrNvData->LocalIp);\r
381 CopyMem (&Ip.v4, &SessionConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
382 IScsiIpToStr (&Ip, FALSE, IfrNvData->SubnetMask);\r
383 CopyMem (&Ip.v4, &SessionConfigData->Gateway, sizeof (EFI_IPv4_ADDRESS));\r
384 IScsiIpToStr (&Ip, FALSE, IfrNvData->Gateway);\r
385 CopyMem (&Ip.v4, &SessionConfigData->TargetIp, sizeof (EFI_IPv4_ADDRESS));\r
386 IScsiIpToStr (&Ip, FALSE, IfrNvData->TargetIp);\r
387 } else if (IfrNvData->IpMode == IP_MODE_IP6) {\r
388 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));\r
389 IP6_COPY_ADDRESS (&Ip.v6, &SessionConfigData->TargetIp);\r
390 IScsiIpToStr (&Ip, TRUE, IfrNvData->TargetIp);\r
391 }\r
392\r
b9679cd7
SZ
393 AsciiStrToUnicodeStrS (\r
394 SessionConfigData->TargetName,\r
395 IfrNvData->TargetName,\r
396 sizeof (IfrNvData->TargetName) / sizeof (IfrNvData->TargetName[0])\r
397 );\r
4c5a5e0c 398 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->BootLun);\r
399 IScsiConvertIsIdToString (IfrNvData->IsId, SessionConfigData->IsId);\r
400\r
401 IfrNvData->ConnectRetryCount = SessionConfigData->ConnectRetryCount;\r
402 IfrNvData->ConnectTimeout = SessionConfigData->ConnectTimeout;\r
403\r
404 //\r
405 // Authentication parameters.\r
406 //\r
407 IfrNvData->AuthenticationType = Attempt->AuthenticationType;\r
408\r
409 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
410 AuthConfigData = &Attempt->AuthConfigData.CHAP;\r
411 IfrNvData->CHAPType = AuthConfigData->CHAPType;\r
b9679cd7
SZ
412 AsciiStrToUnicodeStrS (\r
413 AuthConfigData->CHAPName,\r
414 IfrNvData->CHAPName,\r
415 sizeof (IfrNvData->CHAPName) / sizeof (IfrNvData->CHAPName[0])\r
416 );\r
417 AsciiStrToUnicodeStrS (\r
418 AuthConfigData->CHAPSecret,\r
419 IfrNvData->CHAPSecret,\r
420 sizeof (IfrNvData->CHAPSecret) / sizeof (IfrNvData->CHAPSecret[0])\r
421 );\r
422 AsciiStrToUnicodeStrS (\r
423 AuthConfigData->ReverseCHAPName,\r
424 IfrNvData->ReverseCHAPName,\r
425 sizeof (IfrNvData->ReverseCHAPName) / sizeof (IfrNvData->ReverseCHAPName[0])\r
426 );\r
427 AsciiStrToUnicodeStrS (\r
428 AuthConfigData->ReverseCHAPSecret,\r
429 IfrNvData->ReverseCHAPSecret,\r
430 sizeof (IfrNvData->ReverseCHAPSecret) / sizeof (IfrNvData->ReverseCHAPSecret[0])\r
431 );\r
4c5a5e0c 432 }\r
433\r
434 //\r
435 // Other parameters.\r
436 //\r
b9679cd7
SZ
437 AsciiStrToUnicodeStrS (\r
438 Attempt->AttemptName,\r
439 IfrNvData->AttemptName,\r
440 sizeof (IfrNvData->AttemptName) / sizeof (IfrNvData->AttemptName[0])\r
441 );\r
4c5a5e0c 442}\r
443\r
4c5a5e0c 444/**\r
445 Convert the IFR data to iSCSI configuration data.\r
446\r
c0d494b5 447 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.\r
4c5a5e0c 448 @param[in, out] Attempt The iSCSI attempt config data.\r
449\r
450 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.\r
451 @retval EFI_NOT_FOUND Cannot find the corresponding variable.\r
c0d494b5 452 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.\r
453 @retval EFI_ABORTED The operation is aborted.\r
4c5a5e0c 454 @retval EFI_SUCCESS The operation is completed successfully.\r
455\r
456**/\r
457EFI_STATUS\r
458IScsiConvertIfrNvDataToAttemptConfigData (\r
459 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData,\r
460 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt\r
461 )\r
462{\r
463 EFI_IP_ADDRESS HostIp;\r
464 EFI_IP_ADDRESS SubnetMask;\r
465 EFI_IP_ADDRESS Gateway;\r
466 CHAR16 *MacString;\r
467 CHAR16 *AttemptName1;\r
468 CHAR16 *AttemptName2;\r
469 ISCSI_ATTEMPT_CONFIG_NVDATA *ExistAttempt;\r
470 ISCSI_ATTEMPT_CONFIG_NVDATA *SameNicAttempt;\r
471 CHAR16 IScsiMode[64];\r
472 CHAR16 IpMode[64];\r
473 ISCSI_NIC_INFO *NicInfo;\r
474 EFI_INPUT_KEY Key;\r
c0d494b5 475 UINT8 *AttemptConfigOrder;\r
476 UINTN AttemptConfigOrderSize;\r
477 UINT8 *AttemptOrderTmp;\r
478 UINTN TotalNumber;\r
479 EFI_STATUS Status;\r
4c5a5e0c 480\r
481 if (IfrNvData == NULL || Attempt == NULL) {\r
482 return EFI_INVALID_PARAMETER;\r
483 }\r
484\r
485 //\r
486 // Update those fields which don't have INTERACTIVE attribute.\r
487 //\r
488 Attempt->SessionConfigData.ConnectRetryCount = IfrNvData->ConnectRetryCount;\r
489 Attempt->SessionConfigData.ConnectTimeout = IfrNvData->ConnectTimeout;\r
490 Attempt->SessionConfigData.IpMode = IfrNvData->IpMode;\r
491\r
492 if (IfrNvData->IpMode < IP_MODE_AUTOCONFIG) {\r
493 Attempt->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp;\r
494 Attempt->SessionConfigData.TargetPort = IfrNvData->TargetPort;\r
495\r
496 if (Attempt->SessionConfigData.TargetPort == 0) {\r
497 Attempt->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;\r
498 }\r
499\r
500 Attempt->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp;\r
501 }\r
502\r
503 Attempt->AuthenticationType = IfrNvData->AuthenticationType;\r
504\r
505 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
506 Attempt->AuthConfigData.CHAP.CHAPType = IfrNvData->CHAPType;\r
507 }\r
508\r
509 //\r
510 // Only do full parameter validation if iSCSI is enabled on this device.\r
511 //\r
512 if (IfrNvData->Enabled != ISCSI_DISABLED) {\r
513 if (Attempt->SessionConfigData.ConnectTimeout < CONNECT_MIN_TIMEOUT) {\r
514 CreatePopUp (\r
515 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
516 &Key,\r
517 L"Connection Establishing Timeout is less than minimum value 100ms.",\r
518 NULL\r
519 );\r
520 \r
521 return EFI_INVALID_PARAMETER;\r
522 }\r
523\r
524 //\r
525 // Validate the address configuration of the Initiator if DHCP isn't\r
526 // deployed.\r
527 //\r
528 if (!Attempt->SessionConfigData.InitiatorInfoFromDhcp) {\r
529 CopyMem (&HostIp.v4, &Attempt->SessionConfigData.LocalIp, sizeof (HostIp.v4));\r
530 CopyMem (&SubnetMask.v4, &Attempt->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));\r
531 CopyMem (&Gateway.v4, &Attempt->SessionConfigData.Gateway, sizeof (Gateway.v4));\r
532\r
533 if ((Gateway.Addr[0] != 0)) {\r
534 if (SubnetMask.Addr[0] == 0) {\r
535 CreatePopUp (\r
536 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
537 &Key,\r
538 L"Gateway address is set but subnet mask is zero.",\r
539 NULL\r
540 );\r
541 \r
542 return EFI_INVALID_PARAMETER;\r
543 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {\r
544 CreatePopUp (\r
545 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
546 &Key,\r
547 L"Local IP and Gateway are not in the same subnet.",\r
548 NULL\r
549 );\r
550 \r
551 return EFI_INVALID_PARAMETER;\r
552 }\r
553 }\r
554 }\r
555 //\r
556 // Validate target configuration if DHCP isn't deployed.\r
557 //\r
558 if (!Attempt->SessionConfigData.TargetInfoFromDhcp && Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) {\r
559 if (!IpIsUnicast (&Attempt->SessionConfigData.TargetIp, IfrNvData->IpMode)) {\r
560 CreatePopUp (\r
561 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
562 &Key,\r
563 L"Target IP is invalid!",\r
564 NULL\r
565 );\r
566 return EFI_INVALID_PARAMETER;\r
567 }\r
b2220321
YT
568\r
569 //\r
570 // Validate iSCSI target name configuration again:\r
571 // The format of iSCSI target name is already verified in IScsiFormCallback() when\r
572 // user input the name; here we only check the case user does not input the name.\r
573 //\r
574 if (Attempt->SessionConfigData.TargetName[0] == '\0') {\r
575 CreatePopUp (\r
576 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
577 &Key,\r
578 L"iSCSI target name is NULL!",\r
579 NULL\r
580 );\r
581 return EFI_INVALID_PARAMETER;\r
582 }\r
4c5a5e0c 583 }\r
b2220321
YT
584\r
585\r
4c5a5e0c 586 //\r
587 // Validate the authentication info.\r
588 //\r
589 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
590 if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) {\r
591 CreatePopUp (\r
592 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
593 &Key,\r
594 L"CHAP Name or CHAP Secret is invalid!",\r
595 NULL\r
596 );\r
597 \r
598 return EFI_INVALID_PARAMETER;\r
599 }\r
600\r
601 if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) &&\r
602 ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0'))\r
603 ) {\r
604 CreatePopUp (\r
605 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
606 &Key,\r
607 L"Reverse CHAP Name or Reverse CHAP Secret is invalid!",\r
608 NULL\r
609 ); \r
610 return EFI_INVALID_PARAMETER;\r
611 }\r
612 }\r
613\r
614 //\r
615 // Check whether this attempt uses NIC which is already used by existing attempt.\r
616 //\r
617 SameNicAttempt = IScsiConfigGetAttemptByNic (Attempt, IfrNvData->Enabled);\r
618 if (SameNicAttempt != NULL) {\r
619 AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE * sizeof (CHAR16));\r
620 if (AttemptName1 == NULL) {\r
621 return EFI_OUT_OF_RESOURCES;\r
622 }\r
623\r
624 AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE * sizeof (CHAR16));\r
625 if (AttemptName2 == NULL) {\r
626 FreePool (AttemptName1);\r
627 return EFI_OUT_OF_RESOURCES;\r
628 } \r
629 \r
b9679cd7 630 AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_MAX_SIZE);\r
4c5a5e0c 631 if (StrLen (AttemptName1) > ATTEMPT_NAME_SIZE) {\r
632 CopyMem (&AttemptName1[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16));\r
633 }\r
634\r
b9679cd7 635 AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_MAX_SIZE);\r
4c5a5e0c 636 if (StrLen (AttemptName2) > ATTEMPT_NAME_SIZE) {\r
637 CopyMem (&AttemptName2[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16));\r
638 }\r
639\r
640 UnicodeSPrint (\r
641 mPrivate->PortString,\r
642 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
643 L"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",\r
644 AttemptName1,\r
645 AttemptName2\r
646 );\r
647\r
648 CreatePopUp (\r
649 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
650 &Key,\r
651 mPrivate->PortString,\r
652 NULL\r
653 ); \r
654\r
655 FreePool (AttemptName1);\r
656 FreePool (AttemptName2);\r
657 }\r
658 }\r
659\r
c0d494b5 660 //\r
661 // Update the iSCSI Mode data and record it in attempt help info.\r
662 //\r
663 Attempt->SessionConfigData.Enabled = IfrNvData->Enabled;\r
664 if (IfrNvData->Enabled == ISCSI_DISABLED) {\r
665 UnicodeSPrint (IScsiMode, 64, L"Disabled");\r
666 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {\r
667 UnicodeSPrint (IScsiMode, 64, L"Enabled");\r
668 } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
669 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");\r
670 }\r
671\r
672 if (IfrNvData->IpMode == IP_MODE_IP4) {\r
673 UnicodeSPrint (IpMode, 64, L"IP4");\r
674 } else if (IfrNvData->IpMode == IP_MODE_IP6) {\r
675 UnicodeSPrint (IpMode, 64, L"IP6");\r
676 } else if (IfrNvData->IpMode == IP_MODE_AUTOCONFIG) {\r
677 UnicodeSPrint (IpMode, 64, L"Autoconfigure");\r
678 }\r
679\r
680 NicInfo = IScsiGetNicInfoByIndex (Attempt->NicIndex);\r
681 if (NicInfo == NULL) {\r
682 return EFI_NOT_FOUND;\r
683 }\r
684\r
685 MacString = (CHAR16 *) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN * sizeof (CHAR16));\r
686 if (MacString == NULL) {\r
687 return EFI_OUT_OF_RESOURCES;\r
688 }\r
689\r
b522ca0c 690 AsciiStrToUnicodeStrS (Attempt->MacString, MacString, ISCSI_MAX_MAC_STRING_LEN);\r
c0d494b5 691\r
692 UnicodeSPrint (\r
693 mPrivate->PortString,\r
694 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
695 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",\r
696 MacString,\r
697 NicInfo->BusNumber,\r
698 NicInfo->DeviceNumber,\r
699 NicInfo->FunctionNumber,\r
700 IScsiMode,\r
701 IpMode\r
702 );\r
703\r
704 Attempt->AttemptTitleHelpToken = HiiSetString (\r
705 mCallbackInfo->RegisteredHandle,\r
706 Attempt->AttemptTitleHelpToken,\r
707 mPrivate->PortString,\r
708 NULL\r
709 );\r
710 if (Attempt->AttemptTitleHelpToken == 0) {\r
711 FreePool (MacString);\r
712 return EFI_OUT_OF_RESOURCES;\r
713 }\r
714\r
4c5a5e0c 715 //\r
716 // Check whether this attempt is an existing one.\r
717 //\r
718 ExistAttempt = IScsiConfigGetAttemptByConfigIndex (Attempt->AttemptConfigIndex);\r
719 if (ExistAttempt != NULL) {\r
720 ASSERT (ExistAttempt == Attempt);\r
721\r
722 if (IfrNvData->Enabled == ISCSI_DISABLED &&\r
723 Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
724\r
725 //\r
726 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".\r
727 //\r
728 if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
729 if (mPrivate->MpioCount < 1) {\r
730 return EFI_ABORTED;\r
731 }\r
732\r
733 if (--mPrivate->MpioCount == 0) {\r
734 mPrivate->EnableMpio = FALSE;\r
735 }\r
736 } else if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
737 if (mPrivate->SinglePathCount < 1) {\r
738 return EFI_ABORTED;\r
739 }\r
740 mPrivate->SinglePathCount--;\r
741 }\r
742\r
743 } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO &&\r
744 Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
745 //\r
746 // User updates the Attempt from "Enabled" to "Enabled for MPIO".\r
747 //\r
748 if (mPrivate->SinglePathCount < 1) {\r
749 return EFI_ABORTED;\r
750 }\r
751\r
752 mPrivate->EnableMpio = TRUE;\r
753 mPrivate->MpioCount++;\r
754 mPrivate->SinglePathCount--;\r
755\r
756 } else if (IfrNvData->Enabled == ISCSI_ENABLED &&\r
757 Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
758 //\r
759 // User updates the Attempt from "Enabled for MPIO" to "Enabled".\r
760 //\r
761 if (mPrivate->MpioCount < 1) {\r
762 return EFI_ABORTED;\r
763 }\r
764\r
765 if (--mPrivate->MpioCount == 0) {\r
766 mPrivate->EnableMpio = FALSE;\r
767 }\r
768 mPrivate->SinglePathCount++;\r
769\r
770 } else if (IfrNvData->Enabled != ISCSI_DISABLED &&\r
771 Attempt->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
772 //\r
773 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".\r
774 //\r
775 if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
776 mPrivate->EnableMpio = TRUE;\r
777 mPrivate->MpioCount++;\r
778\r
779 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {\r
780 mPrivate->SinglePathCount++;\r
781 }\r
782 }\r
783\r
c0d494b5 784 } else if (ExistAttempt == NULL) {\r
785 //\r
786 // When a new attempt is created, pointer of the attempt is saved to\r
787 // mPrivate->NewAttempt, and also saved to mCallbackInfo->Current in\r
788 // IScsiConfigProcessDefault. If input Attempt does not match any existing\r
789 // attempt, it should be a new created attempt. Save it to system now.\r
790 // \r
791 ASSERT (Attempt == mPrivate->NewAttempt);\r
792\r
793 //\r
794 // Save current order number for this attempt.\r
795 //\r
796 AttemptConfigOrder = IScsiGetVariableAndSize (\r
797 L"AttemptOrder",\r
9bdc6592 798 &gIScsiConfigGuid,\r
c0d494b5 799 &AttemptConfigOrderSize\r
800 );\r
801\r
802 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);\r
803 TotalNumber++;\r
804\r
805 //\r
806 // Append the new created attempt order to the end.\r
807 //\r
808 AttemptOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));\r
809 if (AttemptOrderTmp == NULL) {\r
810 if (AttemptConfigOrder != NULL) {\r
811 FreePool (AttemptConfigOrder);\r
812 }\r
813 return EFI_OUT_OF_RESOURCES;\r
814 }\r
815\r
816 if (AttemptConfigOrder != NULL) {\r
817 CopyMem (AttemptOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);\r
818 FreePool (AttemptConfigOrder);\r
819 }\r
820\r
821 AttemptOrderTmp[TotalNumber - 1] = Attempt->AttemptConfigIndex;\r
822 AttemptConfigOrder = AttemptOrderTmp;\r
823 AttemptConfigOrderSize = TotalNumber * sizeof (UINT8);\r
824\r
825 Status = gRT->SetVariable (\r
826 L"AttemptOrder",\r
9bdc6592 827 &gIScsiConfigGuid,\r
9c12f2d7 828 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
c0d494b5 829 AttemptConfigOrderSize,\r
830 AttemptConfigOrder\r
831 );\r
832 FreePool (AttemptConfigOrder);\r
833 if (EFI_ERROR (Status)) {\r
834 return Status;\r
835 }\r
836\r
837 //\r
838 // Insert new created attempt to array.\r
839 //\r
840 InsertTailList (&mPrivate->AttemptConfigs, &Attempt->Link);\r
841 mPrivate->AttemptCount++;\r
842 //\r
843 // Reset mPrivate->NewAttempt to NULL, which indicates none attempt is created\r
844 // but not saved now.\r
845 //\r
846 mPrivate->NewAttempt = NULL;\r
847\r
4c5a5e0c 848 if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
849 //\r
850 // This new Attempt is enabled for MPIO; enable the multipath mode.\r
851 //\r
852 mPrivate->EnableMpio = TRUE;\r
853 mPrivate->MpioCount++;\r
854 } else if (IfrNvData->Enabled == ISCSI_ENABLED) {\r
855 mPrivate->SinglePathCount++;\r
856 }\r
4c5a5e0c 857\r
c0d494b5 858 IScsiConfigUpdateAttempt ();\r
4c5a5e0c 859 }\r
860\r
861 //\r
862 // Record the user configuration information in NVR.\r
863 //\r
864 UnicodeSPrint (\r
865 mPrivate->PortString,\r
866 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
867 L"%s%d",\r
868 MacString,\r
869 (UINTN) Attempt->AttemptConfigIndex\r
870 );\r
871\r
872 FreePool (MacString);\r
873\r
874 return gRT->SetVariable (\r
875 mPrivate->PortString,\r
876 &gEfiIScsiInitiatorNameProtocolGuid,\r
877 ISCSI_CONFIG_VAR_ATTR,\r
878 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
879 Attempt\r
880 );\r
881}\r
882\r
883/**\r
884 Create Hii Extend Label OpCode as the start opcode and end opcode. It is \r
885 a help function.\r
886\r
887 @param[in] StartLabelNumber The number of start label.\r
888 @param[out] StartOpCodeHandle Points to the start opcode handle.\r
889 @param[out] StartLabel Points to the created start opcode.\r
890 @param[out] EndOpCodeHandle Points to the end opcode handle.\r
891 @param[out] EndLabel Points to the created end opcode.\r
892\r
893 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this\r
894 operation.\r
895 @retval EFI_INVALID_PARAMETER Any input parameter is invalid. \r
896 @retval EFI_SUCCESS The operation is completed successfully.\r
897\r
898**/\r
899EFI_STATUS\r
900IScsiCreateOpCode (\r
901 IN UINT16 StartLabelNumber,\r
902 OUT VOID **StartOpCodeHandle,\r
903 OUT EFI_IFR_GUID_LABEL **StartLabel,\r
904 OUT VOID **EndOpCodeHandle,\r
905 OUT EFI_IFR_GUID_LABEL **EndLabel\r
906 )\r
907{\r
908 EFI_STATUS Status;\r
909 EFI_IFR_GUID_LABEL *InternalStartLabel;\r
910 EFI_IFR_GUID_LABEL *InternalEndLabel;\r
911\r
912 if (StartOpCodeHandle == NULL || StartLabel == NULL || EndOpCodeHandle == NULL || EndLabel == NULL) {\r
913 return EFI_INVALID_PARAMETER;\r
914 }\r
915\r
916 *StartOpCodeHandle = NULL;\r
917 *EndOpCodeHandle = NULL;\r
918 Status = EFI_OUT_OF_RESOURCES;\r
919\r
920 //\r
921 // Initialize the container for dynamic opcodes.\r
922 //\r
923 *StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
924 if (*StartOpCodeHandle == NULL) {\r
925 return Status;\r
926 }\r
927\r
928 *EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
929 if (*EndOpCodeHandle == NULL) {\r
930 goto Exit;\r
931 }\r
932\r
933 //\r
934 // Create Hii Extend Label OpCode as the start opcode.\r
935 //\r
936 InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
937 *StartOpCodeHandle,\r
938 &gEfiIfrTianoGuid,\r
939 NULL,\r
940 sizeof (EFI_IFR_GUID_LABEL)\r
941 );\r
942 if (InternalStartLabel == NULL) {\r
943 goto Exit;\r
944 }\r
945 \r
946 InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
947 InternalStartLabel->Number = StartLabelNumber;\r
948\r
949 //\r
950 // Create Hii Extend Label OpCode as the end opcode.\r
951 //\r
952 InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
953 *EndOpCodeHandle,\r
954 &gEfiIfrTianoGuid,\r
955 NULL,\r
956 sizeof (EFI_IFR_GUID_LABEL)\r
957 );\r
958 if (InternalEndLabel == NULL) {\r
959 goto Exit;\r
960 }\r
961\r
962 InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
963 InternalEndLabel->Number = LABEL_END;\r
964\r
965 *StartLabel = InternalStartLabel;\r
966 *EndLabel = InternalEndLabel;\r
967\r
968 return EFI_SUCCESS;\r
969\r
970Exit:\r
971\r
972 if (*StartOpCodeHandle != NULL) {\r
973 HiiFreeOpCodeHandle (*StartOpCodeHandle);\r
974 }\r
975\r
976 if (*EndOpCodeHandle != NULL) {\r
977 HiiFreeOpCodeHandle (*EndOpCodeHandle);\r
978 }\r
979 \r
980 return Status;\r
981}\r
982\r
983/**\r
984 Callback function when user presses "Add an Attempt".\r
985\r
986 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this\r
987 operation.\r
988 @retval EFI_SUCCESS The operation is completed successfully.\r
989\r
990**/\r
991EFI_STATUS\r
992IScsiConfigAddAttempt (\r
993 VOID\r
994 )\r
995{\r
996 LIST_ENTRY *Entry;\r
997 ISCSI_NIC_INFO *NicInfo;\r
998 EFI_STRING_ID PortTitleToken;\r
999 EFI_STRING_ID PortTitleHelpToken;\r
1000 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
1001 EFI_STATUS Status;\r
1002 VOID *StartOpCodeHandle;\r
1003 EFI_IFR_GUID_LABEL *StartLabel;\r
1004 VOID *EndOpCodeHandle;\r
1005 EFI_IFR_GUID_LABEL *EndLabel;\r
1006\r
1007 Status = IScsiCreateOpCode (\r
1008 MAC_ENTRY_LABEL,\r
1009 &StartOpCodeHandle,\r
1010 &StartLabel,\r
1011 &EndOpCodeHandle,\r
1012 &EndLabel\r
1013 );\r
1014 if (EFI_ERROR (Status)) {\r
1015 return Status;\r
1016 }\r
1017\r
1018 //\r
1019 // Ask user to select a MAC for this attempt.\r
1020 //\r
1021 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
1022 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
1023 IScsiMacAddrToStr (\r
1024 &NicInfo->PermanentAddress,\r
1025 NicInfo->HwAddressSize,\r
1026 NicInfo->VlanId,\r
1027 MacString\r
1028 );\r
1029\r
c0d494b5 1030 UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"MAC %s", MacString);\r
4c5a5e0c 1031 PortTitleToken = HiiSetString (\r
1032 mCallbackInfo->RegisteredHandle,\r
1033 0,\r
1034 mPrivate->PortString,\r
1035 NULL\r
1036 );\r
1037 if (PortTitleToken == 0) {\r
1038 Status = EFI_INVALID_PARAMETER;\r
1039 goto Exit;\r
1040 }\r
1041\r
1042 UnicodeSPrint (\r
1043 mPrivate->PortString,\r
1044 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
1045 L"PFA: Bus %d | Dev %d | Func %d",\r
1046 NicInfo->BusNumber,\r
1047 NicInfo->DeviceNumber,\r
1048 NicInfo->FunctionNumber\r
1049 );\r
1050 PortTitleHelpToken = HiiSetString (mCallbackInfo->RegisteredHandle, 0, mPrivate->PortString, NULL);\r
1051 if (PortTitleHelpToken == 0) {\r
1052 Status = EFI_INVALID_PARAMETER;\r
1053 goto Exit; \r
1054 }\r
1055\r
1056 HiiCreateGotoOpCode (\r
1057 StartOpCodeHandle, // Container for dynamic created opcodes\r
1058 FORMID_ATTEMPT_FORM,\r
1059 PortTitleToken,\r
1060 PortTitleHelpToken,\r
1061 EFI_IFR_FLAG_CALLBACK, // Question flag\r
1062 (UINT16) (KEY_MAC_ENTRY_BASE + NicInfo->NicIndex)\r
1063 );\r
1064 }\r
1065\r
1066 Status = HiiUpdateForm (\r
1067 mCallbackInfo->RegisteredHandle, // HII handle\r
9bdc6592 1068 &gIScsiConfigGuid, // Formset GUID\r
4c5a5e0c 1069 FORMID_MAC_FORM, // Form ID\r
1070 StartOpCodeHandle, // Label for where to insert opcodes\r
1071 EndOpCodeHandle // Replace data\r
1072 );\r
1073\r
1074Exit:\r
1075 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1076 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1077 \r
1078 return Status;\r
1079}\r
1080\r
1081\r
1082/**\r
1083 Update the MAIN form to display the configured attempts.\r
1084\r
1085**/\r
1086VOID\r
1087IScsiConfigUpdateAttempt (\r
1088 VOID\r
1089 )\r
1090{\r
1091 CHAR16 AttemptName[ATTEMPT_NAME_MAX_SIZE];\r
1092 LIST_ENTRY *Entry;\r
1093 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
1094 VOID *StartOpCodeHandle;\r
1095 EFI_IFR_GUID_LABEL *StartLabel;\r
1096 VOID *EndOpCodeHandle;\r
1097 EFI_IFR_GUID_LABEL *EndLabel;\r
1098 EFI_STATUS Status;\r
1099\r
1100 Status = IScsiCreateOpCode (\r
1101 ATTEMPT_ENTRY_LABEL,\r
1102 &StartOpCodeHandle,\r
1103 &StartLabel,\r
1104 &EndOpCodeHandle,\r
1105 &EndLabel\r
1106 );\r
1107 if (EFI_ERROR (Status)) {\r
1108 return ;\r
1109 }\r
1110\r
1111 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
1112 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
1113\r
f256ab43 1114 AsciiStrToUnicodeStrS (AttemptConfigData->AttemptName, AttemptName, ARRAY_SIZE (AttemptName));\r
4c5a5e0c 1115 UnicodeSPrint (mPrivate->PortString, (UINTN) 128, L"Attempt %s", AttemptName);\r
1116 AttemptConfigData->AttemptTitleToken = HiiSetString (\r
1117 mCallbackInfo->RegisteredHandle,\r
1118 0,\r
1119 mPrivate->PortString,\r
1120 NULL\r
1121 );\r
1122 if (AttemptConfigData->AttemptTitleToken == 0) {\r
1123 return ;\r
1124 }\r
1125\r
1126 HiiCreateGotoOpCode (\r
1127 StartOpCodeHandle, // Container for dynamic created opcodes\r
1128 FORMID_ATTEMPT_FORM, // Form ID\r
1129 AttemptConfigData->AttemptTitleToken, // Prompt text\r
1130 AttemptConfigData->AttemptTitleHelpToken, // Help text\r
1131 EFI_IFR_FLAG_CALLBACK, // Question flag\r
1132 (UINT16) (KEY_ATTEMPT_ENTRY_BASE + AttemptConfigData->AttemptConfigIndex) // Question ID\r
1133 );\r
1134 }\r
1135\r
1136 HiiUpdateForm (\r
1137 mCallbackInfo->RegisteredHandle, // HII handle\r
9bdc6592 1138 &gIScsiConfigGuid, // Formset GUID\r
4c5a5e0c 1139 FORMID_MAIN_FORM, // Form ID\r
1140 StartOpCodeHandle, // Label for where to insert opcodes\r
1141 EndOpCodeHandle // Replace data\r
1142 ); \r
1143\r
1144 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1145 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1146}\r
1147\r
1148\r
1149/**\r
1150 Callback function when user presses "Commit Changes and Exit" in Delete Attempts.\r
1151\r
1152 @param[in] IfrNvData The IFR NV data.\r
1153\r
1154 @retval EFI_NOT_FOUND Cannot find the corresponding variable.\r
1155 @retval EFI_SUCCESS The operation is completed successfully.\r
1156 @retval EFI_ABOTRED This operation is aborted cause of error\r
1157 configuration.\r
1158 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of\r
1159 resources.\r
1160\r
1161**/\r
1162EFI_STATUS\r
1163IScsiConfigDeleteAttempts (\r
1164 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
1165 )\r
1166{\r
1167 EFI_STATUS Status;\r
1168 UINTN Index;\r
1169 UINTN NewIndex;\r
1170 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
1171 UINT8 *AttemptConfigOrder;\r
1172 UINTN AttemptConfigOrderSize;\r
1173 UINT8 *AttemptNewOrder;\r
1174 UINT32 Attribute;\r
1175 UINTN Total;\r
1176 UINTN NewTotal;\r
1177 LIST_ENTRY *Entry;\r
1178 LIST_ENTRY *NextEntry;\r
1179 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
1180\r
1181 AttemptConfigOrder = IScsiGetVariableAndSize (\r
1182 L"AttemptOrder",\r
9bdc6592 1183 &gIScsiConfigGuid,\r
4c5a5e0c 1184 &AttemptConfigOrderSize\r
1185 );\r
1186 if ((AttemptConfigOrder == NULL) || (AttemptConfigOrderSize == 0)) {\r
1187 return EFI_NOT_FOUND;\r
1188 }\r
1189\r
1190 AttemptNewOrder = AllocateZeroPool (AttemptConfigOrderSize);\r
1191 if (AttemptNewOrder == NULL) {\r
c0d494b5 1192 Status = EFI_OUT_OF_RESOURCES;\r
1193 goto Error;\r
4c5a5e0c 1194 }\r
1195\r
1196 Total = AttemptConfigOrderSize / sizeof (UINT8);\r
1197 NewTotal = Total;\r
1198 Index = 0;\r
1199\r
1200 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {\r
1201 if (IfrNvData->DeleteAttemptList[Index] == 0) {\r
1202 Index++;\r
1203 continue;\r
1204 }\r
1205\r
1206 //\r
1207 // Delete the attempt.\r
1208 //\r
1209\r
1210 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
1211 if (AttemptConfigData == NULL) {\r
1212 Status = EFI_NOT_FOUND;\r
1213 goto Error;\r
1214 }\r
1215\r
1216 //\r
1217 // Remove this attempt from UI configured attempt list.\r
1218 //\r
1219 RemoveEntryList (&AttemptConfigData->Link);\r
1220 mPrivate->AttemptCount--;\r
1221\r
1222 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
1223 if (mPrivate->MpioCount < 1) {\r
1224 Status = EFI_ABORTED;\r
1225 goto Error;\r
1226 }\r
1227\r
1228 //\r
1229 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.\r
1230 //\r
1231 if (--mPrivate->MpioCount == 0) {\r
1232 mPrivate->EnableMpio = FALSE;\r
1233 }\r
1234 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
1235 if (mPrivate->SinglePathCount < 1) {\r
1236 Status = EFI_ABORTED;\r
1237 goto Error;\r
1238 }\r
1239\r
1240 mPrivate->SinglePathCount--;\r
1241 }\r
1242\r
f256ab43 1243 AsciiStrToUnicodeStrS (AttemptConfigData->MacString, MacString, ARRAY_SIZE (MacString));\r
4c5a5e0c 1244\r
1245 UnicodeSPrint (\r
1246 mPrivate->PortString,\r
1247 (UINTN) 128,\r
1248 L"%s%d",\r
1249 MacString,\r
1250 (UINTN) AttemptConfigData->AttemptConfigIndex\r
1251 );\r
1252\r
1253 gRT->SetVariable (\r
1254 mPrivate->PortString,\r
1255 &gEfiIScsiInitiatorNameProtocolGuid,\r
1256 0,\r
1257 0,\r
1258 NULL\r
1259 );\r
1260\r
1261 //\r
1262 // Mark the attempt order in NVR to be deleted - 0.\r
1263 //\r
1264 for (NewIndex = 0; NewIndex < Total; NewIndex++) {\r
1265 if (AttemptConfigOrder[NewIndex] == AttemptConfigData->AttemptConfigIndex) {\r
1266 AttemptConfigOrder[NewIndex] = 0;\r
1267 break;\r
1268 }\r
1269 }\r
1270\r
1271 NewTotal--;\r
1272 FreePool (AttemptConfigData);\r
1273\r
1274 //\r
1275 // Check next Attempt.\r
1276 //\r
1277 Index++;\r
1278 }\r
1279\r
1280 //\r
1281 // Construct AttemptNewOrder.\r
1282 //\r
1283 for (Index = 0, NewIndex = 0; Index < Total; Index++) {\r
1284 if (AttemptConfigOrder[Index] != 0) {\r
1285 AttemptNewOrder[NewIndex] = AttemptConfigOrder[Index];\r
1286 NewIndex++;\r
1287 }\r
1288 }\r
1289\r
9c12f2d7 1290 Attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
4c5a5e0c 1291\r
1292 //\r
1293 // Update AttemptOrder in NVR.\r
1294 //\r
1295 Status = gRT->SetVariable (\r
1296 L"AttemptOrder",\r
9bdc6592 1297 &gIScsiConfigGuid,\r
4c5a5e0c 1298 Attribute,\r
1299 NewTotal * sizeof (UINT8),\r
1300 AttemptNewOrder\r
1301 );\r
1302\r
1303Error:\r
c0d494b5 1304 if (AttemptConfigOrder != NULL) {\r
1305 FreePool (AttemptConfigOrder);\r
1306 }\r
1307\r
1308 if (AttemptNewOrder != NULL) {\r
1309 FreePool (AttemptNewOrder);\r
1310 }\r
4c5a5e0c 1311 \r
1312 return Status;\r
1313}\r
1314\r
1315\r
1316/**\r
1317 Callback function when user presses "Delete Attempts".\r
1318\r
1319 @param[in] IfrNvData The IFR nv data.\r
1320\r
1321 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
1322 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.\r
1323 @retval EFI_SUCCESS The operation is completed successfully.\r
1324\r
1325**/\r
1326EFI_STATUS\r
1327IScsiConfigDisplayDeleteAttempts (\r
1328 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
1329 )\r
1330{\r
1331\r
1332 UINT8 *AttemptConfigOrder;\r
1333 UINTN AttemptConfigOrderSize;\r
1334 LIST_ENTRY *Entry;\r
1335 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
1336 UINT8 Index;\r
1337 VOID *StartOpCodeHandle;\r
1338 EFI_IFR_GUID_LABEL *StartLabel;\r
1339 VOID *EndOpCodeHandle;\r
1340 EFI_IFR_GUID_LABEL *EndLabel;\r
1341 EFI_STATUS Status;\r
1342\r
1343 Status = IScsiCreateOpCode (\r
1344 DELETE_ENTRY_LABEL,\r
1345 &StartOpCodeHandle,\r
1346 &StartLabel,\r
1347 &EndOpCodeHandle,\r
1348 &EndLabel\r
1349 );\r
1350 if (EFI_ERROR (Status)) {\r
1351 return Status;\r
1352 }\r
1353\r
1354 AttemptConfigOrder = IScsiGetVariableAndSize (\r
1355 L"AttemptOrder",\r
9bdc6592 1356 &gIScsiConfigGuid,\r
4c5a5e0c 1357 &AttemptConfigOrderSize\r
1358 );\r
1359 if (AttemptConfigOrder != NULL) {\r
1360 //\r
1361 // Create the check box opcode to be deleted.\r
1362 //\r
1363 Index = 0;\r
1364\r
1365 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
1366 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
1367 IfrNvData->DeleteAttemptList[Index] = 0x00;\r
1368\r
1369 HiiCreateCheckBoxOpCode(\r
1370 StartOpCodeHandle,\r
1371 (EFI_QUESTION_ID) (ATTEMPT_DEL_QUESTION_ID + Index),\r
1372 CONFIGURATION_VARSTORE_ID,\r
1373 (UINT16) (ATTEMPT_DEL_VAR_OFFSET + Index),\r
1374 AttemptConfigData->AttemptTitleToken,\r
1375 AttemptConfigData->AttemptTitleHelpToken,\r
1376 0,\r
1377 0,\r
1378 NULL\r
1379 );\r
1380\r
1381 Index++;\r
1382\r
1383 if (Index == ISCSI_MAX_ATTEMPTS_NUM) {\r
1384 break;\r
1385 }\r
1386 }\r
1387\r
1388 FreePool (AttemptConfigOrder);\r
1389 }\r
1390\r
1391 Status = HiiUpdateForm (\r
1392 mCallbackInfo->RegisteredHandle, // HII handle\r
9bdc6592 1393 &gIScsiConfigGuid, // Formset GUID\r
4c5a5e0c 1394 FORMID_DELETE_FORM, // Form ID\r
1395 StartOpCodeHandle, // Label for where to insert opcodes\r
1396 EndOpCodeHandle // Replace data\r
1397 ); \r
1398\r
1399 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1400 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1401\r
1402 return Status;\r
1403}\r
1404\r
1405\r
1406/**\r
1407 Callback function when user presses "Change Attempt Order".\r
1408\r
1409 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
1410 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this\r
1411 operation.\r
1412 @retval EFI_SUCCESS The operation is completed successfully.\r
1413\r
1414**/\r
1415EFI_STATUS\r
1416IScsiConfigDisplayOrderAttempts (\r
1417 VOID\r
1418 )\r
1419{\r
1420 EFI_STATUS Status;\r
1421 UINT8 Index;\r
1422 LIST_ENTRY *Entry;\r
1423 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
1424 VOID *StartOpCodeHandle;\r
1425 EFI_IFR_GUID_LABEL *StartLabel;\r
1426 VOID *EndOpCodeHandle;\r
1427 EFI_IFR_GUID_LABEL *EndLabel;\r
1428 VOID *OptionsOpCodeHandle; \r
1429 \r
1430 Status = IScsiCreateOpCode (\r
1431 ORDER_ENTRY_LABEL,\r
1432 &StartOpCodeHandle,\r
1433 &StartLabel,\r
1434 &EndOpCodeHandle,\r
1435 &EndLabel\r
1436 );\r
1437 if (EFI_ERROR (Status)) {\r
1438 return Status;\r
1439 }\r
7a49cd08 1440 ASSERT (StartOpCodeHandle != NULL);\r
4c5a5e0c 1441\r
1442 OptionsOpCodeHandle = NULL;\r
1443\r
1444 //\r
1445 // If no attempt to be ordered, update the original form and exit.\r
1446 //\r
1447 if (mPrivate->AttemptCount == 0) {\r
1448 goto Exit;\r
1449 }\r
1450\r
1451 //\r
1452 // Create Option OpCode.\r
1453 //\r
1454 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1455 if (OptionsOpCodeHandle == NULL) {\r
1456 Status = EFI_OUT_OF_RESOURCES;\r
1457 goto Error;\r
1458 }\r
1459\r
1460 Index = 0;\r
1461\r
1462 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
1463 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
1464 HiiCreateOneOfOptionOpCode (\r
1465 OptionsOpCodeHandle,\r
1466 AttemptConfigData->AttemptTitleToken,\r
1467 0,\r
1468 EFI_IFR_NUMERIC_SIZE_1,\r
1469 AttemptConfigData->AttemptConfigIndex\r
1470 );\r
1471 Index++;\r
1472 }\r
1473\r
1474 ASSERT (Index == mPrivate->AttemptCount);\r
1475\r
1476 HiiCreateOrderedListOpCode (\r
1477 StartOpCodeHandle, // Container for dynamic created opcodes\r
1478 DYNAMIC_ORDERED_LIST_QUESTION_ID, // Question ID\r
1479 CONFIGURATION_VARSTORE_ID, // VarStore ID\r
1480 DYNAMIC_ORDERED_LIST_VAR_OFFSET, // Offset in Buffer Storage\r
1481 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY), // Question prompt text \r
1482 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY), // Question help text \r
1483 0, // Question flag\r
1484 EFI_IFR_UNIQUE_SET, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET\r
1485 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question value\r
1486 ISCSI_MAX_ATTEMPTS_NUM, // Maximum container\r
1487 OptionsOpCodeHandle, // Option Opcode list \r
1488 NULL // Default Opcode is NULL \r
1489 );\r
1490\r
1491Exit:\r
1492 Status = HiiUpdateForm (\r
1493 mCallbackInfo->RegisteredHandle, // HII handle\r
9bdc6592 1494 &gIScsiConfigGuid, // Formset GUID\r
4c5a5e0c 1495 FORMID_ORDER_FORM, // Form ID\r
1496 StartOpCodeHandle, // Label for where to insert opcodes\r
1497 EndOpCodeHandle // Replace data\r
1498 ); \r
1499\r
1500Error:\r
1501 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1502 HiiFreeOpCodeHandle (EndOpCodeHandle); \r
1503 if (OptionsOpCodeHandle != NULL) {\r
1504 HiiFreeOpCodeHandle (OptionsOpCodeHandle);\r
1505 }\r
1506\r
1507 return Status;\r
1508}\r
1509\r
1510\r
1511/**\r
1512 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order.\r
1513\r
1514 @param[in] IfrNvData The IFR nv data.\r
1515\r
1516 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this\r
1517 operation.\r
1518 @retval EFI_NOT_FOUND Cannot find the corresponding variable.\r
1519 @retval EFI_SUCCESS The operation is completed successfully.\r
1520\r
1521**/\r
1522EFI_STATUS\r
1523IScsiConfigOrderAttempts (\r
1524 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
1525 )\r
1526{\r
1527 EFI_STATUS Status;\r
1528 UINTN Index;\r
1529 UINTN Indexj;\r
1530 UINT8 AttemptConfigIndex;\r
1531 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
1532 UINT8 *AttemptConfigOrder;\r
1533 UINT8 *AttemptConfigOrderTmp;\r
1534 UINTN AttemptConfigOrderSize;\r
1535\r
1536 AttemptConfigOrder = IScsiGetVariableAndSize (\r
1537 L"AttemptOrder",\r
9bdc6592 1538 &gIScsiConfigGuid,\r
4c5a5e0c 1539 &AttemptConfigOrderSize\r
1540 );\r
1541 if (AttemptConfigOrder == NULL) {\r
1542 return EFI_NOT_FOUND;\r
1543 }\r
1544\r
1545 AttemptConfigOrderTmp = AllocateZeroPool (AttemptConfigOrderSize);\r
1546 if (AttemptConfigOrderTmp == NULL) {\r
1547 Status = EFI_OUT_OF_RESOURCES;\r
1548 goto Exit;\r
1549 }\r
1550\r
1551 for (Index = 0; Index < ISCSI_MAX_ATTEMPTS_NUM; Index++) {\r
1552 //\r
1553 // The real content ends with 0.\r
1554 //\r
1555 if (IfrNvData->DynamicOrderedList[Index] == 0) {\r
1556 break;\r
1557 }\r
1558\r
1559 AttemptConfigIndex = IfrNvData->DynamicOrderedList[Index];\r
1560 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex);\r
1561 if (AttemptConfigData == NULL) {\r
1562 Status = EFI_NOT_FOUND;\r
1563 goto Exit;\r
1564 }\r
1565\r
1566 //\r
1567 // Reorder the Attempt List.\r
1568 //\r
1569 RemoveEntryList (&AttemptConfigData->Link);\r
1570 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);\r
1571\r
1572 AttemptConfigOrderTmp[Index] = AttemptConfigIndex;\r
1573\r
1574 //\r
1575 // Mark it to be deleted - 0.\r
1576 //\r
1577 for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) {\r
1578 if (AttemptConfigOrder[Indexj] == AttemptConfigIndex) {\r
1579 AttemptConfigOrder[Indexj] = 0;\r
1580 break;\r
1581 }\r
1582 }\r
1583 }\r
1584\r
1585 //\r
1586 // Adjust the attempt order in NVR.\r
1587 //\r
1588 for (; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
1589 for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) {\r
1590 if (AttemptConfigOrder[Indexj] != 0) {\r
1591 AttemptConfigOrderTmp[Index] = AttemptConfigOrder[Indexj];\r
1592 AttemptConfigOrder[Indexj] = 0;\r
1593 continue;\r
1594 }\r
1595 }\r
1596 }\r
1597\r
1598 Status = gRT->SetVariable (\r
1599 L"AttemptOrder",\r
9bdc6592 1600 &gIScsiConfigGuid,\r
9c12f2d7 1601 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
4c5a5e0c 1602 AttemptConfigOrderSize,\r
1603 AttemptConfigOrderTmp\r
1604 );\r
1605\r
1606Exit:\r
1607 if (AttemptConfigOrderTmp != NULL) {\r
1608 FreePool (AttemptConfigOrderTmp);\r
1609 }\r
1610\r
1611 FreePool (AttemptConfigOrder);\r
1612 return Status;\r
1613}\r
1614\r
1615\r
1616/**\r
1617 Callback function when a user presses "Attempt *" or when a user selects a NIC to\r
1618 create the new attempt.\r
1619\r
1620 @param[in] KeyValue A unique value which is sent to the original\r
1621 exporting driver so that it can identify the type\r
1622 of data to expect.\r
1623 @param[in] IfrNvData The IFR nv data.\r
1624\r
1625 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this\r
1626 operation.\r
1627 @retval EFI_NOT_FOUND Cannot find the corresponding variable.\r
1628 @retval EFI_SUCCESS The operation is completed successfully.\r
1629\r
1630**/\r
1631EFI_STATUS\r
1632IScsiConfigProcessDefault (\r
1633 IN EFI_QUESTION_ID KeyValue,\r
1634 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
1635 )\r
1636{\r
1637 BOOLEAN NewAttempt;\r
1638 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
1639 ISCSI_SESSION_CONFIG_NVDATA *ConfigData;\r
1640 UINT8 CurrentAttemptConfigIndex;\r
1641 ISCSI_NIC_INFO *NicInfo;\r
1642 UINT8 NicIndex;\r
1643 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
1644 UINT8 *AttemptConfigOrder;\r
1645 UINTN AttemptConfigOrderSize;\r
1646 UINTN TotalNumber;\r
4c5a5e0c 1647 UINTN Index;\r
4c5a5e0c 1648\r
c0d494b5 1649 //\r
1650 // Is User creating a new attempt?\r
1651 //\r
4c5a5e0c 1652 NewAttempt = FALSE;\r
1653\r
1654 if ((KeyValue >= KEY_MAC_ENTRY_BASE) &&\r
1655 (KeyValue <= (UINT16) (mPrivate->MaxNic + KEY_MAC_ENTRY_BASE))) {\r
1656 //\r
1657 // User has pressed "Add an Attempt" and then selects a NIC.\r
1658 //\r
1659 NewAttempt = TRUE;\r
1660 } else if ((KeyValue >= KEY_ATTEMPT_ENTRY_BASE) &&\r
1661 (KeyValue < (ISCSI_MAX_ATTEMPTS_NUM + KEY_ATTEMPT_ENTRY_BASE))) {\r
1662\r
1663 //\r
1664 // User has pressed "Attempt *".\r
1665 //\r
1666 NewAttempt = FALSE;\r
1667 } else {\r
1668 //\r
1669 // Don't process anything.\r
1670 //\r
1671 return EFI_SUCCESS;\r
1672 }\r
639a76d1
ED
1673 \r
1674 //\r
1675 // Free any attempt that is previously created but not saved to system.\r
1676 //\r
1677 if (mPrivate->NewAttempt != NULL) {\r
1678 FreePool (mPrivate->NewAttempt);\r
1679 mPrivate->NewAttempt = NULL;\r
1680 }\r
4c5a5e0c 1681\r
1682 if (NewAttempt) {\r
1683 //\r
1684 // Determine which NIC user has selected for the new created attempt.\r
1685 //\r
1686 NicIndex = (UINT8) (KeyValue - KEY_MAC_ENTRY_BASE);\r
1687 NicInfo = IScsiGetNicInfoByIndex (NicIndex);\r
1688 if (NicInfo == NULL) {\r
1689 return EFI_NOT_FOUND;\r
1690 }\r
1691 \r
1692 //\r
c0d494b5 1693 // Create new attempt.\r
4c5a5e0c 1694 //\r
1695\r
1696 AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA));\r
1697 if (AttemptConfigData == NULL) {\r
1698 return EFI_OUT_OF_RESOURCES;\r
1699 }\r
1700\r
1701 ConfigData = &AttemptConfigData->SessionConfigData;\r
1702 ConfigData->TargetPort = ISCSI_WELL_KNOWN_PORT;\r
1703 ConfigData->ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;\r
1704 ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY;\r
1705\r
1706 AttemptConfigData->AuthenticationType = ISCSI_AUTH_TYPE_CHAP;\r
1707 AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI;\r
1708\r
1709 //\r
1710 // Get current order number for this attempt.\r
1711 //\r
1712 AttemptConfigOrder = IScsiGetVariableAndSize (\r
1713 L"AttemptOrder",\r
9bdc6592 1714 &gIScsiConfigGuid,\r
4c5a5e0c 1715 &AttemptConfigOrderSize\r
1716 );\r
1717\r
1718 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);\r
1719\r
1720 if (AttemptConfigOrder == NULL) {\r
1721 CurrentAttemptConfigIndex = 1;\r
1722 } else {\r
1723 //\r
1724 // Get the max attempt config index.\r
1725 //\r
1726 CurrentAttemptConfigIndex = AttemptConfigOrder[0];\r
1727 for (Index = 1; Index < TotalNumber; Index++) {\r
1728 if (CurrentAttemptConfigIndex < AttemptConfigOrder[Index]) {\r
1729 CurrentAttemptConfigIndex = AttemptConfigOrder[Index];\r
1730 }\r
1731 }\r
1732\r
1733 CurrentAttemptConfigIndex++;\r
1734 }\r
1735\r
1736 TotalNumber++;\r
1737\r
1738 //\r
c0d494b5 1739 // Record the mapping between attempt order and attempt's configdata.\r
4c5a5e0c 1740 //\r
c0d494b5 1741 AttemptConfigData->AttemptConfigIndex = CurrentAttemptConfigIndex;\r
4c5a5e0c 1742\r
1743 if (AttemptConfigOrder != NULL) {\r
c0d494b5 1744 FreePool (AttemptConfigOrder);\r
4c5a5e0c 1745 }\r
1746\r
4c5a5e0c 1747 //\r
1748 // Record the MAC info in Config Data.\r
1749 //\r
1750 IScsiMacAddrToStr (\r
1751 &NicInfo->PermanentAddress,\r
1752 NicInfo->HwAddressSize,\r
1753 NicInfo->VlanId,\r
1754 MacString\r
1755 );\r
1756\r
b9679cd7 1757 UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, sizeof (AttemptConfigData->MacString));\r
4c5a5e0c 1758 AttemptConfigData->NicIndex = NicIndex;\r
1759\r
1760 //\r
1761 // Generate OUI-format ISID based on MAC address.\r
1762 //\r
1763 CopyMem (AttemptConfigData->SessionConfigData.IsId, &NicInfo->PermanentAddress, 6);\r
1764 AttemptConfigData->SessionConfigData.IsId[0] = \r
1765 (UINT8) (AttemptConfigData->SessionConfigData.IsId[0] & 0x3F);\r
1766\r
1767 //\r
1768 // Add the help info for the new attempt.\r
1769 //\r
1770 UnicodeSPrint (\r
1771 mPrivate->PortString,\r
1772 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
1773 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d",\r
1774 MacString,\r
1775 NicInfo->BusNumber,\r
1776 NicInfo->DeviceNumber,\r
1777 NicInfo->FunctionNumber\r
1778 );\r
1779\r
1780 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (\r
1781 mCallbackInfo->RegisteredHandle,\r
1782 0,\r
1783 mPrivate->PortString,\r
1784 NULL\r
1785 );\r
1786 if (AttemptConfigData->AttemptTitleHelpToken == 0) {\r
1787 FreePool (AttemptConfigData);\r
1788 return EFI_INVALID_PARAMETER;\r
1789 }\r
1790\r
1791 //\r
1792 // Set the attempt name to default.\r
1793 //\r
1794 UnicodeSPrint (\r
1795 mPrivate->PortString,\r
1796 (UINTN) 128,\r
1797 L"%d",\r
1798 (UINTN) AttemptConfigData->AttemptConfigIndex\r
1799 );\r
b9679cd7 1800 UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, sizeof (AttemptConfigData->AttemptName));\r
4c5a5e0c 1801\r
c0d494b5 1802 //\r
1803 // Save the created Attempt temporarily. If user does not save the attempt\r
1804 // by press 'KEY_SAVE_ATTEMPT_CONFIG' later, iSCSI driver would know that\r
1805 // and free resources.\r
1806 //\r
1807 mPrivate->NewAttempt = (VOID *) AttemptConfigData;\r
1808\r
4c5a5e0c 1809 } else {\r
1810 //\r
1811 // Determine which Attempt user has selected to configure.\r
1812 // Get the attempt configuration data.\r
1813 //\r
1814 CurrentAttemptConfigIndex = (UINT8) (KeyValue - KEY_ATTEMPT_ENTRY_BASE);\r
1815\r
1816 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex);\r
1817 if (AttemptConfigData == NULL) {\r
1818 DEBUG ((DEBUG_ERROR, "Corresponding configuration data can not be retrieved!\n"));\r
1819 return EFI_NOT_FOUND;\r
1820 }\r
1821 }\r
1822\r
1823 //\r
1824 // Clear the old IFR data to avoid sharing it with other attempts.\r
1825 //\r
1826 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
1827 ZeroMem (IfrNvData->CHAPName, sizeof (IfrNvData->CHAPName));\r
1828 ZeroMem (IfrNvData->CHAPSecret, sizeof (IfrNvData->CHAPSecret));\r
1829 ZeroMem (IfrNvData->ReverseCHAPName, sizeof (IfrNvData->ReverseCHAPName));\r
1830 ZeroMem (IfrNvData->ReverseCHAPSecret, sizeof (IfrNvData->ReverseCHAPSecret));\r
1831 }\r
1832 \r
1833 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData, IfrNvData);\r
1834\r
c0d494b5 1835 //\r
1836 // Update current attempt to be a new created attempt or an existing attempt.\r
1837 //\r
4c5a5e0c 1838 mCallbackInfo->Current = AttemptConfigData;\r
1839\r
4c5a5e0c 1840 return EFI_SUCCESS;\r
1841}\r
1842\r
1843\r
1844/**\r
1845 \r
1846 This function allows the caller to request the current\r
1847 configuration for one or more named elements. The resulting\r
1848 string is in <ConfigAltResp> format. Also, any and all alternative\r
1849 configuration strings shall be appended to the end of the\r
1850 current configuration string. If they are, they must appear\r
1851 after the current configuration. They must contain the same\r
1852 routing (GUID, NAME, PATH) as the current configuration string.\r
1853 They must have an additional description indicating the type of\r
1854 alternative configuration the string represents,\r
1855 "ALTCFG=<StringToken>". That <StringToken> (when\r
1856 converted from Hex UNICODE to binary) is a reference to a\r
1857 string in the associated string pack.\r
1858\r
1859 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1860\r
1861 @param[in] Request A null-terminated Unicode string in\r
1862 <ConfigRequest> format. Note that this\r
1863 includes the routing information as well as\r
1864 the configurable name / value pairs. It is\r
1865 invalid for this string to be in\r
1866 <MultiConfigRequest> format.\r
1867\r
1868 @param[out] Progress On return, points to a character in the\r
1869 Request string. Points to the string's null\r
1870 terminator if request was successful. Points\r
1871 to the most recent "&" before the first\r
1872 failing name / value pair (or the beginning\r
1873 of the string if the failure is in the first\r
1874 name / value pair) if the request was not successful. \r
1875\r
1876 @param[out] Results A null-terminated Unicode string in\r
1877 <ConfigAltResp> format which has all values\r
1878 filled in for the names in the Request string.\r
1879 String to be allocated by the called function.\r
1880\r
1881 @retval EFI_SUCCESS The Results string is filled with the\r
1882 values corresponding to all requested\r
1883 names.\r
1884\r
1885 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
1886 parts of the results that must be\r
1887 stored awaiting possible future\r
1888 protocols.\r
1889\r
1890 @retval EFI_INVALID_PARAMETER For example, passing in a NULL\r
1891 for the Request parameter\r
1892 would result in this type of\r
1893 error. In this case, the\r
1894 Progress parameter would be\r
1895 set to NULL. \r
1896\r
1897 @retval EFI_NOT_FOUND Routing data doesn't match any\r
1898 known driver. Progress set to the\r
1899 first character in the routing header.\r
1900 Note: There is no requirement that the\r
1901 driver validate the routing data. It\r
1902 must skip the <ConfigHdr> in order to\r
1903 process the names.\r
1904\r
1905 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set\r
1906 to most recent "&" before the\r
1907 error or the beginning of the\r
1908 string.\r
1909\r
1910 @retval EFI_INVALID_PARAMETER Unknown name. Progress points\r
1911 to the & before the name in\r
1912 question.\r
1913\r
1914**/\r
1915EFI_STATUS\r
1916EFIAPI\r
1917IScsiFormExtractConfig (\r
1918 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1919 IN CONST EFI_STRING Request,\r
1920 OUT EFI_STRING *Progress,\r
1921 OUT EFI_STRING *Results\r
1922 )\r
1923{\r
1924 EFI_STATUS Status;\r
1925 CHAR8 *InitiatorName;\r
1926 UINTN BufferSize;\r
1927 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
1928 ISCSI_FORM_CALLBACK_INFO *Private;\r
1929 EFI_STRING ConfigRequestHdr;\r
1930 EFI_STRING ConfigRequest;\r
1931 BOOLEAN AllocatedRequest;\r
1932 UINTN Size;\r
1933\r
1934 if (This == NULL || Progress == NULL || Results == NULL) {\r
1935 return EFI_INVALID_PARAMETER;\r
1936 }\r
1937\r
1938 *Progress = Request;\r
9bdc6592 1939 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gIScsiConfigGuid, mVendorStorageName)) {\r
4c5a5e0c 1940 return EFI_NOT_FOUND;\r
1941 }\r
1942\r
1943 ConfigRequestHdr = NULL;\r
1944 ConfigRequest = NULL;\r
1945 AllocatedRequest = FALSE;\r
1946 Size = 0;\r
1947\r
1948 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
1949 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
1950 if (IfrNvData == NULL) {\r
1951 return EFI_OUT_OF_RESOURCES;\r
1952 }\r
1953 \r
1954 if (Private->Current != NULL) {\r
1955 IScsiConvertAttemptConfigDataToIfrNvData (Private->Current, IfrNvData);\r
1956 }\r
1957\r
1958 BufferSize = ISCSI_NAME_MAX_SIZE;\r
1959 InitiatorName = (CHAR8 *) AllocateZeroPool (BufferSize);\r
1960 if (InitiatorName == NULL) {\r
1961 FreePool (IfrNvData);\r
1962 return EFI_OUT_OF_RESOURCES;\r
1963 }\r
1964 \r
1965 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
1966 if (EFI_ERROR (Status)) {\r
1967 IfrNvData->InitiatorName[0] = L'\0';\r
1968 } else {\r
b9679cd7
SZ
1969 AsciiStrToUnicodeStrS (\r
1970 InitiatorName,\r
1971 IfrNvData->InitiatorName,\r
1972 sizeof (IfrNvData->InitiatorName) / sizeof (IfrNvData->InitiatorName[0])\r
1973 );\r
4c5a5e0c 1974 }\r
1975\r
1976 //\r
1977 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().\r
1978 //\r
1979 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
1980 ConfigRequest = Request;\r
1981 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
1982 //\r
1983 // Request has no request element, construct full request string.\r
1984 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
1985 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
1986 //\r
9bdc6592 1987 ConfigRequestHdr = HiiConstructConfigHdr (&gIScsiConfigGuid, mVendorStorageName, Private->DriverHandle);\r
4c5a5e0c 1988 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
1989 ConfigRequest = AllocateZeroPool (Size);\r
7c275b3c
ZL
1990 if (ConfigRequest == NULL) {\r
1991 FreePool (IfrNvData);\r
1992 FreePool (InitiatorName);\r
1993 return EFI_OUT_OF_RESOURCES;\r
1994 }\r
4c5a5e0c 1995 AllocatedRequest = TRUE;\r
1996 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
1997 FreePool (ConfigRequestHdr);\r
1998 }\r
1999\r
2000 Status = gHiiConfigRouting->BlockToConfig (\r
2001 gHiiConfigRouting,\r
2002 ConfigRequest,\r
2003 (UINT8 *) IfrNvData,\r
2004 BufferSize,\r
2005 Results,\r
2006 Progress\r
2007 );\r
2008 FreePool (IfrNvData);\r
2009 FreePool (InitiatorName);\r
2010\r
2011 //\r
2012 // Free the allocated config request string.\r
2013 //\r
2014 if (AllocatedRequest) {\r
2015 FreePool (ConfigRequest);\r
2016 ConfigRequest = NULL;\r
2017 }\r
2018 //\r
2019 // Set Progress string to the original request string.\r
2020 //\r
2021 if (Request == NULL) {\r
2022 *Progress = NULL;\r
2023 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
2024 *Progress = Request + StrLen (Request);\r
2025 }\r
2026\r
2027 return Status;\r
2028}\r
2029\r
2030\r
2031/**\r
2032 \r
2033 This function applies changes in a driver's configuration.\r
2034 Input is a Configuration, which has the routing data for this\r
2035 driver followed by name / value configuration pairs. The driver\r
2036 must apply those pairs to its configurable storage. If the\r
2037 driver's configuration is stored in a linear block of data\r
2038 and the driver's name / value pairs are in <BlockConfig>\r
2039 format, it may use the ConfigToBlock helper function (above) to\r
2040 simplify the job.\r
2041\r
2042 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2043\r
2044 @param[in] Configuration A null-terminated Unicode string in\r
2045 <ConfigString> format. \r
2046 \r
2047 @param[out] Progress A pointer to a string filled in with the\r
2048 offset of the most recent '&' before the\r
2049 first failing name / value pair (or the\r
2050 beginning of the string if the failure\r
2051 is in the first name / value pair) or\r
2052 the terminating NULL if all was\r
2053 successful.\r
2054\r
2055 @retval EFI_SUCCESS The results have been distributed or are\r
2056 awaiting distribution.\r
2057 \r
2058 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
2059 parts of the results that must be\r
2060 stored awaiting possible future\r
2061 protocols.\r
2062 \r
2063 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
2064 Results parameter would result\r
2065 in this type of error.\r
2066 \r
2067 @retval EFI_NOT_FOUND Target for the specified routing data\r
2068 was not found.\r
2069\r
2070**/\r
2071EFI_STATUS\r
2072EFIAPI\r
2073IScsiFormRouteConfig (\r
2074 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2075 IN CONST EFI_STRING Configuration,\r
2076 OUT EFI_STRING *Progress\r
2077 )\r
2078{\r
2079 if (This == NULL || Configuration == NULL || Progress == NULL) {\r
2080 return EFI_INVALID_PARAMETER;\r
2081 }\r
2082\r
2083 //\r
2084 // Check routing data in <ConfigHdr>.\r
2085 // Note: if only one Storage is used, then this checking could be skipped.\r
2086 //\r
9bdc6592 2087 if (!HiiIsConfigHdrMatch (Configuration, &gIScsiConfigGuid, mVendorStorageName)) {\r
4c5a5e0c 2088 *Progress = Configuration;\r
2089 return EFI_NOT_FOUND;\r
2090 }\r
2091\r
2092 *Progress = Configuration + StrLen (Configuration);\r
2093 return EFI_SUCCESS;\r
2094}\r
2095\r
2096\r
2097/**\r
2098 \r
2099 This function is called to provide results data to the driver.\r
2100 This data consists of a unique key that is used to identify\r
2101 which data is either being passed back or being asked for.\r
2102\r
2103 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2104 @param[in] Action Specifies the type of action taken by the browser.\r
2105 @param[in] QuestionId A unique value which is sent to the original\r
2106 exporting driver so that it can identify the type\r
2107 of data to expect. The format of the data tends to \r
2108 vary based on the opcode that generated the callback.\r
2109 @param[in] Type The type of value for the question.\r
2110 @param[in, out] Value A pointer to the data being sent to the original\r
2111 exporting driver.\r
2112 @param[out] ActionRequest On return, points to the action requested by the\r
2113 callback function.\r
2114\r
2115 @retval EFI_SUCCESS The callback successfully handled the action.\r
2116 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
2117 variable and its data.\r
2118 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
2119 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
2120 callback.\r
2121**/\r
2122EFI_STATUS\r
2123EFIAPI\r
2124IScsiFormCallback (\r
2125 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2126 IN EFI_BROWSER_ACTION Action,\r
2127 IN EFI_QUESTION_ID QuestionId,\r
2128 IN UINT8 Type,\r
2129 IN OUT EFI_IFR_TYPE_VALUE *Value,\r
2130 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
2131 )\r
2132{\r
2133 ISCSI_FORM_CALLBACK_INFO *Private;\r
2134 UINTN BufferSize;\r
2135 CHAR8 *IScsiName;\r
2136 CHAR8 IpString[IP_STR_MAX_SIZE];\r
2137 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];\r
2138 UINT64 Lun;\r
2139 EFI_IP_ADDRESS HostIp;\r
2140 EFI_IP_ADDRESS SubnetMask;\r
2141 EFI_IP_ADDRESS Gateway;\r
2142 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
2143 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData;\r
2144 EFI_STATUS Status;\r
2145 CHAR16 AttemptName[ATTEMPT_NAME_SIZE + 4];\r
2146 EFI_INPUT_KEY Key;\r
2147\r
2148 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {\r
2149 //\r
2150 // Do nothing for UEFI OPEN/CLOSE Action\r
2151 //\r
2152 return EFI_SUCCESS;\r
2153 }\r
2154\r
639a76d1 2155 if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {\r
4c5a5e0c 2156 //\r
639a76d1 2157 // All other type return unsupported.\r
4c5a5e0c 2158 //\r
639a76d1
ED
2159 return EFI_UNSUPPORTED;\r
2160 }\r
4c5a5e0c 2161\r
639a76d1
ED
2162 if ((Value == NULL) || (ActionRequest == NULL)) {\r
2163 return EFI_INVALID_PARAMETER;\r
2164 }\r
4c5a5e0c 2165\r
639a76d1
ED
2166 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
2167 \r
2168 //\r
2169 // Retrieve uncommitted data from Browser\r
2170 //\r
2171 \r
2172 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
2173 IfrNvData = AllocateZeroPool (BufferSize);\r
2174 if (IfrNvData == NULL) {\r
2175 return EFI_OUT_OF_RESOURCES;\r
2176 }\r
2177 \r
2178 IScsiName = (CHAR8 *) AllocateZeroPool (ISCSI_NAME_MAX_SIZE);\r
2179 if (IScsiName == NULL) {\r
2180 FreePool (IfrNvData);\r
2181 return EFI_OUT_OF_RESOURCES;\r
2182 }\r
2183 \r
2184 Status = EFI_SUCCESS;\r
2185 \r
2186 ZeroMem (&OldIfrNvData, BufferSize);\r
2187 \r
2188 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);\r
2189 \r
2190 CopyMem (&OldIfrNvData, IfrNvData, BufferSize);\r
4c5a5e0c 2191\r
639a76d1
ED
2192 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
2193 switch (QuestionId) {\r
2194 case KEY_ADD_ATTEMPT:\r
e9da7dea
ZL
2195 //\r
2196 // Check whether iSCSI initiator name is configured already.\r
2197 //\r
2198 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;\r
2199 Status = gIScsiInitiatorName.Get (\r
2200 &gIScsiInitiatorName,\r
2201 &mPrivate->InitiatorNameLength,\r
2202 mPrivate->InitiatorName\r
2203 );\r
2204 if (EFI_ERROR (Status)) {\r
2205 CreatePopUp (\r
2206 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2207 &Key,\r
2208 L"Error: please configure iSCSI initiator name first!",\r
2209 NULL\r
2210 ); \r
2211 break;\r
2212 }\r
2213 \r
639a76d1
ED
2214 Status = IScsiConfigAddAttempt ();\r
2215 break;\r
4c5a5e0c 2216\r
639a76d1
ED
2217 case KEY_DELETE_ATTEMPT:\r
2218 CopyMem (\r
2219 OldIfrNvData.DeleteAttemptList,\r
2220 IfrNvData->DeleteAttemptList,\r
2221 sizeof (IfrNvData->DeleteAttemptList)\r
2222 );\r
2223 Status = IScsiConfigDisplayDeleteAttempts (IfrNvData);\r
2224 break;\r
4c5a5e0c 2225\r
639a76d1
ED
2226 case KEY_ORDER_ATTEMPT_CONFIG:\r
2227 //\r
2228 // Order the attempt according to user input.\r
2229 //\r
2230 CopyMem (\r
2231 OldIfrNvData.DynamicOrderedList,\r
2232 IfrNvData->DynamicOrderedList,\r
2233 sizeof (IfrNvData->DynamicOrderedList)\r
2234 );\r
2235 IScsiConfigDisplayOrderAttempts ();\r
2236 break;\r
2237 \r
2238 default:\r
2239 Status = IScsiConfigProcessDefault (QuestionId, IfrNvData);\r
2240 break;\r
2241 }\r
2242 } else if (Action == EFI_BROWSER_ACTION_CHANGED) { \r
4c5a5e0c 2243 switch (QuestionId) {\r
2244 case KEY_INITIATOR_NAME:\r
b9679cd7 2245 UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, IScsiName, ISCSI_NAME_MAX_SIZE);\r
4c5a5e0c 2246 BufferSize = AsciiStrSize (IScsiName);\r
2247\r
2248 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);\r
2249 if (EFI_ERROR (Status)) {\r
2250 CreatePopUp (\r
2251 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2252 &Key,\r
2253 L"Invalid iSCSI Name!",\r
2254 NULL\r
2255 ); \r
2256 }\r
2257\r
f10810ca 2258 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
4c5a5e0c 2259 break;\r
639a76d1
ED
2260 case KEY_ATTEMPT_NAME:\r
2261 if (StrLen (IfrNvData->AttemptName) > ATTEMPT_NAME_SIZE) {\r
2262 CopyMem (AttemptName, IfrNvData->AttemptName, ATTEMPT_NAME_SIZE * sizeof (CHAR16));\r
2263 CopyMem (&AttemptName[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16));\r
2264 } else {\r
2265 CopyMem (\r
2266 AttemptName,\r
2267 IfrNvData->AttemptName,\r
2268 (StrLen (IfrNvData->AttemptName) + 1) * sizeof (CHAR16)\r
2269 );\r
2270 }\r
4c5a5e0c 2271\r
b9679cd7 2272 UnicodeStrToAsciiStrS (IfrNvData->AttemptName, Private->Current->AttemptName, sizeof (Private->Current->AttemptName));\r
4c5a5e0c 2273\r
639a76d1 2274 IScsiConfigUpdateAttempt ();\r
4c5a5e0c 2275\r
639a76d1
ED
2276 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
2277 break;\r
2278 \r
2279 case KEY_SAVE_ATTEMPT_CONFIG:\r
2280 Status = IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData, Private->Current);\r
4c5a5e0c 2281 if (EFI_ERROR (Status)) {\r
2282 break;\r
2283 }\r
2284\r
f10810ca 2285 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
4c5a5e0c 2286 break;\r
2287\r
4c5a5e0c 2288 case KEY_SAVE_ORDER_CHANGES:\r
2289 //\r
2290 // Sync the Attempt Order to NVR.\r
2291 //\r
2292 Status = IScsiConfigOrderAttempts (IfrNvData);\r
2293 if (EFI_ERROR (Status)) {\r
2294 break;\r
2295 }\r
2296\r
2297 IScsiConfigUpdateAttempt ();\r
639a76d1 2298 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
4c5a5e0c 2299 break;\r
2300\r
2301 case KEY_IGNORE_ORDER_CHANGES:\r
2302 CopyMem (\r
2303 IfrNvData->DynamicOrderedList,\r
2304 OldIfrNvData.DynamicOrderedList,\r
2305 sizeof (IfrNvData->DynamicOrderedList)\r
2306 );\r
639a76d1 2307 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
4c5a5e0c 2308 break;\r
2309\r
639a76d1
ED
2310 case KEY_SAVE_DELETE_ATTEMPT:\r
2311 //\r
2312 // Delete the Attempt Order from NVR\r
2313 //\r
2314 Status = IScsiConfigDeleteAttempts (IfrNvData);\r
2315 if (EFI_ERROR (Status)) {\r
2316 break;\r
4c5a5e0c 2317 }\r
2318\r
4c5a5e0c 2319 IScsiConfigUpdateAttempt ();\r
639a76d1
ED
2320 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
2321 break;\r
4c5a5e0c 2322\r
639a76d1
ED
2323 case KEY_IGNORE_DELETE_ATTEMPT:\r
2324 CopyMem (\r
2325 IfrNvData->DeleteAttemptList,\r
2326 OldIfrNvData.DeleteAttemptList,\r
2327 sizeof (IfrNvData->DeleteAttemptList)\r
2328 );\r
2329 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
4c5a5e0c 2330 break;\r
2331\r
2332 case KEY_IP_MODE:\r
2333 switch (Value->u8) {\r
2334 case IP_MODE_IP6:\r
2335 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));\r
2336 IScsiIpToStr (&Private->Current->SessionConfigData.TargetIp, TRUE, IfrNvData->TargetIp);\r
2337 Private->Current->AutoConfigureMode = 0;\r
2338 break;\r
2339\r
2340 case IP_MODE_IP4:\r
2341 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));\r
2342 IScsiIpToStr (&Private->Current->SessionConfigData.TargetIp, FALSE, IfrNvData->TargetIp);\r
2343 Private->Current->AutoConfigureMode = 0;\r
2344\r
2345 break;\r
2346 }\r
2347\r
2348 break;\r
2349\r
2350 case KEY_LOCAL_IP:\r
2351 Status = NetLibStrToIp4 (IfrNvData->LocalIp, &HostIp.v4);\r
2352 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
2353 CreatePopUp (\r
2354 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2355 &Key,\r
2356 L"Invalid IP address!",\r
2357 NULL\r
2358 ); \r
2359 \r
2360 Status = EFI_INVALID_PARAMETER;\r
2361 } else {\r
2362 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
2363 }\r
2364\r
2365 break;\r
2366\r
2367 case KEY_SUBNET_MASK:\r
2368 Status = NetLibStrToIp4 (IfrNvData->SubnetMask, &SubnetMask.v4);\r
2369 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
2370 CreatePopUp (\r
2371 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2372 &Key,\r
2373 L"Invalid Subnet Mask!",\r
2374 NULL\r
2375 ); \r
2376 \r
2377 Status = EFI_INVALID_PARAMETER;\r
2378 } else {\r
2379 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
2380 }\r
2381\r
2382 break;\r
2383\r
2384 case KEY_GATE_WAY:\r
2385 Status = NetLibStrToIp4 (IfrNvData->Gateway, &Gateway.v4);\r
2386 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {\r
2387 CreatePopUp (\r
2388 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2389 &Key,\r
2390 L"Invalid Gateway!",\r
2391 NULL\r
2392 ); \r
2393 Status = EFI_INVALID_PARAMETER;\r
2394 } else {\r
2395 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
2396 }\r
2397\r
2398 break;\r
2399\r
2400 case KEY_TARGET_IP:\r
b9679cd7 2401 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, IpString, sizeof (IpString));\r
4c5a5e0c 2402 Status = IScsiAsciiStrToIp (IpString, IfrNvData->IpMode, &HostIp);\r
2403 if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, IfrNvData->IpMode)) {\r
2404 CreatePopUp (\r
2405 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2406 &Key,\r
2407 L"Invalid IP address!",\r
2408 NULL\r
2409 ); \r
2410 Status = EFI_INVALID_PARAMETER;\r
2411 } else {\r
2412 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp));\r
2413 }\r
2414\r
2415 break;\r
2416\r
2417 case KEY_TARGET_NAME:\r
b9679cd7 2418 UnicodeStrToAsciiStrS (IfrNvData->TargetName, IScsiName, ISCSI_NAME_MAX_SIZE);\r
4c5a5e0c 2419 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));\r
2420 if (EFI_ERROR (Status)) {\r
2421 CreatePopUp (\r
2422 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2423 &Key,\r
2424 L"Invalid iSCSI Name!",\r
2425 NULL\r
b2220321 2426 );\r
4c5a5e0c 2427 } else {\r
c960bdc2 2428 AsciiStrCpyS (Private->Current->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName);\r
4c5a5e0c 2429 }\r
2430\r
2431 break;\r
2432\r
2433 case KEY_DHCP_ENABLE:\r
2434 if (IfrNvData->InitiatorInfoFromDhcp == 0) {\r
2435 IfrNvData->TargetInfoFromDhcp = 0;\r
2436 }\r
2437\r
2438 break;\r
2439\r
2440 case KEY_BOOT_LUN:\r
b9679cd7 2441 UnicodeStrToAsciiStrS (IfrNvData->BootLun, LunString, sizeof (LunString));\r
4c5a5e0c 2442 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);\r
2443 if (EFI_ERROR (Status)) {\r
2444 CreatePopUp (\r
2445 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2446 &Key,\r
2447 L"Invalid LUN string!",\r
2448 NULL\r
2449 ); \r
2450 } else {\r
2451 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
2452 }\r
2453\r
2454 break;\r
2455\r
2456 case KEY_AUTH_TYPE:\r
2457 switch (Value->u8) {\r
2458 case ISCSI_AUTH_TYPE_CHAP:\r
2459 IfrNvData->CHAPType = ISCSI_CHAP_UNI;\r
2460 break;\r
2461 default:\r
2462 break;\r
2463 }\r
2464\r
2465 break;\r
2466\r
2467 case KEY_CHAP_NAME:\r
b9679cd7 2468 UnicodeStrToAsciiStrS (\r
4c5a5e0c 2469 IfrNvData->CHAPName,\r
b9679cd7
SZ
2470 Private->Current->AuthConfigData.CHAP.CHAPName,\r
2471 sizeof (Private->Current->AuthConfigData.CHAP.CHAPName)\r
4c5a5e0c 2472 );\r
2473 break;\r
2474\r
2475 case KEY_CHAP_SECRET:\r
b9679cd7 2476 UnicodeStrToAsciiStrS (\r
4c5a5e0c 2477 IfrNvData->CHAPSecret,\r
b9679cd7
SZ
2478 Private->Current->AuthConfigData.CHAP.CHAPSecret,\r
2479 sizeof (Private->Current->AuthConfigData.CHAP.CHAPSecret)\r
4c5a5e0c 2480 );\r
2481 break;\r
2482\r
2483 case KEY_REVERSE_CHAP_NAME:\r
b9679cd7 2484 UnicodeStrToAsciiStrS (\r
4c5a5e0c 2485 IfrNvData->ReverseCHAPName,\r
b9679cd7
SZ
2486 Private->Current->AuthConfigData.CHAP.ReverseCHAPName,\r
2487 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPName)\r
4c5a5e0c 2488 );\r
2489 break;\r
2490\r
2491 case KEY_REVERSE_CHAP_SECRET:\r
b9679cd7 2492 UnicodeStrToAsciiStrS (\r
4c5a5e0c 2493 IfrNvData->ReverseCHAPSecret,\r
b9679cd7
SZ
2494 Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret,\r
2495 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret)\r
4c5a5e0c 2496 );\r
2497 break;\r
2498\r
2499 case KEY_CONFIG_ISID:\r
2500 IScsiParseIsIdFromString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);\r
2501 IScsiConvertIsIdToString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);\r
2502\r
2503 break;\r
2504\r
4c5a5e0c 2505 default:\r
4c5a5e0c 2506 break;\r
2507 }\r
639a76d1 2508 }\r
4c5a5e0c 2509\r
639a76d1
ED
2510 if (!EFI_ERROR (Status)) {\r
2511 //\r
2512 // Pass changed uncommitted data back to Form Browser.\r
2513 //\r
2514 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
2515 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);\r
4c5a5e0c 2516 }\r
2517\r
639a76d1
ED
2518 FreePool (IfrNvData);\r
2519 FreePool (IScsiName);\r
2520\r
2521 return Status;\r
4c5a5e0c 2522}\r
2523\r
2524\r
2525/**\r
2526 Initialize the iSCSI configuration form.\r
2527\r
2528 @param[in] DriverBindingHandle The iSCSI driverbinding handle.\r
2529\r
2530 @retval EFI_SUCCESS The iSCSI configuration form is initialized.\r
2531 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
2532\r
2533**/\r
2534EFI_STATUS\r
2535IScsiConfigFormInit (\r
2536 IN EFI_HANDLE DriverBindingHandle\r
2537 )\r
2538{\r
2539 EFI_STATUS Status;\r
2540 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;\r
2541\r
2542 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO));\r
2543 if (CallbackInfo == NULL) {\r
2544 return EFI_OUT_OF_RESOURCES;\r
2545 }\r
2546\r
2547 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;\r
2548 CallbackInfo->Current = NULL;\r
2549\r
2550 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;\r
2551 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;\r
2552 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;\r
2553\r
2554 //\r
2555 // Install Device Path Protocol and Config Access protocol to driver handle.\r
2556 //\r
2557 Status = gBS->InstallMultipleProtocolInterfaces (\r
2558 &CallbackInfo->DriverHandle,\r
2559 &gEfiDevicePathProtocolGuid,\r
2560 &mIScsiHiiVendorDevicePath,\r
2561 &gEfiHiiConfigAccessProtocolGuid,\r
2562 &CallbackInfo->ConfigAccess,\r
2563 NULL\r
2564 );\r
2565 ASSERT_EFI_ERROR (Status);\r
2566 \r
2567 //\r
2568 // Publish our HII data.\r
2569 //\r
2570 CallbackInfo->RegisteredHandle = HiiAddPackages (\r
9bdc6592 2571 &gIScsiConfigGuid,\r
4c5a5e0c 2572 CallbackInfo->DriverHandle,\r
2573 IScsiDxeStrings,\r
2574 IScsiConfigVfrBin,\r
2575 NULL\r
2576 );\r
2577 if (CallbackInfo->RegisteredHandle == NULL) {\r
2578 gBS->UninstallMultipleProtocolInterfaces (\r
2579 &CallbackInfo->DriverHandle,\r
2580 &gEfiDevicePathProtocolGuid,\r
2581 &mIScsiHiiVendorDevicePath,\r
2582 &gEfiHiiConfigAccessProtocolGuid,\r
2583 &CallbackInfo->ConfigAccess,\r
2584 NULL\r
2585 );\r
2586 FreePool(CallbackInfo);\r
2587 return EFI_OUT_OF_RESOURCES;\r
2588 }\r
2589\r
2590 mCallbackInfo = CallbackInfo;\r
2591\r
2592 return EFI_SUCCESS;\r
2593}\r
2594\r
2595\r
2596/**\r
2597 Unload the iSCSI configuration form, this includes: delete all the iSCSI\r
2598 configuration entries, uninstall the form callback protocol, and\r
2599 free the resources used.\r
2600\r
2601 @param[in] DriverBindingHandle The iSCSI driverbinding handle.\r
2602\r
2603 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.\r
2604 @retval Others Failed to unload the form.\r
2605\r
2606**/\r
2607EFI_STATUS\r
2608IScsiConfigFormUnload (\r
2609 IN EFI_HANDLE DriverBindingHandle\r
2610 )\r
2611{\r
2612 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
2613 ISCSI_NIC_INFO *NicInfo;\r
2614 LIST_ENTRY *Entry;\r
2615 EFI_STATUS Status;\r
2616\r
2617 while (!IsListEmpty (&mPrivate->AttemptConfigs)) {\r
2618 Entry = NetListRemoveHead (&mPrivate->AttemptConfigs);\r
2619 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
2620 FreePool (AttemptConfigData);\r
2621 mPrivate->AttemptCount--;\r
2622 }\r
2623\r
2624 ASSERT (mPrivate->AttemptCount == 0);\r
2625\r
2626 while (!IsListEmpty (&mPrivate->NicInfoList)) {\r
2627 Entry = NetListRemoveHead (&mPrivate->NicInfoList);\r
2628 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
2629 FreePool (NicInfo);\r
2630 mPrivate->NicCount--;\r
2631 }\r
2632\r
2633 ASSERT (mPrivate->NicCount == 0);\r
2634\r
c0d494b5 2635 //\r
2636 // Free attempt is created but not saved to system.\r
2637 //\r
2638 if (mPrivate->NewAttempt != NULL) {\r
2639 FreePool (mPrivate->NewAttempt);\r
2640 }\r
2641\r
4c5a5e0c 2642 FreePool (mPrivate);\r
2643 mPrivate = NULL;\r
2644\r
2645 //\r
2646 // Remove HII package list.\r
2647 //\r
2648 HiiRemovePackages (mCallbackInfo->RegisteredHandle);\r
2649\r
2650 //\r
2651 // Uninstall Device Path Protocol and Config Access protocol.\r
2652 //\r
2653 Status = gBS->UninstallMultipleProtocolInterfaces (\r
2654 mCallbackInfo->DriverHandle,\r
2655 &gEfiDevicePathProtocolGuid,\r
2656 &mIScsiHiiVendorDevicePath,\r
2657 &gEfiHiiConfigAccessProtocolGuid,\r
2658 &mCallbackInfo->ConfigAccess,\r
2659 NULL\r
2660 );\r
2661\r
2662 FreePool (mCallbackInfo);\r
2663\r
2664 return Status;\r
2665}\r