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