VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/NetworkPkg/IScsiDxe/IScsiMisc.c

Last change on this file was 105670, checked in by vboxsync, 7 months ago

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette