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