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