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