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