IScsiMisc.c revision b7cc5bf180e9deefc91a5e66e0b80fd222503608
1/** @file 2 Miscellaneous routines for iSCSI driver. 3 4Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR> 5This program and the accompanying materials 6are licensed and made available under the terms and conditions of the BSD License 7which accompanies this distribution. The full text of the license may be found at 8http://opensource.org/licenses/bsd-license.php 9 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13**/ 14 15#include "IScsiImpl.h" 16 17GLOBAL_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**/ 28VOID 29IScsiStrTrim ( 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**/ 81UINT8 82IScsiGetSubnetMaskPrefixLength ( 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**/ 124EFI_STATUS 125IScsiAsciiStrToLun ( 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**/ 198VOID 199IScsiLunToUnicodeStr ( 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 StrCpy (TempStr, 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**/ 250EFI_STATUS 251IScsiAsciiStrToIp ( 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**/ 286VOID 287IScsiMacAddrToStr ( 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**/ 325EFI_STATUS 326IScsiBinToHex ( 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**/ 374EFI_STATUS 375IScsiHexToBin ( 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**/ 427UINTN 428IScsiNetNtoi ( 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**/ 449VOID 450IScsiGenRandom ( 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**/ 475EFI_STATUS 476IScsiAddNic ( 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**/ 559EFI_STATUS 560IScsiRemoveNic ( 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**/ 663ISCSI_NIC_INFO * 664IScsiGetNicInfoByIndex ( 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**/ 694UINT16 695IScsiGetNICPciLocation ( 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**/ 753VOID * 754IScsiGetVariableAndSize ( 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**/ 803ISCSI_DRIVER_DATA * 804IScsiCreateDriverData ( 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**/ 860VOID 861IScsiCleanDriverData ( 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**/ 903BOOLEAN 904IScsiDhcpIsConfigured ( 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(EFI_ERROR (Status)) { 957 continue; 958 } 959 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex); 960 961 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) { 962 FreePool (AttemptTmp); 963 continue; 964 } 965 966 if (AttemptTmp->SessionConfigData.IpMode != IP_MODE_AUTOCONFIG && 967 AttemptTmp->SessionConfigData.IpMode != ((IpVersion == IP_VERSION_4) ? IP_MODE_IP4 : IP_MODE_IP6)) { 968 FreePool (AttemptTmp); 969 continue; 970 } 971 972 if(AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG || 973 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp == TRUE || 974 AttemptTmp->SessionConfigData.TargetInfoFromDhcp == TRUE) { 975 FreePool (AttemptTmp); 976 FreePool (AttemptConfigOrder); 977 return TRUE; 978 } 979 980 FreePool (AttemptTmp); 981 } 982 983 FreePool (AttemptConfigOrder); 984 return FALSE; 985} 986 987/** 988 Get the various configuration data. 989 990 @param[in] Private The iSCSI driver data. 991 992 @retval EFI_SUCCESS The configuration data is retrieved. 993 @retval EFI_NOT_FOUND This iSCSI driver is not configured yet. 994 995**/ 996EFI_STATUS 997IScsiGetConfigData ( 998 IN ISCSI_DRIVER_DATA *Private 999 ) 1000{ 1001 EFI_STATUS Status; 1002 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN]; 1003 UINTN Index; 1004 ISCSI_NIC_INFO *NicInfo; 1005 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData; 1006 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp; 1007 UINT8 *AttemptConfigOrder; 1008 UINTN AttemptConfigOrderSize; 1009 CHAR16 IScsiMode[64]; 1010 CHAR16 IpMode[64]; 1011 1012 // 1013 // There should be at least one attempt configured. 1014 // 1015 AttemptConfigOrder = IScsiGetVariableAndSize ( 1016 L"AttemptOrder", 1017 &gIScsiConfigGuid, 1018 &AttemptConfigOrderSize 1019 ); 1020 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) { 1021 return EFI_NOT_FOUND; 1022 } 1023 1024 // 1025 // Get the iSCSI Initiator Name. 1026 // 1027 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE; 1028 Status = gIScsiInitiatorName.Get ( 1029 &gIScsiInitiatorName, 1030 &mPrivate->InitiatorNameLength, 1031 mPrivate->InitiatorName 1032 ); 1033 if (EFI_ERROR (Status)) { 1034 return Status; 1035 } 1036 1037 // 1038 // Get the normal configuration. 1039 // 1040 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) { 1041 1042 // 1043 // Check whether the attempt exists in AttemptConfig. 1044 // 1045 AttemptTmp = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]); 1046 if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) { 1047 continue; 1048 } else if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled != ISCSI_DISABLED) { 1049 // 1050 // Check the autoconfig path to see whether it should be retried. 1051 // 1052 if (AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG && 1053 AttemptTmp->AutoConfigureMode != IP_MODE_AUTOCONFIG_SUCCESS) { 1054 if (mPrivate->Ipv6Flag && 1055 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6) { 1056 // 1057 // Autoconfigure for IP6 already attempted but failed. Do not try again. 1058 // 1059 continue; 1060 } else if (!mPrivate->Ipv6Flag && 1061 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4) { 1062 // 1063 // Autoconfigure for IP4 already attempted but failed. Do not try again. 1064 // 1065 continue; 1066 } else { 1067 // 1068 // Try another approach for this autoconfigure path. 1069 // 1070 AttemptTmp->AutoConfigureMode = 1071 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4); 1072 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp = TRUE; 1073 AttemptTmp->SessionConfigData.TargetInfoFromDhcp = TRUE; 1074 AttemptTmp->DhcpSuccess = FALSE; 1075 1076 // 1077 // Get some information from the dhcp server. 1078 // 1079 if (!mPrivate->Ipv6Flag) { 1080 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp); 1081 if (!EFI_ERROR (Status)) { 1082 AttemptTmp->DhcpSuccess = TRUE; 1083 } 1084 } else { 1085 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp); 1086 if (!EFI_ERROR (Status)) { 1087 AttemptTmp->DhcpSuccess = TRUE; 1088 } 1089 } 1090 1091 // 1092 // Refresh the state of this attempt to NVR. 1093 // 1094 AsciiStrToUnicodeStr (AttemptTmp->MacString, MacString); 1095 UnicodeSPrint ( 1096 mPrivate->PortString, 1097 (UINTN) ISCSI_NAME_IFR_MAX_SIZE, 1098 L"%s%d", 1099 MacString, 1100 (UINTN) AttemptTmp->AttemptConfigIndex 1101 ); 1102 1103 gRT->SetVariable ( 1104 mPrivate->PortString, 1105 &gEfiIScsiInitiatorNameProtocolGuid, 1106 ISCSI_CONFIG_VAR_ATTR, 1107 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA), 1108 AttemptTmp 1109 ); 1110 1111 continue; 1112 } 1113 } else if (AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp && !AttemptTmp->ValidPath) { 1114 // 1115 // Get DHCP information for already added, but failed, attempt. 1116 // 1117 AttemptTmp->DhcpSuccess = FALSE; 1118 if (!mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP4)) { 1119 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp); 1120 if (!EFI_ERROR (Status)) { 1121 AttemptTmp->DhcpSuccess = TRUE; 1122 } 1123 } else if (mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP6)) { 1124 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp); 1125 if (!EFI_ERROR (Status)) { 1126 AttemptTmp->DhcpSuccess = TRUE; 1127 } 1128 } 1129 1130 // 1131 // Refresh the state of this attempt to NVR. 1132 // 1133 AsciiStrToUnicodeStr (AttemptTmp->MacString, MacString); 1134 UnicodeSPrint ( 1135 mPrivate->PortString, 1136 (UINTN) ISCSI_NAME_IFR_MAX_SIZE, 1137 L"%s%d", 1138 MacString, 1139 (UINTN) AttemptTmp->AttemptConfigIndex 1140 ); 1141 1142 gRT->SetVariable ( 1143 mPrivate->PortString, 1144 &gEfiIScsiInitiatorNameProtocolGuid, 1145 ISCSI_CONFIG_VAR_ATTR, 1146 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA), 1147 AttemptTmp 1148 ); 1149 1150 continue; 1151 1152 } else { 1153 continue; 1154 } 1155 } 1156 1157 // 1158 // This attempt does not exist in AttemptConfig. Try to add a new one. 1159 // 1160 1161 NicInfo = IScsiGetNicInfoByIndex (mPrivate->CurrentNic); 1162 ASSERT (NicInfo != NULL); 1163 IScsiMacAddrToStr (&NicInfo->PermanentAddress, NicInfo->HwAddressSize, NicInfo->VlanId, MacString); 1164 UnicodeSPrint ( 1165 mPrivate->PortString, 1166 (UINTN) 128, 1167 L"%s%d", 1168 MacString, 1169 (UINTN) AttemptConfigOrder[Index] 1170 ); 1171 1172 GetVariable2 ( 1173 mPrivate->PortString, 1174 &gEfiIScsiInitiatorNameProtocolGuid, 1175 (VOID**)&AttemptConfigData, 1176 NULL 1177 ); 1178 1179 if (AttemptConfigData == NULL) { 1180 continue; 1181 } 1182 1183 ASSERT (AttemptConfigOrder[Index] == AttemptConfigData->AttemptConfigIndex); 1184 1185 AttemptConfigData->NicIndex = NicInfo->NicIndex; 1186 AttemptConfigData->DhcpSuccess = FALSE; 1187 AttemptConfigData->ValidiBFTPath = (BOOLEAN) (mPrivate->EnableMpio ? TRUE : FALSE); 1188 AttemptConfigData->ValidPath = FALSE; 1189 1190 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) { 1191 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp = TRUE; 1192 AttemptConfigData->SessionConfigData.TargetInfoFromDhcp = TRUE; 1193 1194 AttemptConfigData->AutoConfigureMode = 1195 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4); 1196 } 1197 1198 // 1199 // Get some information from dhcp server. 1200 // 1201 if (AttemptConfigData->SessionConfigData.Enabled != ISCSI_DISABLED && 1202 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp) { 1203 1204 if (!mPrivate->Ipv6Flag && 1205 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4 || 1206 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4)) { 1207 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptConfigData); 1208 if (!EFI_ERROR (Status)) { 1209 AttemptConfigData->DhcpSuccess = TRUE; 1210 } 1211 } else if (mPrivate->Ipv6Flag && 1212 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6 || 1213 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6)) { 1214 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptConfigData); 1215 if (!EFI_ERROR (Status)) { 1216 AttemptConfigData->DhcpSuccess = TRUE; 1217 } 1218 } 1219 1220 // 1221 // Refresh the state of this attempt to NVR. 1222 // 1223 AsciiStrToUnicodeStr (AttemptConfigData->MacString, MacString); 1224 UnicodeSPrint ( 1225 mPrivate->PortString, 1226 (UINTN) ISCSI_NAME_IFR_MAX_SIZE, 1227 L"%s%d", 1228 MacString, 1229 (UINTN) AttemptConfigData->AttemptConfigIndex 1230 ); 1231 1232 gRT->SetVariable ( 1233 mPrivate->PortString, 1234 &gEfiIScsiInitiatorNameProtocolGuid, 1235 ISCSI_CONFIG_VAR_ATTR, 1236 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA), 1237 AttemptConfigData 1238 ); 1239 } 1240 1241 // 1242 // Update Attempt Help Info. 1243 // 1244 1245 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED) { 1246 UnicodeSPrint (IScsiMode, 64, L"Disabled"); 1247 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) { 1248 UnicodeSPrint (IScsiMode, 64, L"Enabled"); 1249 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) { 1250 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO"); 1251 } 1252 1253 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) { 1254 UnicodeSPrint (IpMode, 64, L"IP4"); 1255 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) { 1256 UnicodeSPrint (IpMode, 64, L"IP6"); 1257 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) { 1258 UnicodeSPrint (IpMode, 64, L"Autoconfigure"); 1259 } 1260 1261 UnicodeSPrint ( 1262 mPrivate->PortString, 1263 (UINTN) ISCSI_NAME_IFR_MAX_SIZE, 1264 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s", 1265 MacString, 1266 NicInfo->BusNumber, 1267 NicInfo->DeviceNumber, 1268 NicInfo->FunctionNumber, 1269 IScsiMode, 1270 IpMode 1271 ); 1272 1273 AttemptConfigData->AttemptTitleHelpToken = HiiSetString ( 1274 mCallbackInfo->RegisteredHandle, 1275 0, 1276 mPrivate->PortString, 1277 NULL 1278 ); 1279 ASSERT (AttemptConfigData->AttemptTitleHelpToken != 0); 1280 1281 // 1282 // Record the attempt in global link list. 1283 // 1284 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link); 1285 mPrivate->AttemptCount++; 1286 1287 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) { 1288 mPrivate->MpioCount++; 1289 mPrivate->EnableMpio = TRUE; 1290 1291 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB) { 1292 mPrivate->Krb5MpioCount++; 1293 } 1294 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) { 1295 mPrivate->SinglePathCount++; 1296 } 1297 } 1298 1299 // 1300 // Reorder the AttemptConfig by the configured order. 1301 // 1302 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) { 1303 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]); 1304 if (AttemptConfigData == NULL) { 1305 continue; 1306 } 1307 1308 RemoveEntryList (&AttemptConfigData->Link); 1309 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link); 1310 } 1311 1312 // 1313 // Update the Main Form. 1314 // 1315 IScsiConfigUpdateAttempt (); 1316 1317 FreePool (AttemptConfigOrder); 1318 1319 // 1320 // There should be at least one attempt configuration. 1321 // 1322 if (!mPrivate->EnableMpio) { 1323 if (mPrivate->SinglePathCount == 0) { 1324 return EFI_NOT_FOUND; 1325 } 1326 mPrivate->ValidSinglePathCount = mPrivate->SinglePathCount; 1327 } 1328 1329 return EFI_SUCCESS; 1330} 1331 1332 1333/** 1334 Get the device path of the iSCSI tcp connection and update it. 1335 1336 @param Session The iSCSI session. 1337 1338 @return The updated device path. 1339 @retval NULL Other errors as indicated. 1340 1341**/ 1342EFI_DEVICE_PATH_PROTOCOL * 1343IScsiGetTcpConnDevicePath ( 1344 IN ISCSI_SESSION *Session 1345 ) 1346{ 1347 ISCSI_CONNECTION *Conn; 1348 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 1349 EFI_STATUS Status; 1350 EFI_DEV_PATH *DPathNode; 1351 1352 if (Session->State != SESSION_STATE_LOGGED_IN) { 1353 return NULL; 1354 } 1355 1356 Conn = NET_LIST_USER_STRUCT_S ( 1357 Session->Conns.ForwardLink, 1358 ISCSI_CONNECTION, 1359 Link, 1360 ISCSI_CONNECTION_SIGNATURE 1361 ); 1362 1363 Status = gBS->HandleProtocol ( 1364 Conn->TcpIo.Handle, 1365 &gEfiDevicePathProtocolGuid, 1366 (VOID **) &DevicePath 1367 ); 1368 if (EFI_ERROR (Status)) { 1369 return NULL; 1370 } 1371 // 1372 // Duplicate it. 1373 // 1374 DevicePath = DuplicateDevicePath (DevicePath); 1375 if (DevicePath == NULL) { 1376 return NULL; 1377 } 1378 1379 DPathNode = (EFI_DEV_PATH *) DevicePath; 1380 1381 while (!IsDevicePathEnd (&DPathNode->DevPath)) { 1382 if (DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) { 1383 if (!Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP) { 1384 DPathNode->Ipv4.LocalPort = 0; 1385 1386 DPathNode->Ipv4.StaticIpAddress = 1387 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp); 1388 1389 IP4_COPY_ADDRESS ( 1390 &DPathNode->Ipv4.GatewayIpAddress, 1391 &Session->ConfigData->SessionConfigData.Gateway 1392 ); 1393 1394 IP4_COPY_ADDRESS ( 1395 &DPathNode->Ipv4.SubnetMask, 1396 &Session->ConfigData->SessionConfigData.SubnetMask 1397 ); 1398 break; 1399 } else if (Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv6_DP) { 1400 DPathNode->Ipv6.LocalPort = 0; 1401 DPathNode->Ipv6.IpAddressOrigin = 0; 1402 DPathNode->Ipv6.PrefixLength = IP6_PREFIX_LENGTH; 1403 ZeroMem (&DPathNode->Ipv6.GatewayIpAddress, sizeof (EFI_IPv6_ADDRESS)); 1404 break; 1405 } 1406 } 1407 1408 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath); 1409 } 1410 1411 return DevicePath; 1412} 1413 1414 1415/** 1416 Abort the session when the transition from BS to RT is initiated. 1417 1418 @param[in] Event The event signaled. 1419 @param[in] Context The iSCSI driver data. 1420 1421**/ 1422VOID 1423EFIAPI 1424IScsiOnExitBootService ( 1425 IN EFI_EVENT Event, 1426 IN VOID *Context 1427 ) 1428{ 1429 ISCSI_DRIVER_DATA *Private; 1430 1431 Private = (ISCSI_DRIVER_DATA *) Context; 1432 gBS->CloseEvent (Private->ExitBootServiceEvent); 1433 1434 if (Private->Session != NULL) { 1435 IScsiSessionAbort (Private->Session); 1436 } 1437} 1438