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