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