]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IScsiDxe/IScsiMisc.c
Update network stack code to use StrnCpy instead of StrCpy.
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiMisc.c
1 /** @file
2 Miscellaneous routines for iSCSI driver.
3
4 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "IScsiImpl.h"
16
17 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 IScsiHexString[] = "0123456789ABCDEFabcdef";
18
19 /**
20 Removes (trims) specified leading and trailing characters from a string.
21
22 @param[in, out] Str Pointer to the null-terminated string to be trimmed.
23 On return, Str will hold the trimmed string.
24
25 @param[in] CharC Character will be trimmed from str.
26
27 **/
28 VOID
29 IScsiStrTrim (
30 IN OUT CHAR16 *Str,
31 IN CHAR16 CharC
32 )
33 {
34 CHAR16 *Pointer1;
35 CHAR16 *Pointer2;
36
37 if (*Str == 0) {
38 return ;
39 }
40
41 //
42 // Trim off the leading and trailing characters c
43 //
44 for (Pointer1 = Str; (*Pointer1 != 0) && (*Pointer1 == CharC); Pointer1++) {
45 ;
46 }
47
48 Pointer2 = Str;
49 if (Pointer2 == Pointer1) {
50 while (*Pointer1 != 0) {
51 Pointer2++;
52 Pointer1++;
53 }
54 } else {
55 while (*Pointer1 != 0) {
56 *Pointer2 = *Pointer1;
57 Pointer1++;
58 Pointer2++;
59 }
60 *Pointer2 = 0;
61 }
62
63
64 for (Pointer1 = Str + StrLen(Str) - 1; Pointer1 >= Str && *Pointer1 == CharC; Pointer1--) {
65 ;
66 }
67 if (Pointer1 != Str + StrLen(Str) - 1) {
68 *(Pointer1 + 1) = 0;
69 }
70 }
71
72 /**
73 Calculate the prefix length of the IPv4 subnet mask.
74
75 @param[in] SubnetMask The IPv4 subnet mask.
76
77 @return The prefix length of the subnet mask.
78 @retval 0 Other errors as indicated.
79
80 **/
81 UINT8
82 IScsiGetSubnetMaskPrefixLength (
83 IN EFI_IPv4_ADDRESS *SubnetMask
84 )
85 {
86 UINT8 Len;
87 UINT32 ReverseMask;
88
89 //
90 // The SubnetMask is in network byte order.
91 //
92 ReverseMask = (SubnetMask->Addr[0] << 24) | (SubnetMask->Addr[1] << 16) | (SubnetMask->Addr[2] << 8) | (SubnetMask->Addr[3]);
93
94 //
95 // Reverse it.
96 //
97 ReverseMask = ~ReverseMask;
98
99 if ((ReverseMask & (ReverseMask + 1)) != 0) {
100 return 0;
101 }
102
103 Len = 0;
104
105 while (ReverseMask != 0) {
106 ReverseMask = ReverseMask >> 1;
107 Len++;
108 }
109
110 return (UINT8) (32 - Len);
111 }
112
113
114 /**
115 Convert the hexadecimal encoded LUN string into the 64-bit LUN.
116
117 @param[in] Str The hexadecimal encoded LUN string.
118 @param[out] Lun Storage to return the 64-bit LUN.
119
120 @retval EFI_SUCCESS The 64-bit LUN is stored in Lun.
121 @retval EFI_INVALID_PARAMETER The string is malformatted.
122
123 **/
124 EFI_STATUS
125 IScsiAsciiStrToLun (
126 IN CHAR8 *Str,
127 OUT UINT8 *Lun
128 )
129 {
130 UINTN Index, IndexValue, IndexNum, SizeStr;
131 CHAR8 TemStr[2];
132 UINT8 TemValue;
133 UINT16 Value[4];
134
135 ZeroMem (Lun, 8);
136 ZeroMem (TemStr, 2);
137 ZeroMem ((UINT8 *) Value, sizeof (Value));
138 SizeStr = AsciiStrLen (Str);
139 IndexValue = 0;
140 IndexNum = 0;
141
142 for (Index = 0; Index < SizeStr; Index ++) {
143 TemStr[0] = Str[Index];
144 TemValue = (UINT8) AsciiStrHexToUint64 (TemStr);
145 if (TemValue == 0 && TemStr[0] != '0') {
146 if ((TemStr[0] != '-') || (IndexNum == 0)) {
147 //
148 // Invalid Lun Char.
149 //
150 return EFI_INVALID_PARAMETER;
151 }
152 }
153
154 if ((TemValue == 0) && (TemStr[0] == '-')) {
155 //
156 // Next Lun value.
157 //
158 if (++IndexValue >= 4) {
159 //
160 // Max 4 Lun value.
161 //
162 return EFI_INVALID_PARAMETER;
163 }
164 //
165 // Restart str index for the next lun value.
166 //
167 IndexNum = 0;
168 continue;
169 }
170
171 if (++IndexNum > 4) {
172 //
173 // Each Lun Str can't exceed size 4, because it will be as UINT16 value.
174 //
175 return EFI_INVALID_PARAMETER;
176 }
177
178 //
179 // Combine UINT16 value.
180 //
181 Value[IndexValue] = (UINT16) ((Value[IndexValue] << 4) + TemValue);
182 }
183
184 for (Index = 0; Index <= IndexValue; Index ++) {
185 *((UINT16 *) &Lun[Index * 2]) = HTONS (Value[Index]);
186 }
187
188 return EFI_SUCCESS;
189 }
190
191 /**
192 Convert the 64-bit LUN into the hexadecimal encoded LUN string.
193
194 @param[in] Lun The 64-bit LUN.
195 @param[out] Str The storage to return the hexadecimal encoded LUN string.
196
197 **/
198 VOID
199 IScsiLunToUnicodeStr (
200 IN UINT8 *Lun,
201 OUT CHAR16 *Str
202 )
203 {
204 UINTN Index;
205 CHAR16 *TempStr;
206
207 TempStr = Str;
208
209 for (Index = 0; Index < 4; Index++) {
210
211 if ((Lun[2 * Index] | Lun[2 * Index + 1]) == 0) {
212 StrnCpy (TempStr, L"0-", StrLen (L"0-"));
213 } else {
214 TempStr[0] = (CHAR16) IScsiHexString[Lun[2 * Index] >> 4];
215 TempStr[1] = (CHAR16) IScsiHexString[Lun[2 * Index] & 0x0F];
216 TempStr[2] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] >> 4];
217 TempStr[3] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] & 0x0F];
218 TempStr[4] = L'-';
219 TempStr[5] = 0;
220
221 IScsiStrTrim (TempStr, L'0');
222 }
223
224 TempStr += StrLen (TempStr);
225 }
226
227 Str[StrLen (Str) - 1] = 0;
228
229 for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) {
230 if ((Str[Index] == L'0') && (Str[Index - 1] == L'-')) {
231 Str[Index - 1] = 0;
232 } else {
233 break;
234 }
235 }
236 }
237
238 /**
239 Convert the formatted IP address into the binary IP address.
240
241 @param[in] Str The UNICODE string.
242 @param[in] IpMode Indicates whether the IP address is v4 or v6.
243 @param[out] Ip The storage to return the ASCII string.
244
245 @retval EFI_SUCCESS The binary IP address is returned in Ip.
246 @retval EFI_INVALID_PARAMETER The IP string is malformatted or IpMode is
247 invalid.
248
249 **/
250 EFI_STATUS
251 IScsiAsciiStrToIp (
252 IN CHAR8 *Str,
253 IN UINT8 IpMode,
254 OUT EFI_IP_ADDRESS *Ip
255 )
256 {
257 EFI_STATUS Status;
258
259 if (IpMode == IP_MODE_IP4 || IpMode == IP_MODE_AUTOCONFIG_IP4) {
260 return NetLibAsciiStrToIp4 (Str, &Ip->v4);
261
262 } else if (IpMode == IP_MODE_IP6 || IpMode == IP_MODE_AUTOCONFIG_IP6) {
263 return NetLibAsciiStrToIp6 (Str, &Ip->v6);
264
265 } else if (IpMode == IP_MODE_AUTOCONFIG) {
266 Status = NetLibAsciiStrToIp4 (Str, &Ip->v4);
267 if (!EFI_ERROR (Status)) {
268 return Status;
269 }
270 return NetLibAsciiStrToIp6 (Str, &Ip->v6);
271
272 }
273
274 return EFI_INVALID_PARAMETER;
275 }
276
277 /**
278 Convert the mac address into a hexadecimal encoded "-" seperated string.
279
280 @param[in] Mac The mac address.
281 @param[in] Len Length in bytes of the mac address.
282 @param[in] VlanId VLAN ID of the network device.
283 @param[out] Str The storage to return the mac string.
284
285 **/
286 VOID
287 IScsiMacAddrToStr (
288 IN EFI_MAC_ADDRESS *Mac,
289 IN UINT32 Len,
290 IN UINT16 VlanId,
291 OUT CHAR16 *Str
292 )
293 {
294 UINT32 Index;
295 CHAR16 *String;
296
297 for (Index = 0; Index < Len; Index++) {
298 Str[3 * Index] = (CHAR16) IScsiHexString[(Mac->Addr[Index] >> 4) & 0x0F];
299 Str[3 * Index + 1] = (CHAR16) IScsiHexString[Mac->Addr[Index] & 0x0F];
300 Str[3 * Index + 2] = L':';
301 }
302
303 String = &Str[3 * Index - 1] ;
304 if (VlanId != 0) {
305 String += UnicodeSPrint (String, 6 * sizeof (CHAR16), L"\\%04x", (UINTN) VlanId);
306 }
307
308 *String = L'\0';
309 }
310
311 /**
312 Convert the binary encoded buffer into a hexadecimal encoded string.
313
314 @param[in] BinBuffer The buffer containing the binary data.
315 @param[in] BinLength Length of the binary buffer.
316 @param[in, out] HexStr Pointer to the string.
317 @param[in, out] HexLength The length of the string.
318
319 @retval EFI_SUCCESS The binary data is converted to the hexadecimal string
320 and the length of the string is updated.
321 @retval EFI_BUFFER_TOO_SMALL The string is too small.
322 @retval EFI_INVALID_PARAMETER The IP string is malformatted.
323
324 **/
325 EFI_STATUS
326 IScsiBinToHex (
327 IN UINT8 *BinBuffer,
328 IN UINT32 BinLength,
329 IN OUT CHAR8 *HexStr,
330 IN OUT UINT32 *HexLength
331 )
332 {
333 UINTN Index;
334
335 if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {
336 return EFI_INVALID_PARAMETER;
337 }
338
339 if (((*HexLength) - 3) < BinLength * 2) {
340 *HexLength = BinLength * 2 + 3;
341 return EFI_BUFFER_TOO_SMALL;
342 }
343
344 *HexLength = BinLength * 2 + 3;
345 //
346 // Prefix for Hex String.
347 //
348 HexStr[0] = '0';
349 HexStr[1] = 'x';
350
351 for (Index = 0; Index < BinLength; Index++) {
352 HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4];
353 HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0xf];
354 }
355
356 HexStr[Index * 2 + 2] = '\0';
357
358 return EFI_SUCCESS;
359 }
360
361
362 /**
363 Convert the hexadecimal string into a binary encoded buffer.
364
365 @param[in, out] BinBuffer The binary buffer.
366 @param[in, out] BinLength Length of the binary buffer.
367 @param[in] HexStr The hexadecimal string.
368
369 @retval EFI_SUCCESS The hexadecimal string is converted into a binary
370 encoded buffer.
371 @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.
372
373 **/
374 EFI_STATUS
375 IScsiHexToBin (
376 IN OUT UINT8 *BinBuffer,
377 IN OUT UINT32 *BinLength,
378 IN CHAR8 *HexStr
379 )
380 {
381 UINTN Index;
382 UINTN Length;
383 UINT8 Digit;
384 CHAR8 TemStr[2];
385
386 ZeroMem (TemStr, sizeof (TemStr));
387
388 //
389 // Find out how many hex characters the string has.
390 //
391 if ((HexStr[0] == '0') && ((HexStr[1] == 'x') || (HexStr[1] == 'X'))) {
392 HexStr += 2;
393 }
394
395 Length = AsciiStrLen (HexStr);
396
397 for (Index = 0; Index < Length; Index ++) {
398 TemStr[0] = HexStr[Index];
399 Digit = (UINT8) AsciiStrHexToUint64 (TemStr);
400 if (Digit == 0 && TemStr[0] != '0') {
401 //
402 // Invalid Lun Char.
403 //
404 break;
405 }
406 if ((Index & 1) == 0) {
407 BinBuffer [Index/2] = Digit;
408 } else {
409 BinBuffer [Index/2] = (UINT8) ((BinBuffer [Index/2] << 4) + Digit);
410 }
411 }
412
413 *BinLength = (UINT32) ((Index + 1)/2);
414
415 return EFI_SUCCESS;
416 }
417
418
419 /**
420 Convert the decimal-constant string or hex-constant string into a numerical value.
421
422 @param[in] Str String in decimal or hex.
423
424 @return The numerical value.
425
426 **/
427 UINTN
428 IScsiNetNtoi (
429 IN CHAR8 *Str
430 )
431 {
432 if ((Str[0] == '0') && ((Str[1] == 'x') || (Str[1] == 'X'))) {
433 Str += 2;
434
435 return AsciiStrHexToUintn (Str);
436 }
437
438 return AsciiStrDecimalToUintn (Str);
439 }
440
441
442 /**
443 Generate random numbers.
444
445 @param[in, out] Rand The buffer to contain random numbers.
446 @param[in] RandLength The length of the Rand buffer.
447
448 **/
449 VOID
450 IScsiGenRandom (
451 IN OUT UINT8 *Rand,
452 IN UINTN RandLength
453 )
454 {
455 UINT32 Random;
456
457 while (RandLength > 0) {
458 Random = NET_RANDOM (NetRandomInitSeed ());
459 *Rand++ = (UINT8) (Random);
460 RandLength--;
461 }
462 }
463
464
465 /**
466 Record the NIC info in global structure.
467
468 @param[in] Controller The handle of the controller.
469
470 @retval EFI_SUCCESS The operation is completed.
471 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resources to finish this
472 operation.
473
474 **/
475 EFI_STATUS
476 IScsiAddNic (
477 IN EFI_HANDLE Controller
478 )
479 {
480 EFI_STATUS Status;
481 ISCSI_NIC_INFO *NicInfo;
482 LIST_ENTRY *Entry;
483 EFI_MAC_ADDRESS MacAddr;
484 UINTN HwAddressSize;
485 UINT16 VlanId;
486
487 //
488 // Get MAC address of this network device.
489 //
490 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
491 if (EFI_ERROR (Status)) {
492 return Status;
493 }
494
495 //
496 // Get VLAN ID of this network device.
497 //
498 VlanId = NetLibGetVlanId (Controller);
499
500 //
501 // Check whether the NIC info already exists. Return directly if so.
502 //
503 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
504 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
505 if (NicInfo->HwAddressSize == HwAddressSize &&
506 CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&
507 NicInfo->VlanId == VlanId) {
508 mPrivate->CurrentNic = NicInfo->NicIndex;
509 return EFI_SUCCESS;
510 }
511
512 if (mPrivate->MaxNic < NicInfo->NicIndex) {
513 mPrivate->MaxNic = NicInfo->NicIndex;
514 }
515 }
516
517 //
518 // Record the NIC info in private structure.
519 //
520 NicInfo = AllocateZeroPool (sizeof (ISCSI_NIC_INFO));
521 if (NicInfo == NULL) {
522 return EFI_OUT_OF_RESOURCES;
523 }
524
525 CopyMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize);
526 NicInfo->HwAddressSize = (UINT32) HwAddressSize;
527 NicInfo->VlanId = VlanId;
528 NicInfo->NicIndex = (UINT8) (mPrivate->MaxNic + 1);
529 mPrivate->MaxNic = NicInfo->NicIndex;
530
531 //
532 // Get the PCI location.
533 //
534 IScsiGetNICPciLocation (
535 Controller,
536 &NicInfo->BusNumber,
537 &NicInfo->DeviceNumber,
538 &NicInfo->FunctionNumber
539 );
540
541 InsertTailList (&mPrivate->NicInfoList, &NicInfo->Link);
542 mPrivate->NicCount++;
543
544 mPrivate->CurrentNic = NicInfo->NicIndex;
545 return EFI_SUCCESS;
546 }
547
548
549 /**
550 Delete the recorded NIC info from global structure. Also delete corresponding
551 attempts.
552
553 @param[in] Controller The handle of the controller.
554
555 @retval EFI_SUCCESS The operation is completed.
556 @retval EFI_NOT_FOUND The NIC info to be deleted is not recorded.
557
558 **/
559 EFI_STATUS
560 IScsiRemoveNic (
561 IN EFI_HANDLE Controller
562 )
563 {
564 EFI_STATUS Status;
565 ISCSI_NIC_INFO *NicInfo;
566 LIST_ENTRY *Entry;
567 LIST_ENTRY *NextEntry;
568 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
569 ISCSI_NIC_INFO *ThisNic;
570 EFI_MAC_ADDRESS MacAddr;
571 UINTN HwAddressSize;
572 UINT16 VlanId;
573
574 //
575 // Get MAC address of this network device.
576 //
577 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
578 if (EFI_ERROR (Status)) {
579 return Status;
580 }
581
582 //
583 // Get VLAN ID of this network device.
584 //
585 VlanId = NetLibGetVlanId (Controller);
586
587 //
588 // Check whether the NIC information exists.
589 //
590 ThisNic = NULL;
591
592 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
593 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
594 if (NicInfo->HwAddressSize == HwAddressSize &&
595 CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&
596 NicInfo->VlanId == VlanId) {
597
598 ThisNic = NicInfo;
599 break;
600 }
601 }
602
603 if (ThisNic == NULL) {
604 return EFI_NOT_FOUND;
605 }
606
607 mPrivate->CurrentNic = ThisNic->NicIndex;
608
609 RemoveEntryList (&ThisNic->Link);
610 FreePool (ThisNic);
611 mPrivate->NicCount--;
612
613 //
614 // Remove all attempts related to this NIC.
615 //
616 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
617 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
618 if (AttemptConfigData->NicIndex == mPrivate->CurrentNic) {
619 RemoveEntryList (&AttemptConfigData->Link);
620 mPrivate->AttemptCount--;
621
622 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO && mPrivate->MpioCount > 0) {
623 if (--mPrivate->MpioCount == 0) {
624 mPrivate->EnableMpio = FALSE;
625 }
626
627 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB && mPrivate->Krb5MpioCount > 0) {
628 mPrivate->Krb5MpioCount--;
629 }
630
631 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED && mPrivate->SinglePathCount > 0) {
632 mPrivate->SinglePathCount--;
633
634 if (mPrivate->ValidSinglePathCount > 0) {
635 mPrivate->ValidSinglePathCount--;
636 }
637 }
638
639 FreePool (AttemptConfigData);
640 }
641 }
642
643 //
644 // Free attempt is created but not saved to system.
645 //
646 if (mPrivate->NewAttempt != NULL) {
647 FreePool (mPrivate->NewAttempt);
648 mPrivate->NewAttempt = NULL;
649 }
650
651 return EFI_SUCCESS;
652 }
653
654
655 /**
656 Get the recorded NIC info from global structure by the Index.
657
658 @param[in] NicIndex The index indicates the position of NIC info.
659
660 @return Pointer to the NIC info, or NULL if not found.
661
662 **/
663 ISCSI_NIC_INFO *
664 IScsiGetNicInfoByIndex (
665 IN UINT8 NicIndex
666 )
667 {
668 LIST_ENTRY *Entry;
669 ISCSI_NIC_INFO *NicInfo;
670
671 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
672 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
673 if (NicInfo->NicIndex == NicIndex) {
674 return NicInfo;
675 }
676 }
677
678 return NULL;
679 }
680
681
682 /**
683 Get the NIC's PCI location and return it accroding to the composited
684 format defined in iSCSI Boot Firmware Table.
685
686 @param[in] Controller The handle of the controller.
687 @param[out] Bus The bus number.
688 @param[out] Device The device number.
689 @param[out] Function The function number.
690
691 @return The composited representation of the NIC PCI location.
692
693 **/
694 UINT16
695 IScsiGetNICPciLocation (
696 IN EFI_HANDLE Controller,
697 OUT UINTN *Bus,
698 OUT UINTN *Device,
699 OUT UINTN *Function
700 )
701 {
702 EFI_STATUS Status;
703 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
704 EFI_HANDLE PciIoHandle;
705 EFI_PCI_IO_PROTOCOL *PciIo;
706 UINTN Segment;
707
708 Status = gBS->HandleProtocol (
709 Controller,
710 &gEfiDevicePathProtocolGuid,
711 (VOID **) &DevicePath
712 );
713 if (EFI_ERROR (Status)) {
714 return 0;
715 }
716
717 Status = gBS->LocateDevicePath (
718 &gEfiPciIoProtocolGuid,
719 &DevicePath,
720 &PciIoHandle
721 );
722 if (EFI_ERROR (Status)) {
723 return 0;
724 }
725
726 Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
727 if (EFI_ERROR (Status)) {
728 return 0;
729 }
730
731 Status = PciIo->GetLocation (PciIo, &Segment, Bus, Device, Function);
732 if (EFI_ERROR (Status)) {
733 return 0;
734 }
735
736 return (UINT16) ((*Bus << 8) | (*Device << 3) | *Function);
737 }
738
739
740 /**
741 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
742 buffer, and the size of the buffer. If failure, return NULL.
743
744 @param[in] Name String part of EFI variable name.
745 @param[in] VendorGuid GUID part of EFI variable name.
746 @param[out] VariableSize Returns the size of the EFI variable that was read.
747
748 @return Dynamically allocated memory that contains a copy of the EFI variable.
749 @return Caller is responsible freeing the buffer.
750 @retval NULL Variable was not read.
751
752 **/
753 VOID *
754 IScsiGetVariableAndSize (
755 IN CHAR16 *Name,
756 IN EFI_GUID *VendorGuid,
757 OUT UINTN *VariableSize
758 )
759 {
760 EFI_STATUS Status;
761 UINTN BufferSize;
762 VOID *Buffer;
763
764 Buffer = NULL;
765
766 //
767 // Pass in a zero size buffer to find the required buffer size.
768 //
769 BufferSize = 0;
770 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
771 if (Status == EFI_BUFFER_TOO_SMALL) {
772 //
773 // Allocate the buffer to return
774 //
775 Buffer = AllocateZeroPool (BufferSize);
776 if (Buffer == NULL) {
777 return NULL;
778 }
779 //
780 // Read variable into the allocated buffer.
781 //
782 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
783 if (EFI_ERROR (Status)) {
784 BufferSize = 0;
785 }
786 }
787
788 *VariableSize = BufferSize;
789 return Buffer;
790 }
791
792
793 /**
794 Create the iSCSI driver data.
795
796 @param[in] Image The handle of the driver image.
797 @param[in] Controller The handle of the controller.
798
799 @return The iSCSI driver data created.
800 @retval NULL Other errors as indicated.
801
802 **/
803 ISCSI_DRIVER_DATA *
804 IScsiCreateDriverData (
805 IN EFI_HANDLE Image,
806 IN EFI_HANDLE Controller
807 )
808 {
809 ISCSI_DRIVER_DATA *Private;
810 EFI_STATUS Status;
811
812 Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));
813 if (Private == NULL) {
814 return NULL;
815 }
816
817 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;
818 Private->Image = Image;
819 Private->Controller = Controller;
820 Private->Session = NULL;
821
822 //
823 // Create an event to be signaled when the BS to RT transition is triggerd so
824 // as to abort the iSCSI session.
825 //
826 Status = gBS->CreateEventEx (
827 EVT_NOTIFY_SIGNAL,
828 TPL_CALLBACK,
829 IScsiOnExitBootService,
830 Private,
831 &gEfiEventExitBootServicesGuid,
832 &Private->ExitBootServiceEvent
833 );
834 if (EFI_ERROR (Status)) {
835 FreePool (Private);
836 return NULL;
837 }
838
839 Private->ExtScsiPassThruHandle = NULL;
840 CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));
841
842 //
843 // 0 is designated to the TargetId, so use another value for the AdapterId.
844 //
845 Private->ExtScsiPassThruMode.AdapterId = 2;
846 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
847 Private->ExtScsiPassThruMode.IoAlign = 4;
848 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
849
850 return Private;
851 }
852
853
854 /**
855 Clean the iSCSI driver data.
856
857 @param[in] Private The iSCSI driver data.
858
859 **/
860 VOID
861 IScsiCleanDriverData (
862 IN ISCSI_DRIVER_DATA *Private
863 )
864 {
865 EFI_STATUS Status;
866
867 if (Private->DevicePath != NULL) {
868 gBS->UninstallProtocolInterface (
869 Private->ExtScsiPassThruHandle,
870 &gEfiDevicePathProtocolGuid,
871 Private->DevicePath
872 );
873
874 FreePool (Private->DevicePath);
875 }
876
877 if (Private->ExtScsiPassThruHandle != NULL) {
878 Status = gBS->UninstallProtocolInterface (
879 Private->ExtScsiPassThruHandle,
880 &gEfiExtScsiPassThruProtocolGuid,
881 &Private->IScsiExtScsiPassThru
882 );
883 if (!EFI_ERROR (Status)) {
884 mPrivate->OneSessionEstablished = FALSE;
885 }
886 }
887
888 gBS->CloseEvent (Private->ExitBootServiceEvent);
889
890 FreePool (Private);
891 }
892
893 /**
894 Check wheather the Controller handle is configured to use DHCP protocol.
895
896 @param[in] Controller The handle of the controller.
897 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
898
899 @retval TRUE The handle of the controller need the Dhcp protocol.
900 @retval FALSE The handle of the controller does not need the Dhcp protocol.
901
902 **/
903 BOOLEAN
904 IScsiDhcpIsConfigured (
905 IN EFI_HANDLE Controller,
906 IN UINT8 IpVersion
907 )
908 {
909 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
910 UINT8 *AttemptConfigOrder;
911 UINTN AttemptConfigOrderSize;
912 UINTN Index;
913 EFI_STATUS Status;
914 EFI_MAC_ADDRESS MacAddr;
915 UINTN HwAddressSize;
916 UINT16 VlanId;
917 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
918 CHAR16 AttemptName[ISCSI_NAME_IFR_MAX_SIZE];
919
920 AttemptConfigOrder = IScsiGetVariableAndSize (
921 L"AttemptOrder",
922 &gIScsiConfigGuid,
923 &AttemptConfigOrderSize
924 );
925 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
926 return FALSE;
927 }
928
929 //
930 // Get MAC address of this network device.
931 //
932 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
933 if(EFI_ERROR (Status)) {
934 return FALSE;
935 }
936 //
937 // Get VLAN ID of this network device.
938 //
939 VlanId = NetLibGetVlanId (Controller);
940 IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);
941
942 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
943 UnicodeSPrint (
944 AttemptName,
945 (UINTN) 128,
946 L"%s%d",
947 MacString,
948 (UINTN) AttemptConfigOrder[Index]
949 );
950 Status = GetVariable2 (
951 AttemptName,
952 &gEfiIScsiInitiatorNameProtocolGuid,
953 (VOID**)&AttemptTmp,
954 NULL
955 );
956 if(AttemptTmp == NULL || EFI_ERROR (Status)) {
957 continue;
958 }
959
960 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);
961
962 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {
963 FreePool (AttemptTmp);
964 continue;
965 }
966
967 if (AttemptTmp->SessionConfigData.IpMode != IP_MODE_AUTOCONFIG &&
968 AttemptTmp->SessionConfigData.IpMode != ((IpVersion == IP_VERSION_4) ? IP_MODE_IP4 : IP_MODE_IP6)) {
969 FreePool (AttemptTmp);
970 continue;
971 }
972
973 if(AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG ||
974 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp == TRUE ||
975 AttemptTmp->SessionConfigData.TargetInfoFromDhcp == TRUE) {
976 FreePool (AttemptTmp);
977 FreePool (AttemptConfigOrder);
978 return TRUE;
979 }
980
981 FreePool (AttemptTmp);
982 }
983
984 FreePool (AttemptConfigOrder);
985 return FALSE;
986 }
987
988 /**
989 Get the various configuration data.
990
991 @param[in] Private The iSCSI driver data.
992
993 @retval EFI_SUCCESS The configuration data is retrieved.
994 @retval EFI_NOT_FOUND This iSCSI driver is not configured yet.
995
996 **/
997 EFI_STATUS
998 IScsiGetConfigData (
999 IN ISCSI_DRIVER_DATA *Private
1000 )
1001 {
1002 EFI_STATUS Status;
1003 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
1004 UINTN Index;
1005 ISCSI_NIC_INFO *NicInfo;
1006 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
1007 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
1008 UINT8 *AttemptConfigOrder;
1009 UINTN AttemptConfigOrderSize;
1010 CHAR16 IScsiMode[64];
1011 CHAR16 IpMode[64];
1012
1013 //
1014 // There should be at least one attempt configured.
1015 //
1016 AttemptConfigOrder = IScsiGetVariableAndSize (
1017 L"AttemptOrder",
1018 &gIScsiConfigGuid,
1019 &AttemptConfigOrderSize
1020 );
1021 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
1022 return EFI_NOT_FOUND;
1023 }
1024
1025 //
1026 // Get the iSCSI Initiator Name.
1027 //
1028 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
1029 Status = gIScsiInitiatorName.Get (
1030 &gIScsiInitiatorName,
1031 &mPrivate->InitiatorNameLength,
1032 mPrivate->InitiatorName
1033 );
1034 if (EFI_ERROR (Status)) {
1035 return Status;
1036 }
1037
1038 //
1039 // Get the normal configuration.
1040 //
1041 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1042
1043 //
1044 // Check whether the attempt exists in AttemptConfig.
1045 //
1046 AttemptTmp = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);
1047 if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {
1048 continue;
1049 } else if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled != ISCSI_DISABLED) {
1050 //
1051 // Check the autoconfig path to see whether it should be retried.
1052 //
1053 if (AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&
1054 AttemptTmp->AutoConfigureMode != IP_MODE_AUTOCONFIG_SUCCESS) {
1055 if (mPrivate->Ipv6Flag &&
1056 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6) {
1057 //
1058 // Autoconfigure for IP6 already attempted but failed. Do not try again.
1059 //
1060 continue;
1061 } else if (!mPrivate->Ipv6Flag &&
1062 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4) {
1063 //
1064 // Autoconfigure for IP4 already attempted but failed. Do not try again.
1065 //
1066 continue;
1067 } else {
1068 //
1069 // Try another approach for this autoconfigure path.
1070 //
1071 AttemptTmp->AutoConfigureMode =
1072 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);
1073 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp = TRUE;
1074 AttemptTmp->SessionConfigData.TargetInfoFromDhcp = TRUE;
1075 AttemptTmp->DhcpSuccess = FALSE;
1076
1077 //
1078 // Get some information from the dhcp server.
1079 //
1080 if (!mPrivate->Ipv6Flag) {
1081 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);
1082 if (!EFI_ERROR (Status)) {
1083 AttemptTmp->DhcpSuccess = TRUE;
1084 }
1085 } else {
1086 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);
1087 if (!EFI_ERROR (Status)) {
1088 AttemptTmp->DhcpSuccess = TRUE;
1089 }
1090 }
1091
1092 //
1093 // Refresh the state of this attempt to NVR.
1094 //
1095 AsciiStrToUnicodeStr (AttemptTmp->MacString, MacString);
1096 UnicodeSPrint (
1097 mPrivate->PortString,
1098 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
1099 L"%s%d",
1100 MacString,
1101 (UINTN) AttemptTmp->AttemptConfigIndex
1102 );
1103
1104 gRT->SetVariable (
1105 mPrivate->PortString,
1106 &gEfiIScsiInitiatorNameProtocolGuid,
1107 ISCSI_CONFIG_VAR_ATTR,
1108 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
1109 AttemptTmp
1110 );
1111
1112 continue;
1113 }
1114 } else if (AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp && !AttemptTmp->ValidPath) {
1115 //
1116 // Get DHCP information for already added, but failed, attempt.
1117 //
1118 AttemptTmp->DhcpSuccess = FALSE;
1119 if (!mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP4)) {
1120 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);
1121 if (!EFI_ERROR (Status)) {
1122 AttemptTmp->DhcpSuccess = TRUE;
1123 }
1124 } else if (mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP6)) {
1125 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);
1126 if (!EFI_ERROR (Status)) {
1127 AttemptTmp->DhcpSuccess = TRUE;
1128 }
1129 }
1130
1131 //
1132 // Refresh the state of this attempt to NVR.
1133 //
1134 AsciiStrToUnicodeStr (AttemptTmp->MacString, MacString);
1135 UnicodeSPrint (
1136 mPrivate->PortString,
1137 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
1138 L"%s%d",
1139 MacString,
1140 (UINTN) AttemptTmp->AttemptConfigIndex
1141 );
1142
1143 gRT->SetVariable (
1144 mPrivate->PortString,
1145 &gEfiIScsiInitiatorNameProtocolGuid,
1146 ISCSI_CONFIG_VAR_ATTR,
1147 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
1148 AttemptTmp
1149 );
1150
1151 continue;
1152
1153 } else {
1154 continue;
1155 }
1156 }
1157
1158 //
1159 // This attempt does not exist in AttemptConfig. Try to add a new one.
1160 //
1161
1162 NicInfo = IScsiGetNicInfoByIndex (mPrivate->CurrentNic);
1163 ASSERT (NicInfo != NULL);
1164 IScsiMacAddrToStr (&NicInfo->PermanentAddress, NicInfo->HwAddressSize, NicInfo->VlanId, MacString);
1165 UnicodeSPrint (
1166 mPrivate->PortString,
1167 (UINTN) 128,
1168 L"%s%d",
1169 MacString,
1170 (UINTN) AttemptConfigOrder[Index]
1171 );
1172
1173 GetVariable2 (
1174 mPrivate->PortString,
1175 &gEfiIScsiInitiatorNameProtocolGuid,
1176 (VOID**)&AttemptConfigData,
1177 NULL
1178 );
1179
1180 if (AttemptConfigData == NULL) {
1181 continue;
1182 }
1183
1184 ASSERT (AttemptConfigOrder[Index] == AttemptConfigData->AttemptConfigIndex);
1185
1186 AttemptConfigData->NicIndex = NicInfo->NicIndex;
1187 AttemptConfigData->DhcpSuccess = FALSE;
1188 AttemptConfigData->ValidiBFTPath = (BOOLEAN) (mPrivate->EnableMpio ? TRUE : FALSE);
1189 AttemptConfigData->ValidPath = FALSE;
1190
1191 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
1192 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp = TRUE;
1193 AttemptConfigData->SessionConfigData.TargetInfoFromDhcp = TRUE;
1194
1195 AttemptConfigData->AutoConfigureMode =
1196 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);
1197 }
1198
1199 //
1200 // Get some information from dhcp server.
1201 //
1202 if (AttemptConfigData->SessionConfigData.Enabled != ISCSI_DISABLED &&
1203 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp) {
1204
1205 if (!mPrivate->Ipv6Flag &&
1206 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4 ||
1207 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4)) {
1208 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptConfigData);
1209 if (!EFI_ERROR (Status)) {
1210 AttemptConfigData->DhcpSuccess = TRUE;
1211 }
1212 } else if (mPrivate->Ipv6Flag &&
1213 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6 ||
1214 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6)) {
1215 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptConfigData);
1216 if (!EFI_ERROR (Status)) {
1217 AttemptConfigData->DhcpSuccess = TRUE;
1218 }
1219 }
1220
1221 //
1222 // Refresh the state of this attempt to NVR.
1223 //
1224 AsciiStrToUnicodeStr (AttemptConfigData->MacString, MacString);
1225 UnicodeSPrint (
1226 mPrivate->PortString,
1227 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
1228 L"%s%d",
1229 MacString,
1230 (UINTN) AttemptConfigData->AttemptConfigIndex
1231 );
1232
1233 gRT->SetVariable (
1234 mPrivate->PortString,
1235 &gEfiIScsiInitiatorNameProtocolGuid,
1236 ISCSI_CONFIG_VAR_ATTR,
1237 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
1238 AttemptConfigData
1239 );
1240 }
1241
1242 //
1243 // Update Attempt Help Info.
1244 //
1245
1246 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED) {
1247 UnicodeSPrint (IScsiMode, 64, L"Disabled");
1248 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
1249 UnicodeSPrint (IScsiMode, 64, L"Enabled");
1250 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
1251 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");
1252 }
1253
1254 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {
1255 UnicodeSPrint (IpMode, 64, L"IP4");
1256 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {
1257 UnicodeSPrint (IpMode, 64, L"IP6");
1258 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
1259 UnicodeSPrint (IpMode, 64, L"Autoconfigure");
1260 }
1261
1262 UnicodeSPrint (
1263 mPrivate->PortString,
1264 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
1265 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
1266 MacString,
1267 NicInfo->BusNumber,
1268 NicInfo->DeviceNumber,
1269 NicInfo->FunctionNumber,
1270 IScsiMode,
1271 IpMode
1272 );
1273
1274 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (
1275 mCallbackInfo->RegisteredHandle,
1276 0,
1277 mPrivate->PortString,
1278 NULL
1279 );
1280 ASSERT (AttemptConfigData->AttemptTitleHelpToken != 0);
1281
1282 //
1283 // Record the attempt in global link list.
1284 //
1285 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
1286 mPrivate->AttemptCount++;
1287
1288 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
1289 mPrivate->MpioCount++;
1290 mPrivate->EnableMpio = TRUE;
1291
1292 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB) {
1293 mPrivate->Krb5MpioCount++;
1294 }
1295 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
1296 mPrivate->SinglePathCount++;
1297 }
1298 }
1299
1300 //
1301 // Reorder the AttemptConfig by the configured order.
1302 //
1303 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1304 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);
1305 if (AttemptConfigData == NULL) {
1306 continue;
1307 }
1308
1309 RemoveEntryList (&AttemptConfigData->Link);
1310 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
1311 }
1312
1313 //
1314 // Update the Main Form.
1315 //
1316 IScsiConfigUpdateAttempt ();
1317
1318 FreePool (AttemptConfigOrder);
1319
1320 //
1321 // There should be at least one attempt configuration.
1322 //
1323 if (!mPrivate->EnableMpio) {
1324 if (mPrivate->SinglePathCount == 0) {
1325 return EFI_NOT_FOUND;
1326 }
1327 mPrivate->ValidSinglePathCount = mPrivate->SinglePathCount;
1328 }
1329
1330 return EFI_SUCCESS;
1331 }
1332
1333
1334 /**
1335 Get the device path of the iSCSI tcp connection and update it.
1336
1337 @param Session The iSCSI session.
1338
1339 @return The updated device path.
1340 @retval NULL Other errors as indicated.
1341
1342 **/
1343 EFI_DEVICE_PATH_PROTOCOL *
1344 IScsiGetTcpConnDevicePath (
1345 IN ISCSI_SESSION *Session
1346 )
1347 {
1348 ISCSI_CONNECTION *Conn;
1349 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1350 EFI_STATUS Status;
1351 EFI_DEV_PATH *DPathNode;
1352
1353 if (Session->State != SESSION_STATE_LOGGED_IN) {
1354 return NULL;
1355 }
1356
1357 Conn = NET_LIST_USER_STRUCT_S (
1358 Session->Conns.ForwardLink,
1359 ISCSI_CONNECTION,
1360 Link,
1361 ISCSI_CONNECTION_SIGNATURE
1362 );
1363
1364 Status = gBS->HandleProtocol (
1365 Conn->TcpIo.Handle,
1366 &gEfiDevicePathProtocolGuid,
1367 (VOID **) &DevicePath
1368 );
1369 if (EFI_ERROR (Status)) {
1370 return NULL;
1371 }
1372 //
1373 // Duplicate it.
1374 //
1375 DevicePath = DuplicateDevicePath (DevicePath);
1376 if (DevicePath == NULL) {
1377 return NULL;
1378 }
1379
1380 DPathNode = (EFI_DEV_PATH *) DevicePath;
1381
1382 while (!IsDevicePathEnd (&DPathNode->DevPath)) {
1383 if (DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) {
1384 if (!Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP) {
1385 DPathNode->Ipv4.LocalPort = 0;
1386
1387 DPathNode->Ipv4.StaticIpAddress =
1388 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);
1389
1390 IP4_COPY_ADDRESS (
1391 &DPathNode->Ipv4.GatewayIpAddress,
1392 &Session->ConfigData->SessionConfigData.Gateway
1393 );
1394
1395 IP4_COPY_ADDRESS (
1396 &DPathNode->Ipv4.SubnetMask,
1397 &Session->ConfigData->SessionConfigData.SubnetMask
1398 );
1399 break;
1400 } else if (Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv6_DP) {
1401 DPathNode->Ipv6.LocalPort = 0;
1402 DPathNode->Ipv6.IpAddressOrigin = 0;
1403 DPathNode->Ipv6.PrefixLength = IP6_PREFIX_LENGTH;
1404 ZeroMem (&DPathNode->Ipv6.GatewayIpAddress, sizeof (EFI_IPv6_ADDRESS));
1405 break;
1406 }
1407 }
1408
1409 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);
1410 }
1411
1412 return DevicePath;
1413 }
1414
1415
1416 /**
1417 Abort the session when the transition from BS to RT is initiated.
1418
1419 @param[in] Event The event signaled.
1420 @param[in] Context The iSCSI driver data.
1421
1422 **/
1423 VOID
1424 EFIAPI
1425 IScsiOnExitBootService (
1426 IN EFI_EVENT Event,
1427 IN VOID *Context
1428 )
1429 {
1430 ISCSI_DRIVER_DATA *Private;
1431
1432 Private = (ISCSI_DRIVER_DATA *) Context;
1433 gBS->CloseEvent (Private->ExitBootServiceEvent);
1434
1435 if (Private->Session != NULL) {
1436 IScsiSessionAbort (Private->Session);
1437 }
1438 }
1439
1440 /**
1441 Tests whether a controller handle is being managed by IScsi driver.
1442
1443 This function tests whether the driver specified by DriverBindingHandle is
1444 currently managing the controller specified by ControllerHandle. This test
1445 is performed by evaluating if the the protocol specified by ProtocolGuid is
1446 present on ControllerHandle and is was opened by DriverBindingHandle and Nic
1447 Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.
1448 If ProtocolGuid is NULL, then ASSERT().
1449
1450 @param ControllerHandle A handle for a controller to test.
1451 @param DriverBindingHandle Specifies the driver binding handle for the
1452 driver.
1453 @param ProtocolGuid Specifies the protocol that the driver specified
1454 by DriverBindingHandle opens in its Start()
1455 function.
1456
1457 @retval EFI_SUCCESS ControllerHandle is managed by the driver
1458 specified by DriverBindingHandle.
1459 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver
1460 specified by DriverBindingHandle.
1461
1462 **/
1463 EFI_STATUS
1464 EFIAPI
1465 IScsiTestManagedDevice (
1466 IN EFI_HANDLE ControllerHandle,
1467 IN EFI_HANDLE DriverBindingHandle,
1468 IN EFI_GUID *ProtocolGuid
1469 )
1470 {
1471 EFI_STATUS Status;
1472 VOID *ManagedInterface;
1473 EFI_HANDLE NicControllerHandle;
1474
1475 ASSERT (ProtocolGuid != NULL);
1476
1477 NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid);
1478 if (NicControllerHandle == NULL) {
1479 return EFI_UNSUPPORTED;
1480 }
1481
1482 Status = gBS->OpenProtocol (
1483 ControllerHandle,
1484 (EFI_GUID *) ProtocolGuid,
1485 &ManagedInterface,
1486 DriverBindingHandle,
1487 NicControllerHandle,
1488 EFI_OPEN_PROTOCOL_BY_DRIVER
1489 );
1490 if (!EFI_ERROR (Status)) {
1491 gBS->CloseProtocol (
1492 ControllerHandle,
1493 (EFI_GUID *) ProtocolGuid,
1494 DriverBindingHandle,
1495 NicControllerHandle
1496 );
1497 return EFI_UNSUPPORTED;
1498 }
1499
1500 if (Status != EFI_ALREADY_STARTED) {
1501 return EFI_UNSUPPORTED;
1502 }
1503
1504 return EFI_SUCCESS;
1505 }