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