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