]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IScsiDxe/IScsiMisc.c
NetworkPkg/IScsiDxe: Add IPv6 support condition check.
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiMisc.c
1 /** @file
2 Miscellaneous routines for iSCSI driver.
3
4 Copyright (c) 2004 - 2017, 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 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 IScsiHexString[] = "0123456789ABCDEFabcdef";
18
19 /**
20 Removes (trims) specified leading and trailing characters from a string.
21
22 @param[in, out] Str Pointer to the null-terminated string to be trimmed.
23 On return, Str will hold the trimmed string.
24
25 @param[in] CharC Character will be trimmed from str.
26
27 **/
28 VOID
29 IScsiStrTrim (
30 IN OUT CHAR16 *Str,
31 IN CHAR16 CharC
32 )
33 {
34 CHAR16 *Pointer1;
35 CHAR16 *Pointer2;
36
37 if (*Str == 0) {
38 return ;
39 }
40
41 //
42 // Trim off the leading and trailing characters c
43 //
44 for (Pointer1 = Str; (*Pointer1 != 0) && (*Pointer1 == CharC); Pointer1++) {
45 ;
46 }
47
48 Pointer2 = Str;
49 if (Pointer2 == Pointer1) {
50 while (*Pointer1 != 0) {
51 Pointer2++;
52 Pointer1++;
53 }
54 } else {
55 while (*Pointer1 != 0) {
56 *Pointer2 = *Pointer1;
57 Pointer1++;
58 Pointer2++;
59 }
60 *Pointer2 = 0;
61 }
62
63
64 for (Pointer1 = Str + StrLen(Str) - 1; Pointer1 >= Str && *Pointer1 == CharC; Pointer1--) {
65 ;
66 }
67 if (Pointer1 != Str + StrLen(Str) - 1) {
68 *(Pointer1 + 1) = 0;
69 }
70 }
71
72 /**
73 Calculate the prefix length of the IPv4 subnet mask.
74
75 @param[in] SubnetMask The IPv4 subnet mask.
76
77 @return The prefix length of the subnet mask.
78 @retval 0 Other errors as indicated.
79
80 **/
81 UINT8
82 IScsiGetSubnetMaskPrefixLength (
83 IN EFI_IPv4_ADDRESS *SubnetMask
84 )
85 {
86 UINT8 Len;
87 UINT32 ReverseMask;
88
89 //
90 // The SubnetMask is in network byte order.
91 //
92 ReverseMask = (SubnetMask->Addr[0] << 24) | (SubnetMask->Addr[1] << 16) | (SubnetMask->Addr[2] << 8) | (SubnetMask->Addr[3]);
93
94 //
95 // Reverse it.
96 //
97 ReverseMask = ~ReverseMask;
98
99 if ((ReverseMask & (ReverseMask + 1)) != 0) {
100 return 0;
101 }
102
103 Len = 0;
104
105 while (ReverseMask != 0) {
106 ReverseMask = ReverseMask >> 1;
107 Len++;
108 }
109
110 return (UINT8) (32 - Len);
111 }
112
113
114 /**
115 Convert the hexadecimal encoded LUN string into the 64-bit LUN.
116
117 @param[in] Str The hexadecimal encoded LUN string.
118 @param[out] Lun Storage to return the 64-bit LUN.
119
120 @retval EFI_SUCCESS The 64-bit LUN is stored in Lun.
121 @retval EFI_INVALID_PARAMETER The string is malformatted.
122
123 **/
124 EFI_STATUS
125 IScsiAsciiStrToLun (
126 IN CHAR8 *Str,
127 OUT UINT8 *Lun
128 )
129 {
130 UINTN Index, IndexValue, IndexNum, SizeStr;
131 CHAR8 TemStr[2];
132 UINT8 TemValue;
133 UINT16 Value[4];
134
135 ZeroMem (Lun, 8);
136 ZeroMem (TemStr, 2);
137 ZeroMem ((UINT8 *) Value, sizeof (Value));
138 SizeStr = AsciiStrLen (Str);
139 IndexValue = 0;
140 IndexNum = 0;
141
142 for (Index = 0; Index < SizeStr; Index ++) {
143 TemStr[0] = Str[Index];
144 TemValue = (UINT8) AsciiStrHexToUint64 (TemStr);
145 if (TemValue == 0 && TemStr[0] != '0') {
146 if ((TemStr[0] != '-') || (IndexNum == 0)) {
147 //
148 // Invalid Lun Char.
149 //
150 return EFI_INVALID_PARAMETER;
151 }
152 }
153
154 if ((TemValue == 0) && (TemStr[0] == '-')) {
155 //
156 // Next Lun value.
157 //
158 if (++IndexValue >= 4) {
159 //
160 // Max 4 Lun value.
161 //
162 return EFI_INVALID_PARAMETER;
163 }
164 //
165 // Restart str index for the next lun value.
166 //
167 IndexNum = 0;
168 continue;
169 }
170
171 if (++IndexNum > 4) {
172 //
173 // Each Lun Str can't exceed size 4, because it will be as UINT16 value.
174 //
175 return EFI_INVALID_PARAMETER;
176 }
177
178 //
179 // Combine UINT16 value.
180 //
181 Value[IndexValue] = (UINT16) ((Value[IndexValue] << 4) + TemValue);
182 }
183
184 for (Index = 0; Index <= IndexValue; Index ++) {
185 *((UINT16 *) &Lun[Index * 2]) = HTONS (Value[Index]);
186 }
187
188 return EFI_SUCCESS;
189 }
190
191 /**
192 Convert the 64-bit LUN into the hexadecimal encoded LUN string.
193
194 @param[in] Lun The 64-bit LUN.
195 @param[out] Str The storage to return the hexadecimal encoded LUN string.
196
197 **/
198 VOID
199 IScsiLunToUnicodeStr (
200 IN UINT8 *Lun,
201 OUT CHAR16 *Str
202 )
203 {
204 UINTN Index;
205 CHAR16 *TempStr;
206
207 TempStr = Str;
208
209 for (Index = 0; Index < 4; Index++) {
210
211 if ((Lun[2 * Index] | Lun[2 * Index + 1]) == 0) {
212 CopyMem (TempStr, L"0-", sizeof (L"0-"));
213 } else {
214 TempStr[0] = (CHAR16) IScsiHexString[Lun[2 * Index] >> 4];
215 TempStr[1] = (CHAR16) IScsiHexString[Lun[2 * Index] & 0x0F];
216 TempStr[2] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] >> 4];
217 TempStr[3] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] & 0x0F];
218 TempStr[4] = L'-';
219 TempStr[5] = 0;
220
221 IScsiStrTrim (TempStr, L'0');
222 }
223
224 TempStr += StrLen (TempStr);
225 }
226 //
227 // Remove the last '-'
228 //
229 ASSERT (StrLen(Str) >= 1);
230 Str[StrLen (Str) - 1] = 0;
231
232 for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) {
233 if ((Str[Index] == L'0') && (Str[Index - 1] == L'-')) {
234 Str[Index - 1] = 0;
235 } else {
236 break;
237 }
238 }
239 }
240
241 /**
242 Convert the formatted IP address into the binary IP address.
243
244 @param[in] Str The UNICODE string.
245 @param[in] IpMode Indicates whether the IP address is v4 or v6.
246 @param[out] Ip The storage to return the ASCII string.
247
248 @retval EFI_SUCCESS The binary IP address is returned in Ip.
249 @retval EFI_INVALID_PARAMETER The IP string is malformatted or IpMode is
250 invalid.
251
252 **/
253 EFI_STATUS
254 IScsiAsciiStrToIp (
255 IN CHAR8 *Str,
256 IN UINT8 IpMode,
257 OUT EFI_IP_ADDRESS *Ip
258 )
259 {
260 EFI_STATUS Status;
261
262 if (IpMode == IP_MODE_IP4 || IpMode == IP_MODE_AUTOCONFIG_IP4) {
263 return NetLibAsciiStrToIp4 (Str, &Ip->v4);
264
265 } else if (IpMode == IP_MODE_IP6 || IpMode == IP_MODE_AUTOCONFIG_IP6) {
266 return NetLibAsciiStrToIp6 (Str, &Ip->v6);
267
268 } else if (IpMode == IP_MODE_AUTOCONFIG) {
269 Status = NetLibAsciiStrToIp4 (Str, &Ip->v4);
270 if (!EFI_ERROR (Status)) {
271 return Status;
272 }
273 return NetLibAsciiStrToIp6 (Str, &Ip->v6);
274
275 }
276
277 return EFI_INVALID_PARAMETER;
278 }
279
280 /**
281 Convert the mac address into a hexadecimal encoded "-" seperated string.
282
283 @param[in] Mac The mac address.
284 @param[in] Len Length in bytes of the mac address.
285 @param[in] VlanId VLAN ID of the network device.
286 @param[out] Str The storage to return the mac string.
287
288 **/
289 VOID
290 IScsiMacAddrToStr (
291 IN EFI_MAC_ADDRESS *Mac,
292 IN UINT32 Len,
293 IN UINT16 VlanId,
294 OUT CHAR16 *Str
295 )
296 {
297 UINT32 Index;
298 CHAR16 *String;
299
300 for (Index = 0; Index < Len; Index++) {
301 Str[3 * Index] = (CHAR16) IScsiHexString[(Mac->Addr[Index] >> 4) & 0x0F];
302 Str[3 * Index + 1] = (CHAR16) IScsiHexString[Mac->Addr[Index] & 0x0F];
303 Str[3 * Index + 2] = L':';
304 }
305
306 String = &Str[3 * Index - 1] ;
307 if (VlanId != 0) {
308 String += UnicodeSPrint (String, 6 * sizeof (CHAR16), L"\\%04x", (UINTN) VlanId);
309 }
310
311 *String = L'\0';
312 }
313
314 /**
315 Convert the binary encoded buffer into a hexadecimal encoded string.
316
317 @param[in] BinBuffer The buffer containing the binary data.
318 @param[in] BinLength Length of the binary buffer.
319 @param[in, out] HexStr Pointer to the string.
320 @param[in, out] HexLength The length of the string.
321
322 @retval EFI_SUCCESS The binary data is converted to the hexadecimal string
323 and the length of the string is updated.
324 @retval EFI_BUFFER_TOO_SMALL The string is too small.
325 @retval EFI_INVALID_PARAMETER The IP string is malformatted.
326
327 **/
328 EFI_STATUS
329 IScsiBinToHex (
330 IN UINT8 *BinBuffer,
331 IN UINT32 BinLength,
332 IN OUT CHAR8 *HexStr,
333 IN OUT UINT32 *HexLength
334 )
335 {
336 UINTN Index;
337
338 if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {
339 return EFI_INVALID_PARAMETER;
340 }
341
342 if (((*HexLength) - 3) < BinLength * 2) {
343 *HexLength = BinLength * 2 + 3;
344 return EFI_BUFFER_TOO_SMALL;
345 }
346
347 *HexLength = BinLength * 2 + 3;
348 //
349 // Prefix for Hex String.
350 //
351 HexStr[0] = '0';
352 HexStr[1] = 'x';
353
354 for (Index = 0; Index < BinLength; Index++) {
355 HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4];
356 HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0xf];
357 }
358
359 HexStr[Index * 2 + 2] = '\0';
360
361 return EFI_SUCCESS;
362 }
363
364
365 /**
366 Convert the hexadecimal string into a binary encoded buffer.
367
368 @param[in, out] BinBuffer The binary buffer.
369 @param[in, out] BinLength Length of the binary buffer.
370 @param[in] HexStr The hexadecimal string.
371
372 @retval EFI_SUCCESS The hexadecimal string is converted into a binary
373 encoded buffer.
374 @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.
375
376 **/
377 EFI_STATUS
378 IScsiHexToBin (
379 IN OUT UINT8 *BinBuffer,
380 IN OUT UINT32 *BinLength,
381 IN CHAR8 *HexStr
382 )
383 {
384 UINTN Index;
385 UINTN Length;
386 UINT8 Digit;
387 CHAR8 TemStr[2];
388
389 ZeroMem (TemStr, sizeof (TemStr));
390
391 //
392 // Find out how many hex characters the string has.
393 //
394 if ((HexStr[0] == '0') && ((HexStr[1] == 'x') || (HexStr[1] == 'X'))) {
395 HexStr += 2;
396 }
397
398 Length = AsciiStrLen (HexStr);
399
400 for (Index = 0; Index < Length; Index ++) {
401 TemStr[0] = HexStr[Index];
402 Digit = (UINT8) AsciiStrHexToUint64 (TemStr);
403 if (Digit == 0 && TemStr[0] != '0') {
404 //
405 // Invalid Lun Char.
406 //
407 break;
408 }
409 if ((Index & 1) == 0) {
410 BinBuffer [Index/2] = Digit;
411 } else {
412 BinBuffer [Index/2] = (UINT8) ((BinBuffer [Index/2] << 4) + Digit);
413 }
414 }
415
416 *BinLength = (UINT32) ((Index + 1)/2);
417
418 return EFI_SUCCESS;
419 }
420
421
422 /**
423 Convert the decimal-constant string or hex-constant string into a numerical value.
424
425 @param[in] Str String in decimal or hex.
426
427 @return The numerical value.
428
429 **/
430 UINTN
431 IScsiNetNtoi (
432 IN CHAR8 *Str
433 )
434 {
435 if ((Str[0] == '0') && ((Str[1] == 'x') || (Str[1] == 'X'))) {
436 Str += 2;
437
438 return AsciiStrHexToUintn (Str);
439 }
440
441 return AsciiStrDecimalToUintn (Str);
442 }
443
444
445 /**
446 Generate random numbers.
447
448 @param[in, out] Rand The buffer to contain random numbers.
449 @param[in] RandLength The length of the Rand buffer.
450
451 **/
452 VOID
453 IScsiGenRandom (
454 IN OUT UINT8 *Rand,
455 IN UINTN RandLength
456 )
457 {
458 UINT32 Random;
459
460 while (RandLength > 0) {
461 Random = NET_RANDOM (NetRandomInitSeed ());
462 *Rand++ = (UINT8) (Random);
463 RandLength--;
464 }
465 }
466
467
468 /**
469 Check whether UNDI protocol supports IPv6.
470
471 @param[in] ControllerHandle Controller handle.
472 @param[in] Image Handle of the image.
473 @param[out] Ipv6Support TRUE if UNDI supports IPv6.
474
475 @retval EFI_SUCCESS Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully.
476 @retval EFI_NOT_FOUND Don't know whether UNDI supports IPv6 since NII or AIP is not available.
477
478 **/
479 EFI_STATUS
480 IScsiCheckIpv6Support (
481 IN EFI_HANDLE ControllerHandle,
482 IN EFI_HANDLE Image,
483 OUT BOOLEAN *Ipv6Support
484 )
485 {
486 EFI_HANDLE Handle;
487 EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
488 EFI_STATUS Status;
489 EFI_GUID *InfoTypesBuffer;
490 UINTN InfoTypeBufferCount;
491 UINTN TypeIndex;
492 BOOLEAN Supported;
493 VOID *InfoBlock;
494 UINTN InfoBlockSize;
495
496 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;
497
498 ASSERT (Ipv6Support != NULL);
499
500 //
501 // Check whether the UNDI supports IPv6 by NII protocol.
502 //
503 Status = gBS->OpenProtocol (
504 ControllerHandle,
505 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
506 (VOID **) &Nii,
507 Image,
508 ControllerHandle,
509 EFI_OPEN_PROTOCOL_GET_PROTOCOL
510 );
511 if (Status == EFI_SUCCESS) {
512 *Ipv6Support = Nii->Ipv6Supported;
513 return EFI_SUCCESS;
514 }
515
516 //
517 // Get the NIC handle by SNP protocol.
518 //
519 Handle = NetLibGetSnpHandle (ControllerHandle, NULL);
520 if (Handle == NULL) {
521 return EFI_NOT_FOUND;
522 }
523
524 Aip = NULL;
525 Status = gBS->HandleProtocol (
526 Handle,
527 &gEfiAdapterInformationProtocolGuid,
528 (VOID *) &Aip
529 );
530 if (EFI_ERROR (Status) || Aip == NULL) {
531 return EFI_NOT_FOUND;
532 }
533
534 InfoTypesBuffer = NULL;
535 InfoTypeBufferCount = 0;
536 Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);
537 if (EFI_ERROR (Status) || InfoTypesBuffer == NULL) {
538 FreePool (InfoTypesBuffer);
539 return EFI_NOT_FOUND;
540 }
541
542 Supported = FALSE;
543 for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {
544 if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) {
545 Supported = TRUE;
546 break;
547 }
548 }
549
550 FreePool (InfoTypesBuffer);
551 if (!Supported) {
552 return EFI_NOT_FOUND;
553 }
554
555 //
556 // We now have adapter information block.
557 //
558 InfoBlock = NULL;
559 InfoBlockSize = 0;
560 Status = Aip->GetInformation (Aip, &gEfiAdapterInfoUndiIpv6SupportGuid, &InfoBlock, &InfoBlockSize);
561 if (EFI_ERROR (Status) || InfoBlock == NULL) {
562 FreePool (InfoBlock);
563 return EFI_NOT_FOUND;
564 }
565
566 *Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *) InfoBlock)->Ipv6Support;
567 FreePool (InfoBlock);
568
569 return EFI_SUCCESS;
570 }
571
572 /**
573 Record the NIC info in global structure.
574
575 @param[in] Controller The handle of the controller.
576 @param[in] Image Handle of the image.
577
578 @retval EFI_SUCCESS The operation is completed.
579 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resources to finish this
580 operation.
581
582 **/
583 EFI_STATUS
584 IScsiAddNic (
585 IN EFI_HANDLE Controller,
586 IN EFI_HANDLE Image
587 )
588 {
589 EFI_STATUS Status;
590 ISCSI_NIC_INFO *NicInfo;
591 LIST_ENTRY *Entry;
592 EFI_MAC_ADDRESS MacAddr;
593 UINTN HwAddressSize;
594 UINT16 VlanId;
595
596 //
597 // Get MAC address of this network device.
598 //
599 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
600 if (EFI_ERROR (Status)) {
601 return Status;
602 }
603
604 //
605 // Get VLAN ID of this network device.
606 //
607 VlanId = NetLibGetVlanId (Controller);
608
609 //
610 // Check whether the NIC info already exists. Return directly if so.
611 //
612 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
613 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
614 if (NicInfo->HwAddressSize == HwAddressSize &&
615 CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&
616 NicInfo->VlanId == VlanId) {
617 mPrivate->CurrentNic = NicInfo->NicIndex;
618
619 //
620 // Set IPv6 available flag.
621 //
622 Status = IScsiCheckIpv6Support (Controller, Image, &NicInfo->Ipv6Available);
623 if (EFI_ERROR (Status)) {
624 //
625 // Fail to get the data whether UNDI supports IPv6.
626 // Set default value to TRUE.
627 //
628 NicInfo->Ipv6Available = TRUE;
629 }
630
631 return EFI_SUCCESS;
632 }
633
634 if (mPrivate->MaxNic < NicInfo->NicIndex) {
635 mPrivate->MaxNic = NicInfo->NicIndex;
636 }
637 }
638
639 //
640 // Record the NIC info in private structure.
641 //
642 NicInfo = AllocateZeroPool (sizeof (ISCSI_NIC_INFO));
643 if (NicInfo == NULL) {
644 return EFI_OUT_OF_RESOURCES;
645 }
646
647 CopyMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize);
648 NicInfo->HwAddressSize = (UINT32) HwAddressSize;
649 NicInfo->VlanId = VlanId;
650 NicInfo->NicIndex = (UINT8) (mPrivate->MaxNic + 1);
651 mPrivate->MaxNic = NicInfo->NicIndex;
652
653 //
654 // Set IPv6 available flag.
655 //
656 Status = IScsiCheckIpv6Support (Controller, Image, &NicInfo->Ipv6Available);
657 if (EFI_ERROR (Status)) {
658 //
659 // Fail to get the data whether UNDI supports IPv6.
660 // Set default value to TRUE.
661 //
662 NicInfo->Ipv6Available = TRUE;
663 }
664
665 //
666 // Get the PCI location.
667 //
668 IScsiGetNICPciLocation (
669 Controller,
670 &NicInfo->BusNumber,
671 &NicInfo->DeviceNumber,
672 &NicInfo->FunctionNumber
673 );
674
675 InsertTailList (&mPrivate->NicInfoList, &NicInfo->Link);
676 mPrivate->NicCount++;
677
678 mPrivate->CurrentNic = NicInfo->NicIndex;
679 return EFI_SUCCESS;
680 }
681
682
683 /**
684 Delete the recorded NIC info from global structure. Also delete corresponding
685 attempts.
686
687 @param[in] Controller The handle of the controller.
688
689 @retval EFI_SUCCESS The operation is completed.
690 @retval EFI_NOT_FOUND The NIC info to be deleted is not recorded.
691
692 **/
693 EFI_STATUS
694 IScsiRemoveNic (
695 IN EFI_HANDLE Controller
696 )
697 {
698 EFI_STATUS Status;
699 ISCSI_NIC_INFO *NicInfo;
700 LIST_ENTRY *Entry;
701 LIST_ENTRY *NextEntry;
702 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
703 ISCSI_NIC_INFO *ThisNic;
704 EFI_MAC_ADDRESS MacAddr;
705 UINTN HwAddressSize;
706 UINT16 VlanId;
707
708 //
709 // Get MAC address of this network device.
710 //
711 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
712 if (EFI_ERROR (Status)) {
713 return Status;
714 }
715
716 //
717 // Get VLAN ID of this network device.
718 //
719 VlanId = NetLibGetVlanId (Controller);
720
721 //
722 // Check whether the NIC information exists.
723 //
724 ThisNic = NULL;
725
726 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
727 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
728 if (NicInfo->HwAddressSize == HwAddressSize &&
729 CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&
730 NicInfo->VlanId == VlanId) {
731
732 ThisNic = NicInfo;
733 break;
734 }
735 }
736
737 if (ThisNic == NULL) {
738 return EFI_NOT_FOUND;
739 }
740
741 mPrivate->CurrentNic = ThisNic->NicIndex;
742
743 RemoveEntryList (&ThisNic->Link);
744 FreePool (ThisNic);
745 mPrivate->NicCount--;
746
747 //
748 // Remove all attempts related to this NIC.
749 //
750 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
751 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
752 if (AttemptConfigData->NicIndex == mPrivate->CurrentNic) {
753 RemoveEntryList (&AttemptConfigData->Link);
754 mPrivate->AttemptCount--;
755
756 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO && mPrivate->MpioCount > 0) {
757 if (--mPrivate->MpioCount == 0) {
758 mPrivate->EnableMpio = FALSE;
759 }
760
761 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB && mPrivate->Krb5MpioCount > 0) {
762 mPrivate->Krb5MpioCount--;
763 }
764
765 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED && mPrivate->SinglePathCount > 0) {
766 mPrivate->SinglePathCount--;
767
768 if (mPrivate->ValidSinglePathCount > 0) {
769 mPrivate->ValidSinglePathCount--;
770 }
771 }
772
773 FreePool (AttemptConfigData);
774 }
775 }
776
777 return EFI_SUCCESS;
778 }
779
780 /**
781 Create and initialize the Attempts.
782
783 @param[in] AttemptNum The number of Attempts will be created.
784
785 @retval EFI_SUCCESS The Attempts have been created successfully.
786 @retval Others Failed to create the Attempt.
787
788 **/
789 EFI_STATUS
790 IScsiCreateAttempts (
791 IN UINTN AttemptNum
792 )
793 {
794 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
795 ISCSI_SESSION_CONFIG_NVDATA *ConfigData;
796 UINT8 *AttemptConfigOrder;
797 UINTN AttemptConfigOrderSize;
798 UINT8 *AttemptOrderTmp;
799 UINTN TotalNumber;
800 UINT8 Index;
801 EFI_STATUS Status;
802
803 for (Index = 1; Index <= AttemptNum; Index ++) {
804 //
805 // Get the initialized attempt order. This is used to essure creating attempts by order.
806 //
807 AttemptConfigOrder = IScsiGetVariableAndSize (
808 L"InitialAttemptOrder",
809 &gIScsiConfigGuid,
810 &AttemptConfigOrderSize
811 );
812 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);
813 if (TotalNumber == AttemptNum) {
814 Status = EFI_SUCCESS;
815 break;
816 }
817 TotalNumber++;
818
819 //
820 // Append the new created attempt to the end.
821 //
822 AttemptOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));
823 if (AttemptOrderTmp == NULL) {
824 if (AttemptConfigOrder != NULL) {
825 FreePool (AttemptConfigOrder);
826 }
827 return EFI_OUT_OF_RESOURCES;
828 }
829
830 if (AttemptConfigOrder != NULL) {
831 CopyMem (AttemptOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);
832 FreePool (AttemptConfigOrder);
833 }
834
835 AttemptOrderTmp[TotalNumber - 1] = Index;
836 AttemptConfigOrder = AttemptOrderTmp;
837 AttemptConfigOrderSize = TotalNumber * sizeof (UINT8);
838
839 Status = gRT->SetVariable (
840 L"InitialAttemptOrder",
841 &gIScsiConfigGuid,
842 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
843 AttemptConfigOrderSize,
844 AttemptConfigOrder
845 );
846 FreePool (AttemptConfigOrder);
847 if (EFI_ERROR (Status)) {
848 return Status;
849 }
850
851 //
852 // Create new Attempt
853 //
854 AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA));
855 if (AttemptConfigData == NULL) {
856 return EFI_OUT_OF_RESOURCES;
857 }
858 ConfigData = &AttemptConfigData->SessionConfigData;
859 ConfigData->TargetPort = ISCSI_WELL_KNOWN_PORT;
860 ConfigData->ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;
861 ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY;
862
863 AttemptConfigData->AuthenticationType = ISCSI_AUTH_TYPE_CHAP;
864 AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI;
865 //
866 // Configure the Attempt index and set variable.
867 //
868 AttemptConfigData->AttemptConfigIndex = Index;
869
870 //
871 // Set the attempt name according to the order.
872 //
873 UnicodeSPrint (
874 mPrivate->PortString,
875 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
876 L"Attempt %d",
877 (UINTN) AttemptConfigData->AttemptConfigIndex
878 );
879 UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, ATTEMPT_NAME_SIZE);
880
881 Status = gRT->SetVariable (
882 mPrivate->PortString,
883 &gEfiIScsiInitiatorNameProtocolGuid,
884 ISCSI_CONFIG_VAR_ATTR,
885 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
886 AttemptConfigData
887 );
888 FreePool (AttemptConfigData);
889 if (EFI_ERROR (Status)) {
890 return Status;
891 }
892 }
893
894 return EFI_SUCCESS;
895 }
896
897 /**
898 Create the iSCSI configuration Keywords for each attempt. You can find the keywords
899 defined in the "x-UEFI-ns" namespace (http://www.uefi.org/confignamespace).
900
901 @param[in] KeywordNum The number Sets of Keywords will be created.
902
903 @retval EFI_SUCCESS The operation is completed.
904 @retval Others Failed to create the Keywords.
905
906 **/
907 EFI_STATUS
908 IScsiCreateKeywords (
909 IN UINTN KeywordNum
910 )
911 {
912 VOID *StartOpCodeHandle;
913 EFI_IFR_GUID_LABEL *StartLabel;
914 VOID *EndOpCodeHandle;
915 EFI_IFR_GUID_LABEL *EndLabel;
916 UINTN Index;
917 EFI_STRING_ID StringToken;
918 CHAR16 StringId[64];
919 CHAR16 KeywordId[32];
920 EFI_STATUS Status;
921
922 Status = IScsiCreateOpCode (
923 KEYWORD_ENTRY_LABEL,
924 &StartOpCodeHandle,
925 &StartLabel,
926 &EndOpCodeHandle,
927 &EndLabel
928 );
929 if (EFI_ERROR (Status)) {
930 return EFI_OUT_OF_RESOURCES;
931 }
932
933 for (Index = 1; Index <= KeywordNum; Index ++) {
934 //
935 // Create iSCSIAttemptName Keyword.
936 //
937 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_ATTEMPTT_NAME_PROMPT%d", Index);
938 StringToken = HiiSetString (
939 mCallbackInfo->RegisteredHandle,
940 0,
941 StringId,
942 NULL
943 );
944 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIAttemptName:%d", Index);
945 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
946 HiiCreateStringOpCode (
947 StartOpCodeHandle,
948 (EFI_QUESTION_ID) (ATTEMPT_ATTEMPT_NAME_QUESTION_ID + (Index - 1)),
949 CONFIGURATION_VARSTORE_ID,
950 (UINT16) (ATTEMPT_ATTEMPT_NAME_VAR_OFFSET + ATTEMPT_NAME_SIZE * (Index - 1) * sizeof (CHAR16)),
951 StringToken,
952 StringToken,
953 EFI_IFR_FLAG_READ_ONLY,
954 0,
955 0,
956 ATTEMPT_NAME_SIZE,
957 NULL
958 );
959
960 //
961 // Create iSCSIBootEnable Keyword.
962 //
963 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_MODE_PROMPT%d", Index);
964 StringToken = HiiSetString (
965 mCallbackInfo->RegisteredHandle,
966 0,
967 StringId,
968 NULL
969 );
970 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIBootEnable:%d", Index);
971 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
972 HiiCreateNumericOpCode (
973 StartOpCodeHandle,
974 (EFI_QUESTION_ID) (ATTEMPT_BOOTENABLE_QUESTION_ID + (Index - 1)),
975 CONFIGURATION_VARSTORE_ID,
976 (UINT16) (ATTEMPT_BOOTENABLE_VAR_OFFSET + (Index - 1)),
977 StringToken,
978 StringToken,
979 0,
980 EFI_IFR_NUMERIC_SIZE_1,
981 0,
982 2,
983 0,
984 NULL
985 );
986
987 //
988 // Create iSCSIIpAddressType Keyword.
989 //
990 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_IP_MODE_PROMPT%d", Index);
991 StringToken = HiiSetString (
992 mCallbackInfo->RegisteredHandle,
993 0,
994 StringId,
995 NULL
996 );
997 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIIpAddressType:%d", Index);
998 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
999 HiiCreateNumericOpCode (
1000 StartOpCodeHandle,
1001 (EFI_QUESTION_ID) (ATTEMPT_ADDRESS_TYPE_QUESTION_ID + (Index - 1)),
1002 CONFIGURATION_VARSTORE_ID,
1003 (UINT16) (ATTEMPT_ADDRESS_TYPE_VAR_OFFSET + (Index - 1)),
1004 StringToken,
1005 StringToken,
1006 0,
1007 EFI_IFR_NUMERIC_SIZE_1,
1008 0,
1009 2,
1010 0,
1011 NULL
1012 );
1013
1014 //
1015 // Create iSCSIConnectRetry Keyword.
1016 //
1017 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CONNECT_RETRY_PROMPT%d", Index);
1018 StringToken = HiiSetString (
1019 mCallbackInfo->RegisteredHandle,
1020 0,
1021 StringId,
1022 NULL
1023 );
1024 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIConnectRetry:%d", Index);
1025 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1026 HiiCreateNumericOpCode (
1027 StartOpCodeHandle,
1028 (EFI_QUESTION_ID) (ATTEMPT_CONNECT_RETRY_QUESTION_ID + (Index - 1)),
1029 CONFIGURATION_VARSTORE_ID,
1030 (UINT16) (ATTEMPT_CONNECT_RETRY_VAR_OFFSET + (Index - 1)),
1031 StringToken,
1032 StringToken,
1033 0,
1034 EFI_IFR_NUMERIC_SIZE_1,
1035 0,
1036 16,
1037 0,
1038 NULL
1039 );
1040
1041 //
1042 // Create iSCSIConnectTimeout Keyword.
1043 //
1044 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CONNECT_TIMEOUT_PROMPT%d", Index);
1045 StringToken = HiiSetString (
1046 mCallbackInfo->RegisteredHandle,
1047 0,
1048 StringId,
1049 NULL
1050 );
1051 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIConnectTimeout:%d", Index);
1052 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1053 HiiCreateNumericOpCode (
1054 StartOpCodeHandle,
1055 (EFI_QUESTION_ID) (ATTEMPT_CONNECT_TIMEOUT_QUESTION_ID + (Index - 1)),
1056 CONFIGURATION_VARSTORE_ID,
1057 (UINT16) (ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET + 2 * (Index - 1)),
1058 StringToken,
1059 StringToken,
1060 0,
1061 EFI_IFR_NUMERIC_SIZE_2,
1062 CONNECT_MIN_TIMEOUT,
1063 CONNECT_MAX_TIMEOUT,
1064 0,
1065 NULL
1066 );
1067
1068 //
1069 // Create ISID Keyword.
1070 //
1071 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_ISID_PROMPT%d", Index);
1072 StringToken = HiiSetString (
1073 mCallbackInfo->RegisteredHandle,
1074 0,
1075 StringId,
1076 NULL
1077 );
1078 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIISID:%d", Index);
1079 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1080 HiiCreateStringOpCode (
1081 StartOpCodeHandle,
1082 (EFI_QUESTION_ID) (ATTEMPT_ISID_QUESTION_ID + (Index - 1)),
1083 CONFIGURATION_VARSTORE_ID,
1084 (UINT16) (ATTEMPT_ISID_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1085 StringToken,
1086 STRING_TOKEN (STR_ISCSI_ISID_HELP),
1087 0,
1088 0,
1089 ISID_CONFIGURABLE_MIN_LEN,
1090 ISID_CONFIGURABLE_STORAGE,
1091 NULL
1092 );
1093
1094 //
1095 // Create iSCSIInitiatorInfoViaDHCP Keyword.
1096 //
1097 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_VIA_DHCP_PROMPT%d", Index);
1098 StringToken = HiiSetString (
1099 mCallbackInfo->RegisteredHandle,
1100 0,
1101 StringId,
1102 NULL
1103 );
1104 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorInfoViaDHCP:%d", Index);
1105 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1106 HiiCreateNumericOpCode (
1107 StartOpCodeHandle,
1108 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_VIA_DHCP_QUESTION_ID + (Index - 1)),
1109 CONFIGURATION_VARSTORE_ID,
1110 (UINT16) (ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET + (Index - 1)),
1111 StringToken,
1112 StringToken,
1113 0,
1114 0,
1115 0,
1116 1,
1117 0,
1118 NULL
1119 );
1120
1121 //
1122 // Create iSCSIInitiatorIpAddress Keyword.
1123 //
1124 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_IP_ADDRESS_PROMPT%d", Index);
1125 StringToken = HiiSetString (
1126 mCallbackInfo->RegisteredHandle,
1127 0,
1128 StringId,
1129 NULL
1130 );
1131 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorIpAddress:%d", Index);
1132 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1133 HiiCreateStringOpCode (
1134 StartOpCodeHandle,
1135 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_IP_ADDRESS_QUESTION_ID + (Index - 1)),
1136 CONFIGURATION_VARSTORE_ID,
1137 (UINT16) (ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1138 StringToken,
1139 StringToken,
1140 0,
1141 0,
1142 IP4_MIN_SIZE,
1143 IP4_STR_MAX_SIZE,
1144 NULL
1145 );
1146
1147 //
1148 // Create iSCSIInitiatorNetmask Keyword.
1149 //
1150 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_NET_MASK_PROMPT%d", Index);
1151 StringToken = HiiSetString (
1152 mCallbackInfo->RegisteredHandle,
1153 0,
1154 StringId,
1155 NULL
1156 );
1157 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorNetmask:%d", Index);
1158 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1159 HiiCreateStringOpCode (
1160 StartOpCodeHandle,
1161 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_NET_MASK_QUESTION_ID + (Index - 1)),
1162 CONFIGURATION_VARSTORE_ID,
1163 (UINT16) (ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1164 StringToken,
1165 StringToken,
1166 0,
1167 0,
1168 IP4_MIN_SIZE,
1169 IP4_STR_MAX_SIZE,
1170 NULL
1171 );
1172
1173 //
1174 // Create iSCSIInitiatorGateway Keyword.
1175 //
1176 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_GATE_PROMPT%d", Index);
1177 StringToken = HiiSetString (
1178 mCallbackInfo->RegisteredHandle,
1179 0,
1180 StringId,
1181 NULL
1182 );
1183 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorGateway:%d", Index);
1184 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1185 HiiCreateStringOpCode (
1186 StartOpCodeHandle,
1187 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_GATE_WAY_QUESTION_ID + (Index - 1)),
1188 CONFIGURATION_VARSTORE_ID,
1189 (UINT16) (ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1190 StringToken,
1191 StringToken,
1192 0,
1193 0,
1194 IP4_MIN_SIZE,
1195 IP4_STR_MAX_SIZE,
1196 NULL
1197 );
1198
1199 //
1200 // Create iSCSITargetInfoViaDHCP Keyword.
1201 //
1202 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_VIA_DHCP_PROMPT%d", Index);
1203 StringToken = HiiSetString (
1204 mCallbackInfo->RegisteredHandle,
1205 0,
1206 StringId,
1207 NULL
1208 );
1209 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetInfoViaDHCP:%d", Index);
1210 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1211 HiiCreateNumericOpCode (
1212 StartOpCodeHandle,
1213 (EFI_QUESTION_ID) (ATTEMPT_TARGET_VIA_DHCP_QUESTION_ID + (Index - 1)),
1214 CONFIGURATION_VARSTORE_ID,
1215 (UINT16) (ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET + (Index - 1)),
1216 StringToken,
1217 StringToken,
1218 0,
1219 0,
1220 0,
1221 1,
1222 0,
1223 NULL
1224 );
1225
1226 //
1227 // Create iSCSITargetTcpPort Keyword.
1228 //
1229 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_TCP_PORT_PROMPT%d", Index);
1230 StringToken = HiiSetString (
1231 mCallbackInfo->RegisteredHandle,
1232 0,
1233 StringId,
1234 NULL
1235 );
1236 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetTcpPort:%d", Index);
1237 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1238 HiiCreateNumericOpCode (
1239 StartOpCodeHandle,
1240 (EFI_QUESTION_ID) (ATTEMPT_TARGET_TCP_PORT_QUESTION_ID + (Index - 1)),
1241 CONFIGURATION_VARSTORE_ID,
1242 (UINT16) (ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET + 2 * (Index - 1)),
1243 StringToken,
1244 StringToken,
1245 0,
1246 EFI_IFR_NUMERIC_SIZE_2,
1247 TARGET_PORT_MIN_NUM,
1248 TARGET_PORT_MAX_NUM,
1249 0,
1250 NULL
1251 );
1252
1253 //
1254 // Create iSCSITargetName Keyword.
1255 //
1256 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_NAME_PROMPT%d", Index);
1257 StringToken = HiiSetString (
1258 mCallbackInfo->RegisteredHandle,
1259 0,
1260 StringId,
1261 NULL
1262 );
1263 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetName:%d", Index);
1264 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1265 HiiCreateStringOpCode (
1266 StartOpCodeHandle,
1267 (EFI_QUESTION_ID) (ATTEMPT_TARGET_NAME_QUESTION_ID + (Index - 1)),
1268 CONFIGURATION_VARSTORE_ID,
1269 (UINT16) (ATTEMPT_TARGET_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1270 StringToken,
1271 StringToken,
1272 0,
1273 0,
1274 ISCSI_NAME_IFR_MIN_SIZE,
1275 ISCSI_NAME_IFR_MAX_SIZE,
1276 NULL
1277 );
1278
1279 //
1280 // Create iSCSITargetIpAddress Keyword.
1281 //
1282 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_IP_ADDRESS_PROMPT%d", Index);
1283 StringToken = HiiSetString (
1284 mCallbackInfo->RegisteredHandle,
1285 0,
1286 StringId,
1287 NULL
1288 );
1289 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetIpAddress:%d", Index);
1290 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1291 HiiCreateStringOpCode (
1292 StartOpCodeHandle,
1293 (EFI_QUESTION_ID) (ATTEMPT_TARGET_IP_ADDRESS_QUESTION_ID + (Index - 1)),
1294 CONFIGURATION_VARSTORE_ID,
1295 (UINT16) (ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1296 StringToken,
1297 StringToken,
1298 0,
1299 0,
1300 IP_MIN_SIZE,
1301 IP_STR_MAX_SIZE,
1302 NULL
1303 );
1304
1305 //
1306 // Create iSCSILUN Keyword.
1307 //
1308 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_LUN_PROMPT%d", Index);
1309 StringToken = HiiSetString (
1310 mCallbackInfo->RegisteredHandle,
1311 0,
1312 StringId,
1313 NULL
1314 );
1315 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSILUN:%d", Index);
1316 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1317 HiiCreateStringOpCode (
1318 StartOpCodeHandle,
1319 (EFI_QUESTION_ID) (ATTEMPT_LUN_QUESTION_ID + (Index - 1)),
1320 CONFIGURATION_VARSTORE_ID,
1321 (UINT16) (ATTEMPT_LUN_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1322 StringToken,
1323 StringToken,
1324 0,
1325 0,
1326 LUN_MIN_SIZE,
1327 LUN_MAX_SIZE,
1328 NULL
1329 );
1330
1331 //
1332 // Create iSCSIAuthenticationMethod Keyword.
1333 //
1334 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_AUTHENTICATION_METHOD_PROMPT%d", Index);
1335 StringToken = HiiSetString (
1336 mCallbackInfo->RegisteredHandle,
1337 0,
1338 StringId,
1339 NULL
1340 );
1341 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIAuthenticationMethod:%d", Index);
1342 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1343 HiiCreateNumericOpCode (
1344 StartOpCodeHandle,
1345 (EFI_QUESTION_ID) (ATTEMPT_AUTHENTICATION_METHOD_QUESTION_ID + (Index - 1)),
1346 CONFIGURATION_VARSTORE_ID,
1347 (UINT16) (ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET + (Index - 1)),
1348 StringToken,
1349 StringToken,
1350 0,
1351 0,
1352 0,
1353 1,
1354 0,
1355 NULL
1356 );
1357
1358 //
1359 // Create iSCSIChapType Keyword.
1360 //
1361 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHARTYPE_PROMPT%d", Index);
1362 StringToken = HiiSetString (
1363 mCallbackInfo->RegisteredHandle,
1364 0,
1365 StringId,
1366 NULL
1367 );
1368 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapType:%d", Index);
1369 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1370 HiiCreateNumericOpCode (
1371 StartOpCodeHandle,
1372 (EFI_QUESTION_ID) (ATTEMPT_CHARTYPE_QUESTION_ID + (Index - 1)),
1373 CONFIGURATION_VARSTORE_ID,
1374 (UINT16) (ATTEMPT_CHARTYPE_VAR_OFFSET + (Index - 1)),
1375 StringToken,
1376 StringToken,
1377 0,
1378 0,
1379 0,
1380 1,
1381 0,
1382 NULL
1383 );
1384
1385 //
1386 // Create iSCSIChapUsername Keyword.
1387 //
1388 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_USER_NAME_PROMPT%d", Index);
1389 StringToken = HiiSetString (
1390 mCallbackInfo->RegisteredHandle,
1391 0,
1392 StringId,
1393 NULL
1394 );
1395 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapUsername:%d", Index);
1396 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1397 HiiCreateStringOpCode (
1398 StartOpCodeHandle,
1399 (EFI_QUESTION_ID) (ATTEMPT_CHAR_USER_NAME_QUESTION_ID + (Index - 1)),
1400 CONFIGURATION_VARSTORE_ID,
1401 (UINT16) (ATTEMPT_CHAR_USER_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1402 StringToken,
1403 StringToken,
1404 0,
1405 0,
1406 0,
1407 ISCSI_CHAP_NAME_MAX_LEN,
1408 NULL
1409 );
1410
1411 //
1412 // Create iSCSIChapSecret Keyword.
1413 //
1414 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_SECRET_PROMPT%d", Index);
1415 StringToken = HiiSetString (
1416 mCallbackInfo->RegisteredHandle,
1417 0,
1418 StringId,
1419 NULL
1420 );
1421 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapSecret:%d", Index);
1422 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1423 HiiCreateStringOpCode (
1424 StartOpCodeHandle,
1425 (EFI_QUESTION_ID) (ATTEMPT_CHAR_SECRET_QUESTION_ID + (Index - 1)),
1426 CONFIGURATION_VARSTORE_ID,
1427 (UINT16) (ATTEMPT_CHAR_SECRET_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1428 StringToken,
1429 StringToken,
1430 0,
1431 0,
1432 ISCSI_CHAP_SECRET_MIN_LEN,
1433 ISCSI_CHAP_SECRET_MAX_LEN,
1434 NULL
1435 );
1436
1437 //
1438 // Create iSCSIReverseChapUsername Keyword.
1439 //
1440 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_REVERSE_USER_NAME_PROMPT%d", Index);
1441 StringToken = HiiSetString (
1442 mCallbackInfo->RegisteredHandle,
1443 0,
1444 StringId,
1445 NULL
1446 );
1447 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIReverseChapUsername:%d", Index);
1448 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1449 HiiCreateStringOpCode (
1450 StartOpCodeHandle,
1451 (EFI_QUESTION_ID) (ATTEMPT_CHAR_REVERSE_USER_NAME_QUESTION_ID + (Index - 1)),
1452 CONFIGURATION_VARSTORE_ID,
1453 (UINT16) (ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1454 StringToken,
1455 StringToken,
1456 0,
1457 0,
1458 0,
1459 ISCSI_CHAP_NAME_MAX_LEN,
1460 NULL
1461 );
1462
1463 //
1464 // Create iSCSIReverseChapSecret Keyword.
1465 //
1466 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_REVERSE_SECRET_PROMPT%d", Index);
1467 StringToken = HiiSetString (
1468 mCallbackInfo->RegisteredHandle,
1469 0,
1470 StringId,
1471 NULL
1472 );
1473 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIReverseChapSecret:%d", Index);
1474 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1475 HiiCreateStringOpCode (
1476 StartOpCodeHandle,
1477 (EFI_QUESTION_ID) (ATTEMPT_CHAR_REVERSE_SECRET_QUESTION_ID + (Index - 1)),
1478 CONFIGURATION_VARSTORE_ID,
1479 (UINT16) (ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1480 StringToken,
1481 StringToken,
1482 0,
1483 0,
1484 ISCSI_CHAP_SECRET_MIN_LEN,
1485 ISCSI_CHAP_SECRET_MAX_LEN,
1486 NULL
1487 );
1488 }
1489
1490 Status = HiiUpdateForm (
1491 mCallbackInfo->RegisteredHandle, // HII handle
1492 &gIScsiConfigGuid, // Formset GUID
1493 FORMID_ATTEMPT_FORM, // Form ID
1494 StartOpCodeHandle, // Label for where to insert opcodes
1495 EndOpCodeHandle // Replace data
1496 );
1497
1498 HiiFreeOpCodeHandle (StartOpCodeHandle);
1499 HiiFreeOpCodeHandle (EndOpCodeHandle);
1500
1501 return Status;
1502 }
1503
1504 /**
1505
1506 Free the attempt configure data variable.
1507
1508 **/
1509 VOID
1510 IScsiCleanAttemptVariable (
1511 IN VOID
1512 )
1513 {
1514 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
1515 UINT8 *AttemptConfigOrder;
1516 UINTN AttemptConfigOrderSize;
1517 UINTN Index;
1518
1519 //
1520 // Get the initialized attempt order.
1521 //
1522 AttemptConfigOrder = IScsiGetVariableAndSize (
1523 L"InitialAttemptOrder",
1524 &gIScsiConfigGuid,
1525 &AttemptConfigOrderSize
1526 );
1527 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
1528 return;
1529 }
1530
1531 for (Index = 1; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1532 UnicodeSPrint (
1533 mPrivate->PortString,
1534 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
1535 L"Attempt %d",
1536 Index
1537 );
1538
1539 GetVariable2 (
1540 mPrivate->PortString,
1541 &gEfiIScsiInitiatorNameProtocolGuid,
1542 (VOID**)&AttemptConfigData,
1543 NULL
1544 );
1545
1546 if (AttemptConfigData != NULL) {
1547 gRT->SetVariable (
1548 mPrivate->PortString,
1549 &gEfiIScsiInitiatorNameProtocolGuid,
1550 0,
1551 0,
1552 NULL
1553 );
1554 }
1555 }
1556 return;
1557 }
1558
1559 /**
1560 Get the recorded NIC info from global structure by the Index.
1561
1562 @param[in] NicIndex The index indicates the position of NIC info.
1563
1564 @return Pointer to the NIC info, or NULL if not found.
1565
1566 **/
1567 ISCSI_NIC_INFO *
1568 IScsiGetNicInfoByIndex (
1569 IN UINT8 NicIndex
1570 )
1571 {
1572 LIST_ENTRY *Entry;
1573 ISCSI_NIC_INFO *NicInfo;
1574
1575 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
1576 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
1577 if (NicInfo->NicIndex == NicIndex) {
1578 return NicInfo;
1579 }
1580 }
1581
1582 return NULL;
1583 }
1584
1585
1586 /**
1587 Get the NIC's PCI location and return it according to the composited
1588 format defined in iSCSI Boot Firmware Table.
1589
1590 @param[in] Controller The handle of the controller.
1591 @param[out] Bus The bus number.
1592 @param[out] Device The device number.
1593 @param[out] Function The function number.
1594
1595 @return The composited representation of the NIC PCI location.
1596
1597 **/
1598 UINT16
1599 IScsiGetNICPciLocation (
1600 IN EFI_HANDLE Controller,
1601 OUT UINTN *Bus,
1602 OUT UINTN *Device,
1603 OUT UINTN *Function
1604 )
1605 {
1606 EFI_STATUS Status;
1607 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1608 EFI_HANDLE PciIoHandle;
1609 EFI_PCI_IO_PROTOCOL *PciIo;
1610 UINTN Segment;
1611
1612 Status = gBS->HandleProtocol (
1613 Controller,
1614 &gEfiDevicePathProtocolGuid,
1615 (VOID **) &DevicePath
1616 );
1617 if (EFI_ERROR (Status)) {
1618 return 0;
1619 }
1620
1621 Status = gBS->LocateDevicePath (
1622 &gEfiPciIoProtocolGuid,
1623 &DevicePath,
1624 &PciIoHandle
1625 );
1626 if (EFI_ERROR (Status)) {
1627 return 0;
1628 }
1629
1630 Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
1631 if (EFI_ERROR (Status)) {
1632 return 0;
1633 }
1634
1635 Status = PciIo->GetLocation (PciIo, &Segment, Bus, Device, Function);
1636 if (EFI_ERROR (Status)) {
1637 return 0;
1638 }
1639
1640 return (UINT16) ((*Bus << 8) | (*Device << 3) | *Function);
1641 }
1642
1643
1644 /**
1645 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1646 buffer, and the size of the buffer. If failure, return NULL.
1647
1648 @param[in] Name String part of EFI variable name.
1649 @param[in] VendorGuid GUID part of EFI variable name.
1650 @param[out] VariableSize Returns the size of the EFI variable that was read.
1651
1652 @return Dynamically allocated memory that contains a copy of the EFI variable.
1653 @return Caller is responsible freeing the buffer.
1654 @retval NULL Variable was not read.
1655
1656 **/
1657 VOID *
1658 IScsiGetVariableAndSize (
1659 IN CHAR16 *Name,
1660 IN EFI_GUID *VendorGuid,
1661 OUT UINTN *VariableSize
1662 )
1663 {
1664 EFI_STATUS Status;
1665 UINTN BufferSize;
1666 VOID *Buffer;
1667
1668 Buffer = NULL;
1669
1670 //
1671 // Pass in a zero size buffer to find the required buffer size.
1672 //
1673 BufferSize = 0;
1674 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
1675 if (Status == EFI_BUFFER_TOO_SMALL) {
1676 //
1677 // Allocate the buffer to return
1678 //
1679 Buffer = AllocateZeroPool (BufferSize);
1680 if (Buffer == NULL) {
1681 return NULL;
1682 }
1683 //
1684 // Read variable into the allocated buffer.
1685 //
1686 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
1687 if (EFI_ERROR (Status)) {
1688 BufferSize = 0;
1689 }
1690 }
1691
1692 *VariableSize = BufferSize;
1693 return Buffer;
1694 }
1695
1696
1697 /**
1698 Create the iSCSI driver data.
1699
1700 @param[in] Image The handle of the driver image.
1701 @param[in] Controller The handle of the controller.
1702
1703 @return The iSCSI driver data created.
1704 @retval NULL Other errors as indicated.
1705
1706 **/
1707 ISCSI_DRIVER_DATA *
1708 IScsiCreateDriverData (
1709 IN EFI_HANDLE Image,
1710 IN EFI_HANDLE Controller
1711 )
1712 {
1713 ISCSI_DRIVER_DATA *Private;
1714 EFI_STATUS Status;
1715
1716 Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));
1717 if (Private == NULL) {
1718 return NULL;
1719 }
1720
1721 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;
1722 Private->Image = Image;
1723 Private->Controller = Controller;
1724 Private->Session = NULL;
1725
1726 //
1727 // Create an event to be signaled when the BS to RT transition is triggerd so
1728 // as to abort the iSCSI session.
1729 //
1730 Status = gBS->CreateEventEx (
1731 EVT_NOTIFY_SIGNAL,
1732 TPL_CALLBACK,
1733 IScsiOnExitBootService,
1734 Private,
1735 &gEfiEventExitBootServicesGuid,
1736 &Private->ExitBootServiceEvent
1737 );
1738 if (EFI_ERROR (Status)) {
1739 FreePool (Private);
1740 return NULL;
1741 }
1742
1743 Private->ExtScsiPassThruHandle = NULL;
1744 CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));
1745
1746 //
1747 // 0 is designated to the TargetId, so use another value for the AdapterId.
1748 //
1749 Private->ExtScsiPassThruMode.AdapterId = 2;
1750 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
1751 Private->ExtScsiPassThruMode.IoAlign = 4;
1752 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
1753
1754 return Private;
1755 }
1756
1757
1758 /**
1759 Clean the iSCSI driver data.
1760
1761 @param[in] Private The iSCSI driver data.
1762
1763 @retval EFI_SUCCESS The clean operation is successful.
1764 @retval Others Other errors as indicated.
1765
1766 **/
1767 EFI_STATUS
1768 IScsiCleanDriverData (
1769 IN ISCSI_DRIVER_DATA *Private
1770 )
1771 {
1772 EFI_STATUS Status;
1773
1774 Status = EFI_SUCCESS;
1775
1776 if (Private->DevicePath != NULL) {
1777 Status = gBS->UninstallProtocolInterface (
1778 Private->ExtScsiPassThruHandle,
1779 &gEfiDevicePathProtocolGuid,
1780 Private->DevicePath
1781 );
1782 if (EFI_ERROR (Status)) {
1783 goto EXIT;
1784 }
1785
1786 FreePool (Private->DevicePath);
1787 }
1788
1789 if (Private->ExtScsiPassThruHandle != NULL) {
1790 Status = gBS->UninstallProtocolInterface (
1791 Private->ExtScsiPassThruHandle,
1792 &gEfiExtScsiPassThruProtocolGuid,
1793 &Private->IScsiExtScsiPassThru
1794 );
1795 if (!EFI_ERROR (Status)) {
1796 mPrivate->OneSessionEstablished = FALSE;
1797 }
1798 }
1799
1800 EXIT:
1801
1802 gBS->CloseEvent (Private->ExitBootServiceEvent);
1803
1804 mCallbackInfo->Current = NULL;
1805
1806 FreePool (Private);
1807 return Status;
1808 }
1809
1810 /**
1811 Check wheather the Controller handle is configured to use DHCP protocol.
1812
1813 @param[in] Controller The handle of the controller.
1814 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
1815
1816 @retval TRUE The handle of the controller need the Dhcp protocol.
1817 @retval FALSE The handle of the controller does not need the Dhcp protocol.
1818
1819 **/
1820 BOOLEAN
1821 IScsiDhcpIsConfigured (
1822 IN EFI_HANDLE Controller,
1823 IN UINT8 IpVersion
1824 )
1825 {
1826 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
1827 UINT8 *AttemptConfigOrder;
1828 UINTN AttemptConfigOrderSize;
1829 UINTN Index;
1830 EFI_STATUS Status;
1831 EFI_MAC_ADDRESS MacAddr;
1832 UINTN HwAddressSize;
1833 UINT16 VlanId;
1834 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
1835 CHAR16 AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];
1836 CHAR16 AttemptName[ISCSI_NAME_IFR_MAX_SIZE];
1837
1838 AttemptConfigOrder = IScsiGetVariableAndSize (
1839 L"AttemptOrder",
1840 &gIScsiConfigGuid,
1841 &AttemptConfigOrderSize
1842 );
1843 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
1844 return FALSE;
1845 }
1846
1847 //
1848 // Get MAC address of this network device.
1849 //
1850 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
1851 if(EFI_ERROR (Status)) {
1852 return FALSE;
1853 }
1854 //
1855 // Get VLAN ID of this network device.
1856 //
1857 VlanId = NetLibGetVlanId (Controller);
1858 IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);
1859
1860 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1861 UnicodeSPrint (
1862 AttemptName,
1863 (UINTN) 128,
1864 L"Attempt %d",
1865 (UINTN) AttemptConfigOrder[Index]
1866 );
1867 Status = GetVariable2 (
1868 AttemptName,
1869 &gEfiIScsiInitiatorNameProtocolGuid,
1870 (VOID**)&AttemptTmp,
1871 NULL
1872 );
1873 if(AttemptTmp == NULL || EFI_ERROR (Status)) {
1874 continue;
1875 }
1876
1877 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);
1878
1879 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {
1880 FreePool (AttemptTmp);
1881 continue;
1882 }
1883
1884 if (AttemptTmp->SessionConfigData.IpMode != IP_MODE_AUTOCONFIG &&
1885 AttemptTmp->SessionConfigData.IpMode != ((IpVersion == IP_VERSION_4) ? IP_MODE_IP4 : IP_MODE_IP6)) {
1886 FreePool (AttemptTmp);
1887 continue;
1888 }
1889
1890 AsciiStrToUnicodeStrS (AttemptTmp->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));
1891
1892 if (AttemptTmp->Actived == ISCSI_ACTIVE_DISABLED || StrCmp (MacString, AttemptMacString)) {
1893 continue;
1894 }
1895
1896 if(AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG ||
1897 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp == TRUE ||
1898 AttemptTmp->SessionConfigData.TargetInfoFromDhcp == TRUE) {
1899 FreePool (AttemptTmp);
1900 FreePool (AttemptConfigOrder);
1901 return TRUE;
1902 }
1903
1904 FreePool (AttemptTmp);
1905 }
1906
1907 FreePool (AttemptConfigOrder);
1908 return FALSE;
1909 }
1910
1911 /**
1912 Check whether the Controller handle is configured to use DNS protocol.
1913
1914 @param[in] Controller The handle of the controller.
1915
1916 @retval TRUE The handle of the controller need the Dns protocol.
1917 @retval FALSE The handle of the controller does not need the Dns protocol.
1918
1919 **/
1920 BOOLEAN
1921 IScsiDnsIsConfigured (
1922 IN EFI_HANDLE Controller
1923 )
1924 {
1925 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
1926 UINT8 *AttemptConfigOrder;
1927 UINTN AttemptConfigOrderSize;
1928 UINTN Index;
1929 EFI_STATUS Status;
1930 EFI_MAC_ADDRESS MacAddr;
1931 UINTN HwAddressSize;
1932 UINT16 VlanId;
1933 CHAR16 AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];
1934 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
1935 CHAR16 AttemptName[ISCSI_NAME_IFR_MAX_SIZE];
1936
1937 AttemptConfigOrder = IScsiGetVariableAndSize (
1938 L"AttemptOrder",
1939 &gIScsiConfigGuid,
1940 &AttemptConfigOrderSize
1941 );
1942 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
1943 return FALSE;
1944 }
1945
1946 //
1947 // Get MAC address of this network device.
1948 //
1949 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
1950 if(EFI_ERROR (Status)) {
1951 return FALSE;
1952 }
1953 //
1954 // Get VLAN ID of this network device.
1955 //
1956 VlanId = NetLibGetVlanId (Controller);
1957 IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);
1958
1959 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1960 UnicodeSPrint (
1961 AttemptName,
1962 (UINTN) 128,
1963 L"Attempt %d",
1964 (UINTN) AttemptConfigOrder[Index]
1965 );
1966
1967 Status = GetVariable2 (
1968 AttemptName,
1969 &gEfiIScsiInitiatorNameProtocolGuid,
1970 (VOID**)&AttemptTmp,
1971 NULL
1972 );
1973 if(AttemptTmp == NULL || EFI_ERROR (Status)) {
1974 continue;
1975 }
1976
1977 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);
1978
1979 AsciiStrToUnicodeStrS (AttemptTmp->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));
1980
1981 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED || StrCmp (MacString, AttemptMacString)) {
1982 FreePool (AttemptTmp);
1983 continue;
1984 }
1985
1986 if (AttemptTmp->SessionConfigData.DnsMode) {
1987 FreePool (AttemptTmp);
1988 FreePool (AttemptConfigOrder);
1989 return TRUE;
1990 } else {
1991 FreePool (AttemptTmp);
1992 continue;
1993 }
1994
1995 }
1996
1997 FreePool (AttemptConfigOrder);
1998 return FALSE;
1999
2000 }
2001
2002 /**
2003 Get the various configuration data.
2004
2005 @param[in] Private The iSCSI driver data.
2006
2007 @retval EFI_SUCCESS The configuration data is retrieved.
2008 @retval EFI_NOT_FOUND This iSCSI driver is not configured yet.
2009 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2010
2011 **/
2012 EFI_STATUS
2013 IScsiGetConfigData (
2014 IN ISCSI_DRIVER_DATA *Private
2015 )
2016 {
2017 EFI_STATUS Status;
2018 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
2019 CHAR16 AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];
2020 UINTN Index;
2021 ISCSI_NIC_INFO *NicInfo;
2022 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2023 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
2024 UINT8 *AttemptConfigOrder;
2025 UINTN AttemptConfigOrderSize;
2026 CHAR16 IScsiMode[64];
2027 CHAR16 IpMode[64];
2028
2029 //
2030 // There should be at least one attempt configured.
2031 //
2032 AttemptConfigOrder = IScsiGetVariableAndSize (
2033 L"AttemptOrder",
2034 &gIScsiConfigGuid,
2035 &AttemptConfigOrderSize
2036 );
2037 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
2038 return EFI_NOT_FOUND;
2039 }
2040
2041 //
2042 // Get the iSCSI Initiator Name.
2043 //
2044 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
2045 Status = gIScsiInitiatorName.Get (
2046 &gIScsiInitiatorName,
2047 &mPrivate->InitiatorNameLength,
2048 mPrivate->InitiatorName
2049 );
2050 if (EFI_ERROR (Status)) {
2051 return Status;
2052 }
2053
2054 //
2055 // Get the normal configuration.
2056 //
2057 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
2058
2059 //
2060 // Check whether the attempt exists in AttemptConfig.
2061 //
2062 AttemptTmp = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);
2063 if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {
2064 continue;
2065 } else if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled != ISCSI_DISABLED) {
2066 //
2067 // Check the autoconfig path to see whether it should be retried.
2068 //
2069 if (AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&
2070 !AttemptTmp->AutoConfigureSuccess) {
2071 if (mPrivate->Ipv6Flag &&
2072 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6) {
2073 //
2074 // Autoconfigure for IP6 already attempted but failed. Do not try again.
2075 //
2076 continue;
2077 } else if (!mPrivate->Ipv6Flag &&
2078 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4) {
2079 //
2080 // Autoconfigure for IP4 already attempted but failed. Do not try again.
2081 //
2082 continue;
2083 } else {
2084 //
2085 // Try another approach for this autoconfigure path.
2086 //
2087 AttemptTmp->AutoConfigureMode =
2088 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);
2089 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp = TRUE;
2090 AttemptTmp->SessionConfigData.TargetInfoFromDhcp = TRUE;
2091 AttemptTmp->DhcpSuccess = FALSE;
2092
2093 //
2094 // Get some information from the dhcp server.
2095 //
2096 if (!mPrivate->Ipv6Flag) {
2097 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);
2098 if (!EFI_ERROR (Status)) {
2099 AttemptTmp->DhcpSuccess = TRUE;
2100 }
2101 } else {
2102 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);
2103 if (!EFI_ERROR (Status)) {
2104 AttemptTmp->DhcpSuccess = TRUE;
2105 }
2106 }
2107
2108 //
2109 // Refresh the state of this attempt to NVR.
2110 //
2111 UnicodeSPrint (
2112 mPrivate->PortString,
2113 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2114 L"Attempt %d",
2115 (UINTN) AttemptTmp->AttemptConfigIndex
2116 );
2117
2118 gRT->SetVariable (
2119 mPrivate->PortString,
2120 &gEfiIScsiInitiatorNameProtocolGuid,
2121 ISCSI_CONFIG_VAR_ATTR,
2122 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
2123 AttemptTmp
2124 );
2125
2126 continue;
2127 }
2128 } else if (AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp &&
2129 !AttemptTmp->ValidPath &&
2130 AttemptTmp->NicIndex == mPrivate->CurrentNic) {
2131 //
2132 // If the attempt associates with the current NIC, we can
2133 // get DHCP information for already added, but failed, attempt.
2134 //
2135 AttemptTmp->DhcpSuccess = FALSE;
2136 if (!mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP4)) {
2137 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);
2138 if (!EFI_ERROR (Status)) {
2139 AttemptTmp->DhcpSuccess = TRUE;
2140 }
2141 } else if (mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP6)) {
2142 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);
2143 if (!EFI_ERROR (Status)) {
2144 AttemptTmp->DhcpSuccess = TRUE;
2145 }
2146 }
2147
2148 //
2149 // Refresh the state of this attempt to NVR.
2150 //
2151 UnicodeSPrint (
2152 mPrivate->PortString,
2153 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2154 L"Attempt %d",
2155 (UINTN) AttemptTmp->AttemptConfigIndex
2156 );
2157
2158 gRT->SetVariable (
2159 mPrivate->PortString,
2160 &gEfiIScsiInitiatorNameProtocolGuid,
2161 ISCSI_CONFIG_VAR_ATTR,
2162 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
2163 AttemptTmp
2164 );
2165
2166 continue;
2167
2168 } else {
2169 continue;
2170 }
2171 }
2172
2173 //
2174 // This attempt does not exist in AttemptConfig. Try to add a new one.
2175 //
2176
2177 NicInfo = IScsiGetNicInfoByIndex (mPrivate->CurrentNic);
2178 ASSERT (NicInfo != NULL);
2179 IScsiMacAddrToStr (&NicInfo->PermanentAddress, NicInfo->HwAddressSize, NicInfo->VlanId, MacString);
2180 UnicodeSPrint (
2181 mPrivate->PortString,
2182 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2183 L"Attempt %d",
2184 (UINTN) AttemptConfigOrder[Index]
2185 );
2186
2187 GetVariable2 (
2188 mPrivate->PortString,
2189 &gEfiIScsiInitiatorNameProtocolGuid,
2190 (VOID**)&AttemptConfigData,
2191 NULL
2192 );
2193 AsciiStrToUnicodeStrS (AttemptConfigData->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));
2194
2195 if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_DISABLED ||
2196 StrCmp (MacString, AttemptMacString)) {
2197 continue;
2198 }
2199
2200 ASSERT (AttemptConfigOrder[Index] == AttemptConfigData->AttemptConfigIndex);
2201
2202 AttemptConfigData->NicIndex = NicInfo->NicIndex;
2203 AttemptConfigData->DhcpSuccess = FALSE;
2204 AttemptConfigData->ValidiBFTPath = (BOOLEAN) (mPrivate->EnableMpio ? TRUE : FALSE);
2205 AttemptConfigData->ValidPath = FALSE;
2206
2207 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
2208 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp = TRUE;
2209 AttemptConfigData->SessionConfigData.TargetInfoFromDhcp = TRUE;
2210
2211 AttemptConfigData->AutoConfigureMode =
2212 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);
2213 AttemptConfigData->AutoConfigureSuccess = FALSE;
2214 }
2215
2216 //
2217 // Get some information from dhcp server.
2218 //
2219 if (AttemptConfigData->SessionConfigData.Enabled != ISCSI_DISABLED &&
2220 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp) {
2221
2222 if (!mPrivate->Ipv6Flag &&
2223 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4 ||
2224 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4)) {
2225 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptConfigData);
2226 if (!EFI_ERROR (Status)) {
2227 AttemptConfigData->DhcpSuccess = TRUE;
2228 }
2229 } else if (mPrivate->Ipv6Flag &&
2230 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6 ||
2231 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6)) {
2232 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptConfigData);
2233 if (!EFI_ERROR (Status)) {
2234 AttemptConfigData->DhcpSuccess = TRUE;
2235 }
2236 }
2237
2238 //
2239 // Refresh the state of this attempt to NVR.
2240 //
2241 UnicodeSPrint (
2242 mPrivate->PortString,
2243 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2244 L"Attempt %d",
2245 (UINTN) AttemptConfigData->AttemptConfigIndex
2246 );
2247
2248 gRT->SetVariable (
2249 mPrivate->PortString,
2250 &gEfiIScsiInitiatorNameProtocolGuid,
2251 ISCSI_CONFIG_VAR_ATTR,
2252 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
2253 AttemptConfigData
2254 );
2255 }
2256
2257 //
2258 // Update Attempt Help Info.
2259 //
2260
2261 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED) {
2262 UnicodeSPrint (IScsiMode, 64, L"Disabled");
2263 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
2264 UnicodeSPrint (IScsiMode, 64, L"Enabled");
2265 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
2266 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");
2267 }
2268
2269 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {
2270 UnicodeSPrint (IpMode, 64, L"IP4");
2271 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {
2272 UnicodeSPrint (IpMode, 64, L"IP6");
2273 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
2274 UnicodeSPrint (IpMode, 64, L"Autoconfigure");
2275 }
2276
2277 UnicodeSPrint (
2278 mPrivate->PortString,
2279 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2280 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
2281 MacString,
2282 NicInfo->BusNumber,
2283 NicInfo->DeviceNumber,
2284 NicInfo->FunctionNumber,
2285 IScsiMode,
2286 IpMode
2287 );
2288
2289 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (
2290 mCallbackInfo->RegisteredHandle,
2291 0,
2292 mPrivate->PortString,
2293 NULL
2294 );
2295 if (AttemptConfigData->AttemptTitleHelpToken == 0) {
2296 return EFI_OUT_OF_RESOURCES;
2297 }
2298
2299 //
2300 // Record the attempt in global link list.
2301 //
2302 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
2303 mPrivate->AttemptCount++;
2304
2305 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
2306 mPrivate->MpioCount++;
2307 mPrivate->EnableMpio = TRUE;
2308
2309 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB) {
2310 mPrivate->Krb5MpioCount++;
2311 }
2312 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
2313 mPrivate->SinglePathCount++;
2314 }
2315 }
2316
2317 //
2318 // Reorder the AttemptConfig by the configured order.
2319 //
2320 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
2321 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);
2322 if (AttemptConfigData == NULL) {
2323 continue;
2324 }
2325
2326 RemoveEntryList (&AttemptConfigData->Link);
2327 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
2328 }
2329
2330 //
2331 // Update the Main Form.
2332 //
2333 IScsiConfigUpdateAttempt ();
2334
2335 FreePool (AttemptConfigOrder);
2336
2337 //
2338 // There should be at least one attempt configuration.
2339 //
2340 if (!mPrivate->EnableMpio) {
2341 if (mPrivate->SinglePathCount == 0) {
2342 return EFI_NOT_FOUND;
2343 }
2344 mPrivate->ValidSinglePathCount = mPrivate->SinglePathCount;
2345 }
2346
2347 return EFI_SUCCESS;
2348 }
2349
2350
2351 /**
2352 Get the device path of the iSCSI tcp connection and update it.
2353
2354 @param Session The iSCSI session.
2355
2356 @return The updated device path.
2357 @retval NULL Other errors as indicated.
2358
2359 **/
2360 EFI_DEVICE_PATH_PROTOCOL *
2361 IScsiGetTcpConnDevicePath (
2362 IN ISCSI_SESSION *Session
2363 )
2364 {
2365 ISCSI_CONNECTION *Conn;
2366 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2367 EFI_STATUS Status;
2368 EFI_DEV_PATH *DPathNode;
2369 UINTN PathLen;
2370
2371 if (Session->State != SESSION_STATE_LOGGED_IN) {
2372 return NULL;
2373 }
2374
2375 Conn = NET_LIST_USER_STRUCT_S (
2376 Session->Conns.ForwardLink,
2377 ISCSI_CONNECTION,
2378 Link,
2379 ISCSI_CONNECTION_SIGNATURE
2380 );
2381
2382 Status = gBS->HandleProtocol (
2383 Conn->TcpIo.Handle,
2384 &gEfiDevicePathProtocolGuid,
2385 (VOID **) &DevicePath
2386 );
2387 if (EFI_ERROR (Status)) {
2388 return NULL;
2389 }
2390 //
2391 // Duplicate it.
2392 //
2393 DevicePath = DuplicateDevicePath (DevicePath);
2394 if (DevicePath == NULL) {
2395 return NULL;
2396 }
2397
2398 DPathNode = (EFI_DEV_PATH *) DevicePath;
2399
2400 while (!IsDevicePathEnd (&DPathNode->DevPath)) {
2401 if (DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) {
2402 if (!Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP) {
2403 DPathNode->Ipv4.LocalPort = 0;
2404
2405 DPathNode->Ipv4.StaticIpAddress =
2406 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);
2407
2408 //
2409 // Add a judgement here to support previous versions of IPv4_DEVICE_PATH.
2410 // In previous versions of IPv4_DEVICE_PATH, GatewayIpAddress and SubnetMask
2411 // do not exist.
2412 // In new version of IPv4_DEVICE_PATH, structcure length is 27.
2413 //
2414
2415 PathLen = DevicePathNodeLength (&DPathNode->Ipv4);
2416
2417 if (PathLen == IP4_NODE_LEN_NEW_VERSIONS) {
2418
2419 IP4_COPY_ADDRESS (
2420 &DPathNode->Ipv4.GatewayIpAddress,
2421 &Session->ConfigData->SessionConfigData.Gateway
2422 );
2423
2424 IP4_COPY_ADDRESS (
2425 &DPathNode->Ipv4.SubnetMask,
2426 &Session->ConfigData->SessionConfigData.SubnetMask
2427 );
2428 }
2429
2430 break;
2431 } else if (Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv6_DP) {
2432 DPathNode->Ipv6.LocalPort = 0;
2433
2434 //
2435 // Add a judgement here to support previous versions of IPv6_DEVICE_PATH.
2436 // In previous versions of IPv6_DEVICE_PATH, IpAddressOrigin, PrefixLength
2437 // and GatewayIpAddress do not exist.
2438 // In new version of IPv6_DEVICE_PATH, structure length is 60, while in
2439 // old versions, the length is 43.
2440 //
2441
2442 PathLen = DevicePathNodeLength (&DPathNode->Ipv6);
2443
2444 if (PathLen == IP6_NODE_LEN_NEW_VERSIONS ) {
2445
2446 DPathNode->Ipv6.IpAddressOrigin = 0;
2447 DPathNode->Ipv6.PrefixLength = IP6_PREFIX_LENGTH;
2448 ZeroMem (&DPathNode->Ipv6.GatewayIpAddress, sizeof (EFI_IPv6_ADDRESS));
2449 }
2450 else if (PathLen == IP6_NODE_LEN_OLD_VERSIONS) {
2451
2452 //
2453 // StaticIPAddress is a field in old versions of IPv6_DEVICE_PATH, while ignored in new
2454 // version. Set StaticIPAddress through its' offset in old IPv6_DEVICE_PATH.
2455 //
2456 *((UINT8 *)(&DPathNode->Ipv6) + IP6_OLD_IPADDRESS_OFFSET) =
2457 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);
2458 }
2459
2460 break;
2461 }
2462 }
2463
2464 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);
2465 }
2466
2467 return DevicePath;
2468 }
2469
2470
2471 /**
2472 Abort the session when the transition from BS to RT is initiated.
2473
2474 @param[in] Event The event signaled.
2475 @param[in] Context The iSCSI driver data.
2476
2477 **/
2478 VOID
2479 EFIAPI
2480 IScsiOnExitBootService (
2481 IN EFI_EVENT Event,
2482 IN VOID *Context
2483 )
2484 {
2485 ISCSI_DRIVER_DATA *Private;
2486
2487 Private = (ISCSI_DRIVER_DATA *) Context;
2488 gBS->CloseEvent (Private->ExitBootServiceEvent);
2489
2490 if (Private->Session != NULL) {
2491 IScsiSessionAbort (Private->Session);
2492 }
2493 }
2494
2495 /**
2496 Tests whether a controller handle is being managed by IScsi driver.
2497
2498 This function tests whether the driver specified by DriverBindingHandle is
2499 currently managing the controller specified by ControllerHandle. This test
2500 is performed by evaluating if the the protocol specified by ProtocolGuid is
2501 present on ControllerHandle and is was opened by DriverBindingHandle and Nic
2502 Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.
2503 If ProtocolGuid is NULL, then ASSERT().
2504
2505 @param ControllerHandle A handle for a controller to test.
2506 @param DriverBindingHandle Specifies the driver binding handle for the
2507 driver.
2508 @param ProtocolGuid Specifies the protocol that the driver specified
2509 by DriverBindingHandle opens in its Start()
2510 function.
2511
2512 @retval EFI_SUCCESS ControllerHandle is managed by the driver
2513 specified by DriverBindingHandle.
2514 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver
2515 specified by DriverBindingHandle.
2516
2517 **/
2518 EFI_STATUS
2519 EFIAPI
2520 IScsiTestManagedDevice (
2521 IN EFI_HANDLE ControllerHandle,
2522 IN EFI_HANDLE DriverBindingHandle,
2523 IN EFI_GUID *ProtocolGuid
2524 )
2525 {
2526 EFI_STATUS Status;
2527 VOID *ManagedInterface;
2528 EFI_HANDLE NicControllerHandle;
2529
2530 ASSERT (ProtocolGuid != NULL);
2531
2532 NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid);
2533 if (NicControllerHandle == NULL) {
2534 return EFI_UNSUPPORTED;
2535 }
2536
2537 Status = gBS->OpenProtocol (
2538 ControllerHandle,
2539 (EFI_GUID *) ProtocolGuid,
2540 &ManagedInterface,
2541 DriverBindingHandle,
2542 NicControllerHandle,
2543 EFI_OPEN_PROTOCOL_BY_DRIVER
2544 );
2545 if (!EFI_ERROR (Status)) {
2546 gBS->CloseProtocol (
2547 ControllerHandle,
2548 (EFI_GUID *) ProtocolGuid,
2549 DriverBindingHandle,
2550 NicControllerHandle
2551 );
2552 return EFI_UNSUPPORTED;
2553 }
2554
2555 if (Status != EFI_ALREADY_STARTED) {
2556 return EFI_UNSUPPORTED;
2557 }
2558
2559 return EFI_SUCCESS;
2560 }