]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IScsiDxe/IScsiMisc.c
7bed95a8fba369314df00279d9cd6abe1c54ae29
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiMisc.c
1 /** @file
2 Miscellaneous routines for iSCSI driver.
3
4 Copyright (c) 2004 - 2018, 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 DEBUG ((DEBUG_ERROR,
849 "%a: Failed to set 'InitialAttemptOrder' with Guid (%g): "
850 "%r\n",
851 __FUNCTION__, &gIScsiConfigGuid, Status));
852 return Status;
853 }
854
855 //
856 // Create new Attempt
857 //
858 AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA));
859 if (AttemptConfigData == NULL) {
860 return EFI_OUT_OF_RESOURCES;
861 }
862 ConfigData = &AttemptConfigData->SessionConfigData;
863 ConfigData->TargetPort = ISCSI_WELL_KNOWN_PORT;
864 ConfigData->ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;
865 ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY;
866
867 AttemptConfigData->AuthenticationType = ISCSI_AUTH_TYPE_CHAP;
868 AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI;
869 //
870 // Configure the Attempt index and set variable.
871 //
872 AttemptConfigData->AttemptConfigIndex = Index;
873
874 //
875 // Set the attempt name according to the order.
876 //
877 UnicodeSPrint (
878 mPrivate->PortString,
879 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
880 L"Attempt %d",
881 (UINTN) AttemptConfigData->AttemptConfigIndex
882 );
883 UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, ATTEMPT_NAME_SIZE);
884
885 Status = gRT->SetVariable (
886 mPrivate->PortString,
887 &gEfiIScsiInitiatorNameProtocolGuid,
888 ISCSI_CONFIG_VAR_ATTR,
889 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
890 AttemptConfigData
891 );
892 FreePool (AttemptConfigData);
893 if (EFI_ERROR (Status)) {
894 DEBUG ((DEBUG_ERROR,
895 "%a: Failed to set variable (mPrivate->PortString) with Guid (%g): "
896 "%r\n",
897 __FUNCTION__, &gEfiIScsiInitiatorNameProtocolGuid, Status));
898 return Status;
899 }
900 }
901
902 return EFI_SUCCESS;
903 }
904
905 /**
906 Create the iSCSI configuration Keywords for each attempt. You can find the keywords
907 defined in the "x-UEFI-ns" namespace (http://www.uefi.org/confignamespace).
908
909 @param[in] KeywordNum The number Sets of Keywords will be created.
910
911 @retval EFI_SUCCESS The operation is completed.
912 @retval Others Failed to create the Keywords.
913
914 **/
915 EFI_STATUS
916 IScsiCreateKeywords (
917 IN UINTN KeywordNum
918 )
919 {
920 VOID *StartOpCodeHandle;
921 EFI_IFR_GUID_LABEL *StartLabel;
922 VOID *EndOpCodeHandle;
923 EFI_IFR_GUID_LABEL *EndLabel;
924 UINTN Index;
925 EFI_STRING_ID StringToken;
926 CHAR16 StringId[64];
927 CHAR16 KeywordId[32];
928 EFI_STATUS Status;
929
930 Status = IScsiCreateOpCode (
931 KEYWORD_ENTRY_LABEL,
932 &StartOpCodeHandle,
933 &StartLabel,
934 &EndOpCodeHandle,
935 &EndLabel
936 );
937 if (EFI_ERROR (Status)) {
938 return EFI_OUT_OF_RESOURCES;
939 }
940
941 for (Index = 1; Index <= KeywordNum; Index ++) {
942 //
943 // Create iSCSIAttemptName Keyword.
944 //
945 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_ATTEMPTT_NAME_PROMPT%d", Index);
946 StringToken = HiiSetString (
947 mCallbackInfo->RegisteredHandle,
948 0,
949 StringId,
950 NULL
951 );
952 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIAttemptName:%d", Index);
953 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
954 HiiCreateStringOpCode (
955 StartOpCodeHandle,
956 (EFI_QUESTION_ID) (ATTEMPT_ATTEMPT_NAME_QUESTION_ID + (Index - 1)),
957 CONFIGURATION_VARSTORE_ID,
958 (UINT16) (ATTEMPT_ATTEMPT_NAME_VAR_OFFSET + ATTEMPT_NAME_SIZE * (Index - 1) * sizeof (CHAR16)),
959 StringToken,
960 StringToken,
961 EFI_IFR_FLAG_READ_ONLY,
962 0,
963 0,
964 ATTEMPT_NAME_SIZE,
965 NULL
966 );
967
968 //
969 // Create iSCSIBootEnable Keyword.
970 //
971 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_MODE_PROMPT%d", Index);
972 StringToken = HiiSetString (
973 mCallbackInfo->RegisteredHandle,
974 0,
975 StringId,
976 NULL
977 );
978 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIBootEnable:%d", Index);
979 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
980 HiiCreateNumericOpCode (
981 StartOpCodeHandle,
982 (EFI_QUESTION_ID) (ATTEMPT_BOOTENABLE_QUESTION_ID + (Index - 1)),
983 CONFIGURATION_VARSTORE_ID,
984 (UINT16) (ATTEMPT_BOOTENABLE_VAR_OFFSET + (Index - 1)),
985 StringToken,
986 StringToken,
987 0,
988 EFI_IFR_NUMERIC_SIZE_1,
989 0,
990 2,
991 0,
992 NULL
993 );
994
995 //
996 // Create iSCSIIpAddressType Keyword.
997 //
998 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_IP_MODE_PROMPT%d", Index);
999 StringToken = HiiSetString (
1000 mCallbackInfo->RegisteredHandle,
1001 0,
1002 StringId,
1003 NULL
1004 );
1005 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIIpAddressType:%d", Index);
1006 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1007 HiiCreateNumericOpCode (
1008 StartOpCodeHandle,
1009 (EFI_QUESTION_ID) (ATTEMPT_ADDRESS_TYPE_QUESTION_ID + (Index - 1)),
1010 CONFIGURATION_VARSTORE_ID,
1011 (UINT16) (ATTEMPT_ADDRESS_TYPE_VAR_OFFSET + (Index - 1)),
1012 StringToken,
1013 StringToken,
1014 0,
1015 EFI_IFR_NUMERIC_SIZE_1,
1016 0,
1017 2,
1018 0,
1019 NULL
1020 );
1021
1022 //
1023 // Create iSCSIConnectRetry Keyword.
1024 //
1025 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CONNECT_RETRY_PROMPT%d", Index);
1026 StringToken = HiiSetString (
1027 mCallbackInfo->RegisteredHandle,
1028 0,
1029 StringId,
1030 NULL
1031 );
1032 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIConnectRetry:%d", Index);
1033 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1034 HiiCreateNumericOpCode (
1035 StartOpCodeHandle,
1036 (EFI_QUESTION_ID) (ATTEMPT_CONNECT_RETRY_QUESTION_ID + (Index - 1)),
1037 CONFIGURATION_VARSTORE_ID,
1038 (UINT16) (ATTEMPT_CONNECT_RETRY_VAR_OFFSET + (Index - 1)),
1039 StringToken,
1040 StringToken,
1041 0,
1042 EFI_IFR_NUMERIC_SIZE_1,
1043 0,
1044 16,
1045 0,
1046 NULL
1047 );
1048
1049 //
1050 // Create iSCSIConnectTimeout Keyword.
1051 //
1052 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CONNECT_TIMEOUT_PROMPT%d", Index);
1053 StringToken = HiiSetString (
1054 mCallbackInfo->RegisteredHandle,
1055 0,
1056 StringId,
1057 NULL
1058 );
1059 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIConnectTimeout:%d", Index);
1060 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1061 HiiCreateNumericOpCode (
1062 StartOpCodeHandle,
1063 (EFI_QUESTION_ID) (ATTEMPT_CONNECT_TIMEOUT_QUESTION_ID + (Index - 1)),
1064 CONFIGURATION_VARSTORE_ID,
1065 (UINT16) (ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET + 2 * (Index - 1)),
1066 StringToken,
1067 StringToken,
1068 0,
1069 EFI_IFR_NUMERIC_SIZE_2,
1070 CONNECT_MIN_TIMEOUT,
1071 CONNECT_MAX_TIMEOUT,
1072 0,
1073 NULL
1074 );
1075
1076 //
1077 // Create ISID Keyword.
1078 //
1079 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_ISID_PROMPT%d", Index);
1080 StringToken = HiiSetString (
1081 mCallbackInfo->RegisteredHandle,
1082 0,
1083 StringId,
1084 NULL
1085 );
1086 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIISID:%d", Index);
1087 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1088 HiiCreateStringOpCode (
1089 StartOpCodeHandle,
1090 (EFI_QUESTION_ID) (ATTEMPT_ISID_QUESTION_ID + (Index - 1)),
1091 CONFIGURATION_VARSTORE_ID,
1092 (UINT16) (ATTEMPT_ISID_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1093 StringToken,
1094 STRING_TOKEN (STR_ISCSI_ISID_HELP),
1095 0,
1096 0,
1097 ISID_CONFIGURABLE_MIN_LEN,
1098 ISID_CONFIGURABLE_STORAGE,
1099 NULL
1100 );
1101
1102 //
1103 // Create iSCSIInitiatorInfoViaDHCP Keyword.
1104 //
1105 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_VIA_DHCP_PROMPT%d", Index);
1106 StringToken = HiiSetString (
1107 mCallbackInfo->RegisteredHandle,
1108 0,
1109 StringId,
1110 NULL
1111 );
1112 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorInfoViaDHCP:%d", Index);
1113 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1114 HiiCreateNumericOpCode (
1115 StartOpCodeHandle,
1116 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_VIA_DHCP_QUESTION_ID + (Index - 1)),
1117 CONFIGURATION_VARSTORE_ID,
1118 (UINT16) (ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET + (Index - 1)),
1119 StringToken,
1120 StringToken,
1121 0,
1122 0,
1123 0,
1124 1,
1125 0,
1126 NULL
1127 );
1128
1129 //
1130 // Create iSCSIInitiatorIpAddress Keyword.
1131 //
1132 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_IP_ADDRESS_PROMPT%d", Index);
1133 StringToken = HiiSetString (
1134 mCallbackInfo->RegisteredHandle,
1135 0,
1136 StringId,
1137 NULL
1138 );
1139 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorIpAddress:%d", Index);
1140 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1141 HiiCreateStringOpCode (
1142 StartOpCodeHandle,
1143 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_IP_ADDRESS_QUESTION_ID + (Index - 1)),
1144 CONFIGURATION_VARSTORE_ID,
1145 (UINT16) (ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1146 StringToken,
1147 StringToken,
1148 0,
1149 0,
1150 IP4_MIN_SIZE,
1151 IP4_STR_MAX_SIZE,
1152 NULL
1153 );
1154
1155 //
1156 // Create iSCSIInitiatorNetmask Keyword.
1157 //
1158 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_NET_MASK_PROMPT%d", Index);
1159 StringToken = HiiSetString (
1160 mCallbackInfo->RegisteredHandle,
1161 0,
1162 StringId,
1163 NULL
1164 );
1165 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorNetmask:%d", Index);
1166 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1167 HiiCreateStringOpCode (
1168 StartOpCodeHandle,
1169 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_NET_MASK_QUESTION_ID + (Index - 1)),
1170 CONFIGURATION_VARSTORE_ID,
1171 (UINT16) (ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1172 StringToken,
1173 StringToken,
1174 0,
1175 0,
1176 IP4_MIN_SIZE,
1177 IP4_STR_MAX_SIZE,
1178 NULL
1179 );
1180
1181 //
1182 // Create iSCSIInitiatorGateway Keyword.
1183 //
1184 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_GATE_PROMPT%d", Index);
1185 StringToken = HiiSetString (
1186 mCallbackInfo->RegisteredHandle,
1187 0,
1188 StringId,
1189 NULL
1190 );
1191 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorGateway:%d", Index);
1192 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1193 HiiCreateStringOpCode (
1194 StartOpCodeHandle,
1195 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_GATE_WAY_QUESTION_ID + (Index - 1)),
1196 CONFIGURATION_VARSTORE_ID,
1197 (UINT16) (ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1198 StringToken,
1199 StringToken,
1200 0,
1201 0,
1202 IP4_MIN_SIZE,
1203 IP4_STR_MAX_SIZE,
1204 NULL
1205 );
1206
1207 //
1208 // Create iSCSITargetInfoViaDHCP Keyword.
1209 //
1210 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_VIA_DHCP_PROMPT%d", Index);
1211 StringToken = HiiSetString (
1212 mCallbackInfo->RegisteredHandle,
1213 0,
1214 StringId,
1215 NULL
1216 );
1217 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetInfoViaDHCP:%d", Index);
1218 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1219 HiiCreateNumericOpCode (
1220 StartOpCodeHandle,
1221 (EFI_QUESTION_ID) (ATTEMPT_TARGET_VIA_DHCP_QUESTION_ID + (Index - 1)),
1222 CONFIGURATION_VARSTORE_ID,
1223 (UINT16) (ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET + (Index - 1)),
1224 StringToken,
1225 StringToken,
1226 0,
1227 0,
1228 0,
1229 1,
1230 0,
1231 NULL
1232 );
1233
1234 //
1235 // Create iSCSITargetTcpPort Keyword.
1236 //
1237 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_TCP_PORT_PROMPT%d", Index);
1238 StringToken = HiiSetString (
1239 mCallbackInfo->RegisteredHandle,
1240 0,
1241 StringId,
1242 NULL
1243 );
1244 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetTcpPort:%d", Index);
1245 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1246 HiiCreateNumericOpCode (
1247 StartOpCodeHandle,
1248 (EFI_QUESTION_ID) (ATTEMPT_TARGET_TCP_PORT_QUESTION_ID + (Index - 1)),
1249 CONFIGURATION_VARSTORE_ID,
1250 (UINT16) (ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET + 2 * (Index - 1)),
1251 StringToken,
1252 StringToken,
1253 0,
1254 EFI_IFR_NUMERIC_SIZE_2,
1255 TARGET_PORT_MIN_NUM,
1256 TARGET_PORT_MAX_NUM,
1257 0,
1258 NULL
1259 );
1260
1261 //
1262 // Create iSCSITargetName Keyword.
1263 //
1264 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_NAME_PROMPT%d", Index);
1265 StringToken = HiiSetString (
1266 mCallbackInfo->RegisteredHandle,
1267 0,
1268 StringId,
1269 NULL
1270 );
1271 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetName:%d", Index);
1272 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1273 HiiCreateStringOpCode (
1274 StartOpCodeHandle,
1275 (EFI_QUESTION_ID) (ATTEMPT_TARGET_NAME_QUESTION_ID + (Index - 1)),
1276 CONFIGURATION_VARSTORE_ID,
1277 (UINT16) (ATTEMPT_TARGET_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1278 StringToken,
1279 StringToken,
1280 0,
1281 0,
1282 ISCSI_NAME_IFR_MIN_SIZE,
1283 ISCSI_NAME_IFR_MAX_SIZE,
1284 NULL
1285 );
1286
1287 //
1288 // Create iSCSITargetIpAddress Keyword.
1289 //
1290 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_IP_ADDRESS_PROMPT%d", Index);
1291 StringToken = HiiSetString (
1292 mCallbackInfo->RegisteredHandle,
1293 0,
1294 StringId,
1295 NULL
1296 );
1297 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetIpAddress:%d", Index);
1298 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1299 HiiCreateStringOpCode (
1300 StartOpCodeHandle,
1301 (EFI_QUESTION_ID) (ATTEMPT_TARGET_IP_ADDRESS_QUESTION_ID + (Index - 1)),
1302 CONFIGURATION_VARSTORE_ID,
1303 (UINT16) (ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1304 StringToken,
1305 StringToken,
1306 0,
1307 0,
1308 IP_MIN_SIZE,
1309 IP_STR_MAX_SIZE,
1310 NULL
1311 );
1312
1313 //
1314 // Create iSCSILUN Keyword.
1315 //
1316 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_LUN_PROMPT%d", Index);
1317 StringToken = HiiSetString (
1318 mCallbackInfo->RegisteredHandle,
1319 0,
1320 StringId,
1321 NULL
1322 );
1323 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSILUN:%d", Index);
1324 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1325 HiiCreateStringOpCode (
1326 StartOpCodeHandle,
1327 (EFI_QUESTION_ID) (ATTEMPT_LUN_QUESTION_ID + (Index - 1)),
1328 CONFIGURATION_VARSTORE_ID,
1329 (UINT16) (ATTEMPT_LUN_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1330 StringToken,
1331 StringToken,
1332 0,
1333 0,
1334 LUN_MIN_SIZE,
1335 LUN_MAX_SIZE,
1336 NULL
1337 );
1338
1339 //
1340 // Create iSCSIAuthenticationMethod Keyword.
1341 //
1342 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_AUTHENTICATION_METHOD_PROMPT%d", Index);
1343 StringToken = HiiSetString (
1344 mCallbackInfo->RegisteredHandle,
1345 0,
1346 StringId,
1347 NULL
1348 );
1349 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIAuthenticationMethod:%d", Index);
1350 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1351 HiiCreateNumericOpCode (
1352 StartOpCodeHandle,
1353 (EFI_QUESTION_ID) (ATTEMPT_AUTHENTICATION_METHOD_QUESTION_ID + (Index - 1)),
1354 CONFIGURATION_VARSTORE_ID,
1355 (UINT16) (ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET + (Index - 1)),
1356 StringToken,
1357 StringToken,
1358 0,
1359 0,
1360 0,
1361 1,
1362 0,
1363 NULL
1364 );
1365
1366 //
1367 // Create iSCSIChapType Keyword.
1368 //
1369 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHARTYPE_PROMPT%d", Index);
1370 StringToken = HiiSetString (
1371 mCallbackInfo->RegisteredHandle,
1372 0,
1373 StringId,
1374 NULL
1375 );
1376 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapType:%d", Index);
1377 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1378 HiiCreateNumericOpCode (
1379 StartOpCodeHandle,
1380 (EFI_QUESTION_ID) (ATTEMPT_CHARTYPE_QUESTION_ID + (Index - 1)),
1381 CONFIGURATION_VARSTORE_ID,
1382 (UINT16) (ATTEMPT_CHARTYPE_VAR_OFFSET + (Index - 1)),
1383 StringToken,
1384 StringToken,
1385 0,
1386 0,
1387 0,
1388 1,
1389 0,
1390 NULL
1391 );
1392
1393 //
1394 // Create iSCSIChapUsername Keyword.
1395 //
1396 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_USER_NAME_PROMPT%d", Index);
1397 StringToken = HiiSetString (
1398 mCallbackInfo->RegisteredHandle,
1399 0,
1400 StringId,
1401 NULL
1402 );
1403 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapUsername:%d", Index);
1404 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1405 HiiCreateStringOpCode (
1406 StartOpCodeHandle,
1407 (EFI_QUESTION_ID) (ATTEMPT_CHAR_USER_NAME_QUESTION_ID + (Index - 1)),
1408 CONFIGURATION_VARSTORE_ID,
1409 (UINT16) (ATTEMPT_CHAR_USER_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1410 StringToken,
1411 StringToken,
1412 0,
1413 0,
1414 0,
1415 ISCSI_CHAP_NAME_MAX_LEN,
1416 NULL
1417 );
1418
1419 //
1420 // Create iSCSIChapSecret Keyword.
1421 //
1422 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_SECRET_PROMPT%d", Index);
1423 StringToken = HiiSetString (
1424 mCallbackInfo->RegisteredHandle,
1425 0,
1426 StringId,
1427 NULL
1428 );
1429 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapSecret:%d", Index);
1430 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1431 HiiCreateStringOpCode (
1432 StartOpCodeHandle,
1433 (EFI_QUESTION_ID) (ATTEMPT_CHAR_SECRET_QUESTION_ID + (Index - 1)),
1434 CONFIGURATION_VARSTORE_ID,
1435 (UINT16) (ATTEMPT_CHAR_SECRET_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1436 StringToken,
1437 StringToken,
1438 0,
1439 0,
1440 ISCSI_CHAP_SECRET_MIN_LEN,
1441 ISCSI_CHAP_SECRET_MAX_LEN,
1442 NULL
1443 );
1444
1445 //
1446 // Create iSCSIReverseChapUsername Keyword.
1447 //
1448 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_REVERSE_USER_NAME_PROMPT%d", Index);
1449 StringToken = HiiSetString (
1450 mCallbackInfo->RegisteredHandle,
1451 0,
1452 StringId,
1453 NULL
1454 );
1455 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIReverseChapUsername:%d", Index);
1456 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1457 HiiCreateStringOpCode (
1458 StartOpCodeHandle,
1459 (EFI_QUESTION_ID) (ATTEMPT_CHAR_REVERSE_USER_NAME_QUESTION_ID + (Index - 1)),
1460 CONFIGURATION_VARSTORE_ID,
1461 (UINT16) (ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1462 StringToken,
1463 StringToken,
1464 0,
1465 0,
1466 0,
1467 ISCSI_CHAP_NAME_MAX_LEN,
1468 NULL
1469 );
1470
1471 //
1472 // Create iSCSIReverseChapSecret Keyword.
1473 //
1474 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_REVERSE_SECRET_PROMPT%d", Index);
1475 StringToken = HiiSetString (
1476 mCallbackInfo->RegisteredHandle,
1477 0,
1478 StringId,
1479 NULL
1480 );
1481 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIReverseChapSecret:%d", Index);
1482 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1483 HiiCreateStringOpCode (
1484 StartOpCodeHandle,
1485 (EFI_QUESTION_ID) (ATTEMPT_CHAR_REVERSE_SECRET_QUESTION_ID + (Index - 1)),
1486 CONFIGURATION_VARSTORE_ID,
1487 (UINT16) (ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1488 StringToken,
1489 StringToken,
1490 0,
1491 0,
1492 ISCSI_CHAP_SECRET_MIN_LEN,
1493 ISCSI_CHAP_SECRET_MAX_LEN,
1494 NULL
1495 );
1496 }
1497
1498 Status = HiiUpdateForm (
1499 mCallbackInfo->RegisteredHandle, // HII handle
1500 &gIScsiConfigGuid, // Formset GUID
1501 FORMID_ATTEMPT_FORM, // Form ID
1502 StartOpCodeHandle, // Label for where to insert opcodes
1503 EndOpCodeHandle // Replace data
1504 );
1505
1506 HiiFreeOpCodeHandle (StartOpCodeHandle);
1507 HiiFreeOpCodeHandle (EndOpCodeHandle);
1508
1509 return Status;
1510 }
1511
1512 /**
1513
1514 Free the attempt configure data variable.
1515
1516 **/
1517 VOID
1518 IScsiCleanAttemptVariable (
1519 IN VOID
1520 )
1521 {
1522 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
1523 UINT8 *AttemptConfigOrder;
1524 UINTN AttemptConfigOrderSize;
1525 UINTN Index;
1526
1527 //
1528 // Get the initialized attempt order.
1529 //
1530 AttemptConfigOrder = IScsiGetVariableAndSize (
1531 L"InitialAttemptOrder",
1532 &gIScsiConfigGuid,
1533 &AttemptConfigOrderSize
1534 );
1535 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
1536 return;
1537 }
1538
1539 for (Index = 1; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1540 UnicodeSPrint (
1541 mPrivate->PortString,
1542 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
1543 L"Attempt %d",
1544 Index
1545 );
1546
1547 GetVariable2 (
1548 mPrivate->PortString,
1549 &gEfiIScsiInitiatorNameProtocolGuid,
1550 (VOID**)&AttemptConfigData,
1551 NULL
1552 );
1553
1554 if (AttemptConfigData != NULL) {
1555 gRT->SetVariable (
1556 mPrivate->PortString,
1557 &gEfiIScsiInitiatorNameProtocolGuid,
1558 0,
1559 0,
1560 NULL
1561 );
1562 }
1563 }
1564 return;
1565 }
1566
1567 /**
1568 Get the recorded NIC info from global structure by the Index.
1569
1570 @param[in] NicIndex The index indicates the position of NIC info.
1571
1572 @return Pointer to the NIC info, or NULL if not found.
1573
1574 **/
1575 ISCSI_NIC_INFO *
1576 IScsiGetNicInfoByIndex (
1577 IN UINT8 NicIndex
1578 )
1579 {
1580 LIST_ENTRY *Entry;
1581 ISCSI_NIC_INFO *NicInfo;
1582
1583 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
1584 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
1585 if (NicInfo->NicIndex == NicIndex) {
1586 return NicInfo;
1587 }
1588 }
1589
1590 return NULL;
1591 }
1592
1593
1594 /**
1595 Get the NIC's PCI location and return it according to the composited
1596 format defined in iSCSI Boot Firmware Table.
1597
1598 @param[in] Controller The handle of the controller.
1599 @param[out] Bus The bus number.
1600 @param[out] Device The device number.
1601 @param[out] Function The function number.
1602
1603 @return The composited representation of the NIC PCI location.
1604
1605 **/
1606 UINT16
1607 IScsiGetNICPciLocation (
1608 IN EFI_HANDLE Controller,
1609 OUT UINTN *Bus,
1610 OUT UINTN *Device,
1611 OUT UINTN *Function
1612 )
1613 {
1614 EFI_STATUS Status;
1615 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1616 EFI_HANDLE PciIoHandle;
1617 EFI_PCI_IO_PROTOCOL *PciIo;
1618 UINTN Segment;
1619
1620 Status = gBS->HandleProtocol (
1621 Controller,
1622 &gEfiDevicePathProtocolGuid,
1623 (VOID **) &DevicePath
1624 );
1625 if (EFI_ERROR (Status)) {
1626 return 0;
1627 }
1628
1629 Status = gBS->LocateDevicePath (
1630 &gEfiPciIoProtocolGuid,
1631 &DevicePath,
1632 &PciIoHandle
1633 );
1634 if (EFI_ERROR (Status)) {
1635 return 0;
1636 }
1637
1638 Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
1639 if (EFI_ERROR (Status)) {
1640 return 0;
1641 }
1642
1643 Status = PciIo->GetLocation (PciIo, &Segment, Bus, Device, Function);
1644 if (EFI_ERROR (Status)) {
1645 return 0;
1646 }
1647
1648 return (UINT16) ((*Bus << 8) | (*Device << 3) | *Function);
1649 }
1650
1651
1652 /**
1653 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1654 buffer, and the size of the buffer. If failure, return NULL.
1655
1656 @param[in] Name String part of EFI variable name.
1657 @param[in] VendorGuid GUID part of EFI variable name.
1658 @param[out] VariableSize Returns the size of the EFI variable that was read.
1659
1660 @return Dynamically allocated memory that contains a copy of the EFI variable.
1661 @return Caller is responsible freeing the buffer.
1662 @retval NULL Variable was not read.
1663
1664 **/
1665 VOID *
1666 IScsiGetVariableAndSize (
1667 IN CHAR16 *Name,
1668 IN EFI_GUID *VendorGuid,
1669 OUT UINTN *VariableSize
1670 )
1671 {
1672 EFI_STATUS Status;
1673 UINTN BufferSize;
1674 VOID *Buffer;
1675
1676 Buffer = NULL;
1677
1678 //
1679 // Pass in a zero size buffer to find the required buffer size.
1680 //
1681 BufferSize = 0;
1682 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
1683 if (Status == EFI_BUFFER_TOO_SMALL) {
1684 //
1685 // Allocate the buffer to return
1686 //
1687 Buffer = AllocateZeroPool (BufferSize);
1688 if (Buffer == NULL) {
1689 return NULL;
1690 }
1691 //
1692 // Read variable into the allocated buffer.
1693 //
1694 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
1695 if (EFI_ERROR (Status)) {
1696 BufferSize = 0;
1697 }
1698 }
1699
1700 *VariableSize = BufferSize;
1701 return Buffer;
1702 }
1703
1704
1705 /**
1706 Create the iSCSI driver data.
1707
1708 @param[in] Image The handle of the driver image.
1709 @param[in] Controller The handle of the controller.
1710
1711 @return The iSCSI driver data created.
1712 @retval NULL Other errors as indicated.
1713
1714 **/
1715 ISCSI_DRIVER_DATA *
1716 IScsiCreateDriverData (
1717 IN EFI_HANDLE Image,
1718 IN EFI_HANDLE Controller
1719 )
1720 {
1721 ISCSI_DRIVER_DATA *Private;
1722 EFI_STATUS Status;
1723
1724 Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));
1725 if (Private == NULL) {
1726 return NULL;
1727 }
1728
1729 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;
1730 Private->Image = Image;
1731 Private->Controller = Controller;
1732 Private->Session = NULL;
1733
1734 //
1735 // Create an event to be signaled when the BS to RT transition is triggerd so
1736 // as to abort the iSCSI session.
1737 //
1738 Status = gBS->CreateEventEx (
1739 EVT_NOTIFY_SIGNAL,
1740 TPL_CALLBACK,
1741 IScsiOnExitBootService,
1742 Private,
1743 &gEfiEventExitBootServicesGuid,
1744 &Private->ExitBootServiceEvent
1745 );
1746 if (EFI_ERROR (Status)) {
1747 FreePool (Private);
1748 return NULL;
1749 }
1750
1751 Private->ExtScsiPassThruHandle = NULL;
1752 CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));
1753
1754 //
1755 // 0 is designated to the TargetId, so use another value for the AdapterId.
1756 //
1757 Private->ExtScsiPassThruMode.AdapterId = 2;
1758 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
1759 Private->ExtScsiPassThruMode.IoAlign = 4;
1760 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
1761
1762 return Private;
1763 }
1764
1765
1766 /**
1767 Clean the iSCSI driver data.
1768
1769 @param[in] Private The iSCSI driver data.
1770
1771 @retval EFI_SUCCESS The clean operation is successful.
1772 @retval Others Other errors as indicated.
1773
1774 **/
1775 EFI_STATUS
1776 IScsiCleanDriverData (
1777 IN ISCSI_DRIVER_DATA *Private
1778 )
1779 {
1780 EFI_STATUS Status;
1781
1782 Status = EFI_SUCCESS;
1783
1784 if (Private->DevicePath != NULL) {
1785 Status = gBS->UninstallProtocolInterface (
1786 Private->ExtScsiPassThruHandle,
1787 &gEfiDevicePathProtocolGuid,
1788 Private->DevicePath
1789 );
1790 if (EFI_ERROR (Status)) {
1791 goto EXIT;
1792 }
1793
1794 FreePool (Private->DevicePath);
1795 }
1796
1797 if (Private->ExtScsiPassThruHandle != NULL) {
1798 Status = gBS->UninstallProtocolInterface (
1799 Private->ExtScsiPassThruHandle,
1800 &gEfiExtScsiPassThruProtocolGuid,
1801 &Private->IScsiExtScsiPassThru
1802 );
1803 if (!EFI_ERROR (Status)) {
1804 mPrivate->OneSessionEstablished = FALSE;
1805 }
1806 }
1807
1808 EXIT:
1809 if (Private->ExitBootServiceEvent != NULL) {
1810 gBS->CloseEvent (Private->ExitBootServiceEvent);
1811 }
1812
1813 mCallbackInfo->Current = NULL;
1814
1815 FreePool (Private);
1816 return Status;
1817 }
1818
1819 /**
1820 Check wheather the Controller handle is configured to use DHCP protocol.
1821
1822 @param[in] Controller The handle of the controller.
1823 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
1824
1825 @retval TRUE The handle of the controller need the Dhcp protocol.
1826 @retval FALSE The handle of the controller does not need the Dhcp protocol.
1827
1828 **/
1829 BOOLEAN
1830 IScsiDhcpIsConfigured (
1831 IN EFI_HANDLE Controller,
1832 IN UINT8 IpVersion
1833 )
1834 {
1835 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
1836 UINT8 *AttemptConfigOrder;
1837 UINTN AttemptConfigOrderSize;
1838 UINTN Index;
1839 EFI_STATUS Status;
1840 EFI_MAC_ADDRESS MacAddr;
1841 UINTN HwAddressSize;
1842 UINT16 VlanId;
1843 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
1844 CHAR16 AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];
1845 CHAR16 AttemptName[ISCSI_NAME_IFR_MAX_SIZE];
1846
1847 AttemptConfigOrder = IScsiGetVariableAndSize (
1848 L"AttemptOrder",
1849 &gIScsiConfigGuid,
1850 &AttemptConfigOrderSize
1851 );
1852 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
1853 return FALSE;
1854 }
1855
1856 //
1857 // Get MAC address of this network device.
1858 //
1859 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
1860 if(EFI_ERROR (Status)) {
1861 return FALSE;
1862 }
1863 //
1864 // Get VLAN ID of this network device.
1865 //
1866 VlanId = NetLibGetVlanId (Controller);
1867 IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);
1868
1869 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1870 UnicodeSPrint (
1871 AttemptName,
1872 (UINTN) 128,
1873 L"Attempt %d",
1874 (UINTN) AttemptConfigOrder[Index]
1875 );
1876 Status = GetVariable2 (
1877 AttemptName,
1878 &gEfiIScsiInitiatorNameProtocolGuid,
1879 (VOID**)&AttemptTmp,
1880 NULL
1881 );
1882 if(AttemptTmp == NULL || EFI_ERROR (Status)) {
1883 continue;
1884 }
1885
1886 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);
1887
1888 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {
1889 FreePool (AttemptTmp);
1890 continue;
1891 }
1892
1893 if (AttemptTmp->SessionConfigData.IpMode != IP_MODE_AUTOCONFIG &&
1894 AttemptTmp->SessionConfigData.IpMode != ((IpVersion == IP_VERSION_4) ? IP_MODE_IP4 : IP_MODE_IP6)) {
1895 FreePool (AttemptTmp);
1896 continue;
1897 }
1898
1899 AsciiStrToUnicodeStrS (AttemptTmp->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));
1900
1901 if (AttemptTmp->Actived == ISCSI_ACTIVE_DISABLED || StrCmp (MacString, AttemptMacString)) {
1902 continue;
1903 }
1904
1905 if(AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG ||
1906 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp == TRUE ||
1907 AttemptTmp->SessionConfigData.TargetInfoFromDhcp == TRUE) {
1908 FreePool (AttemptTmp);
1909 FreePool (AttemptConfigOrder);
1910 return TRUE;
1911 }
1912
1913 FreePool (AttemptTmp);
1914 }
1915
1916 FreePool (AttemptConfigOrder);
1917 return FALSE;
1918 }
1919
1920 /**
1921 Check whether the Controller handle is configured to use DNS protocol.
1922
1923 @param[in] Controller The handle of the controller.
1924
1925 @retval TRUE The handle of the controller need the Dns protocol.
1926 @retval FALSE The handle of the controller does not need the Dns protocol.
1927
1928 **/
1929 BOOLEAN
1930 IScsiDnsIsConfigured (
1931 IN EFI_HANDLE Controller
1932 )
1933 {
1934 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
1935 UINT8 *AttemptConfigOrder;
1936 UINTN AttemptConfigOrderSize;
1937 UINTN Index;
1938 EFI_STATUS Status;
1939 EFI_MAC_ADDRESS MacAddr;
1940 UINTN HwAddressSize;
1941 UINT16 VlanId;
1942 CHAR16 AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];
1943 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
1944 CHAR16 AttemptName[ISCSI_NAME_IFR_MAX_SIZE];
1945
1946 AttemptConfigOrder = IScsiGetVariableAndSize (
1947 L"AttemptOrder",
1948 &gIScsiConfigGuid,
1949 &AttemptConfigOrderSize
1950 );
1951 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
1952 return FALSE;
1953 }
1954
1955 //
1956 // Get MAC address of this network device.
1957 //
1958 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
1959 if(EFI_ERROR (Status)) {
1960 return FALSE;
1961 }
1962 //
1963 // Get VLAN ID of this network device.
1964 //
1965 VlanId = NetLibGetVlanId (Controller);
1966 IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);
1967
1968 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1969 UnicodeSPrint (
1970 AttemptName,
1971 (UINTN) 128,
1972 L"Attempt %d",
1973 (UINTN) AttemptConfigOrder[Index]
1974 );
1975
1976 Status = GetVariable2 (
1977 AttemptName,
1978 &gEfiIScsiInitiatorNameProtocolGuid,
1979 (VOID**)&AttemptTmp,
1980 NULL
1981 );
1982 if(AttemptTmp == NULL || EFI_ERROR (Status)) {
1983 continue;
1984 }
1985
1986 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);
1987
1988 AsciiStrToUnicodeStrS (AttemptTmp->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));
1989
1990 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED || StrCmp (MacString, AttemptMacString)) {
1991 FreePool (AttemptTmp);
1992 continue;
1993 }
1994
1995 if (AttemptTmp->SessionConfigData.DnsMode || AttemptTmp->SessionConfigData.TargetInfoFromDhcp) {
1996 FreePool (AttemptTmp);
1997 FreePool (AttemptConfigOrder);
1998 return TRUE;
1999 } else {
2000 FreePool (AttemptTmp);
2001 continue;
2002 }
2003
2004 }
2005
2006 FreePool (AttemptConfigOrder);
2007 return FALSE;
2008
2009 }
2010
2011 /**
2012 Get the various configuration data.
2013
2014 @param[in] Private The iSCSI driver data.
2015
2016 @retval EFI_SUCCESS The configuration data is retrieved.
2017 @retval EFI_NOT_FOUND This iSCSI driver is not configured yet.
2018 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2019
2020 **/
2021 EFI_STATUS
2022 IScsiGetConfigData (
2023 IN ISCSI_DRIVER_DATA *Private
2024 )
2025 {
2026 EFI_STATUS Status;
2027 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
2028 CHAR16 AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];
2029 UINTN Index;
2030 ISCSI_NIC_INFO *NicInfo;
2031 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
2032 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
2033 UINT8 *AttemptConfigOrder;
2034 UINTN AttemptConfigOrderSize;
2035 CHAR16 IScsiMode[64];
2036 CHAR16 IpMode[64];
2037
2038 //
2039 // There should be at least one attempt configured.
2040 //
2041 AttemptConfigOrder = IScsiGetVariableAndSize (
2042 L"AttemptOrder",
2043 &gIScsiConfigGuid,
2044 &AttemptConfigOrderSize
2045 );
2046 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
2047 return EFI_NOT_FOUND;
2048 }
2049
2050 //
2051 // Get the iSCSI Initiator Name.
2052 //
2053 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
2054 Status = gIScsiInitiatorName.Get (
2055 &gIScsiInitiatorName,
2056 &mPrivate->InitiatorNameLength,
2057 mPrivate->InitiatorName
2058 );
2059 if (EFI_ERROR (Status)) {
2060 return Status;
2061 }
2062
2063 //
2064 // Get the normal configuration.
2065 //
2066 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
2067
2068 //
2069 // Check whether the attempt exists in AttemptConfig.
2070 //
2071 AttemptTmp = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);
2072 if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {
2073 continue;
2074 } else if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled != ISCSI_DISABLED) {
2075 //
2076 // Check the autoconfig path to see whether it should be retried.
2077 //
2078 if (AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&
2079 !AttemptTmp->AutoConfigureSuccess) {
2080 if (mPrivate->Ipv6Flag &&
2081 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6) {
2082 //
2083 // Autoconfigure for IP6 already attempted but failed. Do not try again.
2084 //
2085 continue;
2086 } else if (!mPrivate->Ipv6Flag &&
2087 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4) {
2088 //
2089 // Autoconfigure for IP4 already attempted but failed. Do not try again.
2090 //
2091 continue;
2092 } else {
2093 //
2094 // Try another approach for this autoconfigure path.
2095 //
2096 AttemptTmp->AutoConfigureMode =
2097 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);
2098 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp = TRUE;
2099 AttemptTmp->SessionConfigData.TargetInfoFromDhcp = TRUE;
2100 AttemptTmp->DhcpSuccess = FALSE;
2101
2102 //
2103 // Get some information from the dhcp server.
2104 //
2105 if (!mPrivate->Ipv6Flag) {
2106 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);
2107 if (!EFI_ERROR (Status)) {
2108 AttemptTmp->DhcpSuccess = TRUE;
2109 }
2110 } else {
2111 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);
2112 if (!EFI_ERROR (Status)) {
2113 AttemptTmp->DhcpSuccess = TRUE;
2114 }
2115 }
2116
2117 //
2118 // Refresh the state of this attempt to NVR.
2119 //
2120 UnicodeSPrint (
2121 mPrivate->PortString,
2122 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2123 L"Attempt %d",
2124 (UINTN) AttemptTmp->AttemptConfigIndex
2125 );
2126
2127 gRT->SetVariable (
2128 mPrivate->PortString,
2129 &gEfiIScsiInitiatorNameProtocolGuid,
2130 ISCSI_CONFIG_VAR_ATTR,
2131 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
2132 AttemptTmp
2133 );
2134
2135 continue;
2136 }
2137 } else if (AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp &&
2138 !AttemptTmp->ValidPath &&
2139 AttemptTmp->NicIndex == mPrivate->CurrentNic) {
2140 //
2141 // If the attempt associates with the current NIC, we can
2142 // get DHCP information for already added, but failed, attempt.
2143 //
2144 AttemptTmp->DhcpSuccess = FALSE;
2145 if (!mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP4)) {
2146 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);
2147 if (!EFI_ERROR (Status)) {
2148 AttemptTmp->DhcpSuccess = TRUE;
2149 }
2150 } else if (mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP6)) {
2151 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);
2152 if (!EFI_ERROR (Status)) {
2153 AttemptTmp->DhcpSuccess = TRUE;
2154 }
2155 }
2156
2157 //
2158 // Refresh the state of this attempt to NVR.
2159 //
2160 UnicodeSPrint (
2161 mPrivate->PortString,
2162 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2163 L"Attempt %d",
2164 (UINTN) AttemptTmp->AttemptConfigIndex
2165 );
2166
2167 gRT->SetVariable (
2168 mPrivate->PortString,
2169 &gEfiIScsiInitiatorNameProtocolGuid,
2170 ISCSI_CONFIG_VAR_ATTR,
2171 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
2172 AttemptTmp
2173 );
2174
2175 continue;
2176
2177 } else {
2178 continue;
2179 }
2180 }
2181
2182 //
2183 // This attempt does not exist in AttemptConfig. Try to add a new one.
2184 //
2185
2186 NicInfo = IScsiGetNicInfoByIndex (mPrivate->CurrentNic);
2187 ASSERT (NicInfo != NULL);
2188 IScsiMacAddrToStr (&NicInfo->PermanentAddress, NicInfo->HwAddressSize, NicInfo->VlanId, MacString);
2189 UnicodeSPrint (
2190 mPrivate->PortString,
2191 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2192 L"Attempt %d",
2193 (UINTN) AttemptConfigOrder[Index]
2194 );
2195
2196 GetVariable2 (
2197 mPrivate->PortString,
2198 &gEfiIScsiInitiatorNameProtocolGuid,
2199 (VOID**)&AttemptConfigData,
2200 NULL
2201 );
2202 AsciiStrToUnicodeStrS (AttemptConfigData->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));
2203
2204 if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_DISABLED ||
2205 StrCmp (MacString, AttemptMacString)) {
2206 continue;
2207 }
2208
2209 ASSERT (AttemptConfigOrder[Index] == AttemptConfigData->AttemptConfigIndex);
2210
2211 AttemptConfigData->NicIndex = NicInfo->NicIndex;
2212 AttemptConfigData->DhcpSuccess = FALSE;
2213 AttemptConfigData->ValidiBFTPath = (BOOLEAN) (mPrivate->EnableMpio ? TRUE : FALSE);
2214 AttemptConfigData->ValidPath = FALSE;
2215
2216 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
2217 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp = TRUE;
2218 AttemptConfigData->SessionConfigData.TargetInfoFromDhcp = TRUE;
2219
2220 AttemptConfigData->AutoConfigureMode =
2221 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);
2222 AttemptConfigData->AutoConfigureSuccess = FALSE;
2223 }
2224
2225 //
2226 // Get some information from dhcp server.
2227 //
2228 if (AttemptConfigData->SessionConfigData.Enabled != ISCSI_DISABLED &&
2229 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp) {
2230
2231 if (!mPrivate->Ipv6Flag &&
2232 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4 ||
2233 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4)) {
2234 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptConfigData);
2235 if (!EFI_ERROR (Status)) {
2236 AttemptConfigData->DhcpSuccess = TRUE;
2237 }
2238 } else if (mPrivate->Ipv6Flag &&
2239 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6 ||
2240 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6)) {
2241 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptConfigData);
2242 if (!EFI_ERROR (Status)) {
2243 AttemptConfigData->DhcpSuccess = TRUE;
2244 }
2245 }
2246
2247 //
2248 // Refresh the state of this attempt to NVR.
2249 //
2250 UnicodeSPrint (
2251 mPrivate->PortString,
2252 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2253 L"Attempt %d",
2254 (UINTN) AttemptConfigData->AttemptConfigIndex
2255 );
2256
2257 gRT->SetVariable (
2258 mPrivate->PortString,
2259 &gEfiIScsiInitiatorNameProtocolGuid,
2260 ISCSI_CONFIG_VAR_ATTR,
2261 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
2262 AttemptConfigData
2263 );
2264 }
2265
2266 //
2267 // Update Attempt Help Info.
2268 //
2269
2270 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED) {
2271 UnicodeSPrint (IScsiMode, 64, L"Disabled");
2272 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
2273 UnicodeSPrint (IScsiMode, 64, L"Enabled");
2274 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
2275 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");
2276 }
2277
2278 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {
2279 UnicodeSPrint (IpMode, 64, L"IP4");
2280 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {
2281 UnicodeSPrint (IpMode, 64, L"IP6");
2282 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
2283 UnicodeSPrint (IpMode, 64, L"Autoconfigure");
2284 }
2285
2286 UnicodeSPrint (
2287 mPrivate->PortString,
2288 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2289 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
2290 MacString,
2291 NicInfo->BusNumber,
2292 NicInfo->DeviceNumber,
2293 NicInfo->FunctionNumber,
2294 IScsiMode,
2295 IpMode
2296 );
2297
2298 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (
2299 mCallbackInfo->RegisteredHandle,
2300 0,
2301 mPrivate->PortString,
2302 NULL
2303 );
2304 if (AttemptConfigData->AttemptTitleHelpToken == 0) {
2305 return EFI_OUT_OF_RESOURCES;
2306 }
2307
2308 //
2309 // Record the attempt in global link list.
2310 //
2311 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
2312 mPrivate->AttemptCount++;
2313
2314 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
2315 mPrivate->MpioCount++;
2316 mPrivate->EnableMpio = TRUE;
2317
2318 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB) {
2319 mPrivate->Krb5MpioCount++;
2320 }
2321 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
2322 mPrivate->SinglePathCount++;
2323 }
2324 }
2325
2326 //
2327 // Reorder the AttemptConfig by the configured order.
2328 //
2329 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
2330 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);
2331 if (AttemptConfigData == NULL) {
2332 continue;
2333 }
2334
2335 RemoveEntryList (&AttemptConfigData->Link);
2336 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
2337 }
2338
2339 //
2340 // Update the Main Form.
2341 //
2342 IScsiConfigUpdateAttempt ();
2343
2344 FreePool (AttemptConfigOrder);
2345
2346 //
2347 // There should be at least one attempt configuration.
2348 //
2349 if (!mPrivate->EnableMpio) {
2350 if (mPrivate->SinglePathCount == 0) {
2351 return EFI_NOT_FOUND;
2352 }
2353 mPrivate->ValidSinglePathCount = mPrivate->SinglePathCount;
2354 }
2355
2356 return EFI_SUCCESS;
2357 }
2358
2359
2360 /**
2361 Get the device path of the iSCSI tcp connection and update it.
2362
2363 @param Session The iSCSI session.
2364
2365 @return The updated device path.
2366 @retval NULL Other errors as indicated.
2367
2368 **/
2369 EFI_DEVICE_PATH_PROTOCOL *
2370 IScsiGetTcpConnDevicePath (
2371 IN ISCSI_SESSION *Session
2372 )
2373 {
2374 ISCSI_CONNECTION *Conn;
2375 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2376 EFI_STATUS Status;
2377 EFI_DEV_PATH *DPathNode;
2378 UINTN PathLen;
2379
2380 if (Session->State != SESSION_STATE_LOGGED_IN) {
2381 return NULL;
2382 }
2383
2384 Conn = NET_LIST_USER_STRUCT_S (
2385 Session->Conns.ForwardLink,
2386 ISCSI_CONNECTION,
2387 Link,
2388 ISCSI_CONNECTION_SIGNATURE
2389 );
2390
2391 Status = gBS->HandleProtocol (
2392 Conn->TcpIo.Handle,
2393 &gEfiDevicePathProtocolGuid,
2394 (VOID **) &DevicePath
2395 );
2396 if (EFI_ERROR (Status)) {
2397 return NULL;
2398 }
2399 //
2400 // Duplicate it.
2401 //
2402 DevicePath = DuplicateDevicePath (DevicePath);
2403 if (DevicePath == NULL) {
2404 return NULL;
2405 }
2406
2407 DPathNode = (EFI_DEV_PATH *) DevicePath;
2408
2409 while (!IsDevicePathEnd (&DPathNode->DevPath)) {
2410 if (DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) {
2411 if (!Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP) {
2412 DPathNode->Ipv4.LocalPort = 0;
2413
2414 DPathNode->Ipv4.StaticIpAddress =
2415 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);
2416
2417 //
2418 // Add a judgement here to support previous versions of IPv4_DEVICE_PATH.
2419 // In previous versions of IPv4_DEVICE_PATH, GatewayIpAddress and SubnetMask
2420 // do not exist.
2421 // In new version of IPv4_DEVICE_PATH, structcure length is 27.
2422 //
2423
2424 PathLen = DevicePathNodeLength (&DPathNode->Ipv4);
2425
2426 if (PathLen == IP4_NODE_LEN_NEW_VERSIONS) {
2427
2428 IP4_COPY_ADDRESS (
2429 &DPathNode->Ipv4.GatewayIpAddress,
2430 &Session->ConfigData->SessionConfigData.Gateway
2431 );
2432
2433 IP4_COPY_ADDRESS (
2434 &DPathNode->Ipv4.SubnetMask,
2435 &Session->ConfigData->SessionConfigData.SubnetMask
2436 );
2437 }
2438
2439 break;
2440 } else if (Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv6_DP) {
2441 DPathNode->Ipv6.LocalPort = 0;
2442
2443 //
2444 // Add a judgement here to support previous versions of IPv6_DEVICE_PATH.
2445 // In previous versions of IPv6_DEVICE_PATH, IpAddressOrigin, PrefixLength
2446 // and GatewayIpAddress do not exist.
2447 // In new version of IPv6_DEVICE_PATH, structure length is 60, while in
2448 // old versions, the length is 43.
2449 //
2450
2451 PathLen = DevicePathNodeLength (&DPathNode->Ipv6);
2452
2453 if (PathLen == IP6_NODE_LEN_NEW_VERSIONS ) {
2454
2455 DPathNode->Ipv6.IpAddressOrigin = 0;
2456 DPathNode->Ipv6.PrefixLength = IP6_PREFIX_LENGTH;
2457 ZeroMem (&DPathNode->Ipv6.GatewayIpAddress, sizeof (EFI_IPv6_ADDRESS));
2458 }
2459 else if (PathLen == IP6_NODE_LEN_OLD_VERSIONS) {
2460
2461 //
2462 // StaticIPAddress is a field in old versions of IPv6_DEVICE_PATH, while ignored in new
2463 // version. Set StaticIPAddress through its' offset in old IPv6_DEVICE_PATH.
2464 //
2465 *((UINT8 *)(&DPathNode->Ipv6) + IP6_OLD_IPADDRESS_OFFSET) =
2466 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);
2467 }
2468
2469 break;
2470 }
2471 }
2472
2473 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);
2474 }
2475
2476 return DevicePath;
2477 }
2478
2479
2480 /**
2481 Abort the session when the transition from BS to RT is initiated.
2482
2483 @param[in] Event The event signaled.
2484 @param[in] Context The iSCSI driver data.
2485
2486 **/
2487 VOID
2488 EFIAPI
2489 IScsiOnExitBootService (
2490 IN EFI_EVENT Event,
2491 IN VOID *Context
2492 )
2493 {
2494 ISCSI_DRIVER_DATA *Private;
2495
2496 Private = (ISCSI_DRIVER_DATA *) Context;
2497
2498 gBS->CloseEvent (Private->ExitBootServiceEvent);
2499 Private->ExitBootServiceEvent = NULL;
2500
2501 if (Private->Session != NULL) {
2502 IScsiSessionAbort (Private->Session);
2503 }
2504 }
2505
2506 /**
2507 Tests whether a controller handle is being managed by IScsi driver.
2508
2509 This function tests whether the driver specified by DriverBindingHandle is
2510 currently managing the controller specified by ControllerHandle. This test
2511 is performed by evaluating if the the protocol specified by ProtocolGuid is
2512 present on ControllerHandle and is was opened by DriverBindingHandle and Nic
2513 Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.
2514 If ProtocolGuid is NULL, then ASSERT().
2515
2516 @param ControllerHandle A handle for a controller to test.
2517 @param DriverBindingHandle Specifies the driver binding handle for the
2518 driver.
2519 @param ProtocolGuid Specifies the protocol that the driver specified
2520 by DriverBindingHandle opens in its Start()
2521 function.
2522
2523 @retval EFI_SUCCESS ControllerHandle is managed by the driver
2524 specified by DriverBindingHandle.
2525 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver
2526 specified by DriverBindingHandle.
2527
2528 **/
2529 EFI_STATUS
2530 EFIAPI
2531 IScsiTestManagedDevice (
2532 IN EFI_HANDLE ControllerHandle,
2533 IN EFI_HANDLE DriverBindingHandle,
2534 IN EFI_GUID *ProtocolGuid
2535 )
2536 {
2537 EFI_STATUS Status;
2538 VOID *ManagedInterface;
2539 EFI_HANDLE NicControllerHandle;
2540
2541 ASSERT (ProtocolGuid != NULL);
2542
2543 NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid);
2544 if (NicControllerHandle == NULL) {
2545 return EFI_UNSUPPORTED;
2546 }
2547
2548 Status = gBS->OpenProtocol (
2549 ControllerHandle,
2550 (EFI_GUID *) ProtocolGuid,
2551 &ManagedInterface,
2552 DriverBindingHandle,
2553 NicControllerHandle,
2554 EFI_OPEN_PROTOCOL_BY_DRIVER
2555 );
2556 if (!EFI_ERROR (Status)) {
2557 gBS->CloseProtocol (
2558 ControllerHandle,
2559 (EFI_GUID *) ProtocolGuid,
2560 DriverBindingHandle,
2561 NicControllerHandle
2562 );
2563 return EFI_UNSUPPORTED;
2564 }
2565
2566 if (Status != EFI_ALREADY_STARTED) {
2567 return EFI_UNSUPPORTED;
2568 }
2569
2570 return EFI_SUCCESS;
2571 }