1 /** @file 2 Miscellaneous routines for iSCSI driver. 3 4 Copyright (c) 2004 - 2015, 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. On return, 23 Str will hold the trimmed string. 24 25 @param[in] CharC Character will be trimmed from str. 26 **/ 27 VOID 28 StrTrim ( 29 IN OUT CHAR16 *Str, 30 IN CHAR16 CharC 31 ) 32 { 33 CHAR16 *Pointer1; 34 CHAR16 *Pointer2; 35 36 if (*Str == 0) { 37 return; 38 } 39 40 // 41 // Trim off the leading and trailing characters c 42 // 43 for (Pointer1 = Str; (*Pointer1 != 0) && (*Pointer1 == CharC); Pointer1++) { 44 ; 45 } 46 47 Pointer2 = Str; 48 if (Pointer2 == Pointer1) { 49 while (*Pointer1 != 0) { 50 Pointer2++; 51 Pointer1++; 52 } 53 } else { 54 while (*Pointer1 != 0) { 55 *Pointer2 = *Pointer1; 56 Pointer1++; 57 Pointer2++; 58 } 59 *Pointer2 = 0; 60 } 61 62 63 for (Pointer1 = Str + StrLen(Str) - 1; Pointer1 >= Str && *Pointer1 == CharC; Pointer1--) { 64 ; 65 } 66 if (Pointer1 != Str + StrLen(Str) - 1) { 67 *(Pointer1 + 1) = 0; 68 } 69 } 70 71 /** 72 Calculate the prefix length of the IPv4 subnet mask. 73 74 @param[in] SubnetMask The IPv4 subnet mask. 75 76 @return The prefix length of the subnet mask. 77 @retval 0 Other errors as indicated. 78 **/ 79 UINT8 80 IScsiGetSubnetMaskPrefixLength ( 81 IN EFI_IPv4_ADDRESS *SubnetMask 82 ) 83 { 84 UINT8 Len; 85 UINT32 ReverseMask; 86 87 // 88 // The SubnetMask is in network byte order. 89 // 90 ReverseMask = (SubnetMask->Addr[0] << 24) | (SubnetMask->Addr[1] << 16) | (SubnetMask->Addr[2] << 8) | (SubnetMask->Addr[3]); 91 92 // 93 // Reverse it. 94 // 95 ReverseMask = ~ReverseMask; 96 97 if ((ReverseMask & (ReverseMask + 1)) != 0) { 98 return 0; 99 } 100 101 Len = 0; 102 103 while (ReverseMask != 0) { 104 ReverseMask = ReverseMask >> 1; 105 Len++; 106 } 107 108 return (UINT8) (32 - Len); 109 } 110 111 /** 112 Convert the hexadecimal encoded LUN string into the 64-bit LUN. 113 114 @param[in] Str The hexadecimal encoded LUN string. 115 @param[out] Lun Storage to return the 64-bit LUN. 116 117 @retval EFI_SUCCESS The 64-bit LUN is stored in Lun. 118 @retval EFI_INVALID_PARAMETER The string is malformatted. 119 **/ 120 EFI_STATUS 121 IScsiAsciiStrToLun ( 122 IN CHAR8 *Str, 123 OUT UINT8 *Lun 124 ) 125 { 126 UINTN Index, IndexValue, IndexNum, SizeStr; 127 CHAR8 TemStr[2]; 128 UINT8 TemValue; 129 UINT16 Value[4]; 130 131 ZeroMem (Lun, 8); 132 ZeroMem (TemStr, 2); 133 ZeroMem ((UINT8 *) Value, sizeof (Value)); 134 SizeStr = AsciiStrLen (Str); 135 IndexValue = 0; 136 IndexNum = 0; 137 138 for (Index = 0; Index < SizeStr; Index ++) { 139 TemStr[0] = Str[Index]; 140 TemValue = (UINT8) AsciiStrHexToUint64 (TemStr); 141 if (TemValue == 0 && TemStr[0] != '0') { 142 if ((TemStr[0] != '-') || (IndexNum == 0)) { 143 // 144 // Invalid Lun Char 145 // 146 return EFI_INVALID_PARAMETER; 147 } 148 } 149 150 if ((TemValue == 0) && (TemStr[0] == '-')) { 151 // 152 // Next Lun value 153 // 154 if (++IndexValue >= 4) { 155 // 156 // Max 4 Lun value 157 // 158 return EFI_INVALID_PARAMETER; 159 } 160 // 161 // Restart str index for the next lun value 162 // 163 IndexNum = 0; 164 continue; 165 } 166 167 if (++IndexNum > 4) { 168 // 169 // Each Lun Str can't exceed size 4, because it will be as UINT16 value 170 // 171 return EFI_INVALID_PARAMETER; 172 } 173 174 // 175 // Combine UINT16 value 176 // 177 Value[IndexValue] = (UINT16) ((Value[IndexValue] << 4) + TemValue); 178 } 179 180 for (Index = 0; Index <= IndexValue; Index ++) { 181 *((UINT16 *) &Lun[Index * 2]) = HTONS (Value[Index]); 182 } 183 184 return EFI_SUCCESS; 185 } 186 187 /** 188 Convert the 64-bit LUN into the hexadecimal encoded LUN string. 189 190 @param[in] Lun The 64-bit LUN. 191 @param[out] Str The storage to return the hexadecimal encoded LUN string. 192 **/ 193 VOID 194 IScsiLunToUnicodeStr ( 195 IN UINT8 *Lun, 196 OUT CHAR16 *Str 197 ) 198 { 199 UINTN Index; 200 CHAR16 *TempStr; 201 202 TempStr = Str; 203 204 for (Index = 0; Index < 4; Index++) { 205 206 if ((Lun[2 * Index] | Lun[2 * Index + 1]) == 0) { 207 CopyMem(TempStr, L"0-", sizeof (L"0-")); 208 } else { 209 TempStr[0] = (CHAR16) IScsiHexString[Lun[2 * Index] >> 4]; 210 TempStr[1] = (CHAR16) IScsiHexString[Lun[2 * Index] & 0x0F]; 211 TempStr[2] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] >> 4]; 212 TempStr[3] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] & 0x0F]; 213 TempStr[4] = L'-'; 214 TempStr[5] = 0; 215 216 StrTrim (TempStr, L'0'); 217 } 218 219 TempStr += StrLen (TempStr); 220 } 221 222 ASSERT (StrLen(Str) >= 1); 223 Str[StrLen (Str) - 1] = 0; 224 225 for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) { 226 if ((Str[Index] == L'0') && (Str[Index - 1] == L'-')) { 227 Str[Index - 1] = 0; 228 } else { 229 break; 230 } 231 } 232 } 233 234 /** 235 Convert the ASCII string into a UNICODE string. 236 237 @param[in] Source The ASCII string. 238 @param[out] Destination The storage to return the UNICODE string. 239 240 @return CHAR16 * Pointer to the UNICODE string. 241 **/ 242 CHAR16 * 243 IScsiAsciiStrToUnicodeStr ( 244 IN CHAR8 *Source, 245 OUT CHAR16 *Destination 246 ) 247 { 248 ASSERT (Destination != NULL); 249 ASSERT (Source != NULL); 250 251 while (*Source != '\0') { 252 *(Destination++) = (CHAR16) *(Source++); 253 } 254 255 *Destination = '\0'; 256 257 return Destination; 258 } 259 260 /** 261 Convert the UNICODE string into an ASCII string. 262 263 @param[in] Source The UNICODE string. 264 @param[out] Destination The storage to return the ASCII string. 265 266 @return CHAR8 * Pointer to the ASCII string. 267 **/ 268 CHAR8 * 269 IScsiUnicodeStrToAsciiStr ( 270 IN CHAR16 *Source, 271 OUT CHAR8 *Destination 272 ) 273 { 274 ASSERT (Destination != NULL); 275 ASSERT (Source != NULL); 276 277 while (*Source != '\0') { 278 // 279 // If any Unicode characters in Source contain 280 // non-zero value in the upper 8 bits, then ASSERT(). 281 // 282 ASSERT (*Source < 0x100); 283 *(Destination++) = (CHAR8) *(Source++); 284 } 285 286 *Destination = '\0'; 287 288 return Destination; 289 } 290 291 /** 292 Convert the decimal dotted IPv4 address into the binary IPv4 address. 293 294 @param[in] Str The UNICODE string. 295 @param[out] Ip The storage to return the ASCII string. 296 297 @retval EFI_SUCCESS The binary IP address is returned in Ip. 298 @retval EFI_INVALID_PARAMETER The IP string is malformatted. 299 **/ 300 EFI_STATUS 301 IScsiAsciiStrToIp ( 302 IN CHAR8 *Str, 303 OUT EFI_IPv4_ADDRESS *Ip 304 ) 305 { 306 UINTN Index; 307 UINTN Number; 308 309 Index = 0; 310 311 while (*Str != 0) { 312 313 if (Index > 3) { 314 return EFI_INVALID_PARAMETER; 315 } 316 317 Number = 0; 318 while (NET_IS_DIGIT (*Str)) { 319 Number = Number * 10 + (*Str - '0'); 320 Str++; 321 } 322 323 if (Number > 0xFF) { 324 return EFI_INVALID_PARAMETER; 325 } 326 327 Ip->Addr[Index] = (UINT8) Number; 328 329 if ((*Str != '\0') && (*Str != '.')) { 330 // 331 // The current character should be either the NULL terminator or 332 // the dot delimiter. 333 // 334 return EFI_INVALID_PARAMETER; 335 } 336 337 if (*Str == '.') { 338 // 339 // Skip the delimiter. 340 // 341 Str++; 342 } 343 344 Index++; 345 } 346 347 if (Index != 4) { 348 return EFI_INVALID_PARAMETER; 349 } 350 351 return EFI_SUCCESS; 352 } 353 354 /** 355 Convert the mac address into a hexadecimal encoded "-" seperated string. 356 357 @param[in] Mac The mac address. 358 @param[in] Len Length in bytes of the mac address. 359 @param[in] VlanId VLAN ID of the network device. 360 @param[out] Str The storage to return the mac string. 361 **/ 362 VOID 363 IScsiMacAddrToStr ( 364 IN EFI_MAC_ADDRESS *Mac, 365 IN UINT32 Len, 366 IN UINT16 VlanId, 367 OUT CHAR16 *Str 368 ) 369 { 370 UINT32 Index; 371 CHAR16 *String; 372 373 for (Index = 0; Index < Len; Index++) { 374 Str[3 * Index] = (CHAR16) IScsiHexString[(Mac->Addr[Index] >> 4) & 0x0F]; 375 Str[3 * Index + 1] = (CHAR16) IScsiHexString[Mac->Addr[Index] & 0x0F]; 376 Str[3 * Index + 2] = L'-'; 377 } 378 379 String = &Str[3 * Index - 1] ; 380 if (VlanId != 0) { 381 String += UnicodeSPrint (String, 6 * sizeof (CHAR16), L"\\%04x", (UINTN) VlanId); 382 } 383 384 *String = L'\0'; 385 } 386 387 /** 388 Convert the binary encoded buffer into a hexadecimal encoded string. 389 390 @param[in] BinBuffer The buffer containing the binary data. 391 @param[in] BinLength Length of the binary buffer. 392 @param[in, out] HexStr Pointer to the string. 393 @param[in, out] HexLength The length of the string. 394 395 @retval EFI_SUCCESS The binary data is converted to the hexadecimal string 396 and the length of the string is updated. 397 @retval EFI_BUFFER_TOO_SMALL The string is too small. 398 @retval EFI_INVALID_PARAMETER The IP string is malformatted. 399 **/ 400 EFI_STATUS 401 IScsiBinToHex ( 402 IN UINT8 *BinBuffer, 403 IN UINT32 BinLength, 404 IN OUT CHAR8 *HexStr, 405 IN OUT UINT32 *HexLength 406 ) 407 { 408 UINTN Index; 409 410 if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) { 411 return EFI_INVALID_PARAMETER; 412 } 413 414 if (((*HexLength) - 3) < BinLength * 2) { 415 *HexLength = BinLength * 2 + 3; 416 return EFI_BUFFER_TOO_SMALL; 417 } 418 419 *HexLength = BinLength * 2 + 3; 420 // 421 // Prefix for Hex String 422 // 423 HexStr[0] = '0'; 424 HexStr[1] = 'x'; 425 426 for (Index = 0; Index < BinLength; Index++) { 427 HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4]; 428 HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0x0F]; 429 } 430 431 HexStr[Index * 2 + 2] = '\0'; 432 433 return EFI_SUCCESS; 434 } 435 436 /** 437 Convert the hexadecimal string into a binary encoded buffer. 438 439 @param[in, out] BinBuffer The binary buffer. 440 @param[in, out] BinLength Length of the binary buffer. 441 @param[in] HexStr The hexadecimal string. 442 443 @retval EFI_SUCCESS The hexadecimal string is converted into a binary 444 encoded buffer. 445 @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data. 446 **/ 447 EFI_STATUS 448 IScsiHexToBin ( 449 IN OUT UINT8 *BinBuffer, 450 IN OUT UINT32 *BinLength, 451 IN CHAR8 *HexStr 452 ) 453 { 454 UINTN Index; 455 UINTN Length; 456 UINT8 Digit; 457 CHAR8 TemStr[2]; 458 459 ZeroMem (TemStr, sizeof (TemStr)); 460 461 // 462 // Find out how many hex characters the string has. 463 // 464 if ((HexStr[0] == '0') && ((HexStr[1] == 'x') || (HexStr[1] == 'X'))) { 465 HexStr += 2; 466 } 467 468 Length = AsciiStrLen (HexStr); 469 470 for (Index = 0; Index < Length; Index ++) { 471 TemStr[0] = HexStr[Index]; 472 Digit = (UINT8) AsciiStrHexToUint64 (TemStr); 473 if (Digit == 0 && TemStr[0] != '0') { 474 // 475 // Invalid Lun Char 476 // 477 break; 478 } 479 if ((Index & 1) == 0) { 480 BinBuffer [Index/2] = Digit; 481 } else { 482 BinBuffer [Index/2] = (UINT8) ((BinBuffer [Index/2] << 4) + Digit); 483 } 484 } 485 486 *BinLength = (UINT32) ((Index + 1)/2); 487 488 return EFI_SUCCESS; 489 } 490 491 /** 492 Generate random numbers. 493 494 @param[in, out] Rand The buffer to contain random numbers. 495 @param[in] RandLength The length of the Rand buffer. 496 **/ 497 VOID 498 IScsiGenRandom ( 499 IN OUT UINT8 *Rand, 500 IN UINTN RandLength 501 ) 502 { 503 UINT32 Random; 504 505 while (RandLength > 0) { 506 Random = NET_RANDOM (NetRandomInitSeed ()); 507 *Rand++ = (UINT8) (Random); 508 RandLength--; 509 } 510 } 511 512 /** 513 Create the iSCSI driver data.. 514 515 @param[in] Image The handle of the driver image. 516 @param[in] Controller The handle of the controller. 517 518 @return The iSCSI driver data created. 519 @retval NULL Other errors as indicated. 520 **/ 521 ISCSI_DRIVER_DATA * 522 IScsiCreateDriverData ( 523 IN EFI_HANDLE Image, 524 IN EFI_HANDLE Controller 525 ) 526 { 527 ISCSI_DRIVER_DATA *Private; 528 EFI_STATUS Status; 529 530 Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA)); 531 if (Private == NULL) { 532 return NULL; 533 } 534 535 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE; 536 Private->Image = Image; 537 Private->Controller = Controller; 538 539 // 540 // Create an event to be signal when the BS to RT transition is triggerd so 541 // as to abort the iSCSI session. 542 // 543 Status = gBS->CreateEventEx ( 544 EVT_NOTIFY_SIGNAL, 545 TPL_CALLBACK, 546 IScsiOnExitBootService, 547 Private, 548 &gEfiEventExitBootServicesGuid, 549 &Private->ExitBootServiceEvent 550 ); 551 if (EFI_ERROR (Status)) { 552 FreePool (Private); 553 return NULL; 554 } 555 556 CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL)); 557 558 // 559 // 0 is designated to the TargetId, so use another value for the AdapterId. 560 // 561 Private->ExtScsiPassThruMode.AdapterId = 2; 562 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL; 563 Private->ExtScsiPassThruMode.IoAlign = 4; 564 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode; 565 566 // 567 // Install the Ext SCSI PASS THRU protocol. 568 // 569 Status = gBS->InstallProtocolInterface ( 570 &Private->ExtScsiPassThruHandle, 571 &gEfiExtScsiPassThruProtocolGuid, 572 EFI_NATIVE_INTERFACE, 573 &Private->IScsiExtScsiPassThru 574 ); 575 if (EFI_ERROR (Status)) { 576 gBS->CloseEvent (Private->ExitBootServiceEvent); 577 FreePool (Private); 578 579 return NULL; 580 } 581 582 IScsiSessionInit (&Private->Session, FALSE); 583 584 return Private; 585 } 586 587 /** 588 Clean the iSCSI driver data. 589 590 @param[in] Private The iSCSI driver data. 591 **/ 592 VOID 593 IScsiCleanDriverData ( 594 IN ISCSI_DRIVER_DATA *Private 595 ) 596 { 597 if (Private->DevicePath != NULL) { 598 gBS->UninstallProtocolInterface ( 599 Private->ExtScsiPassThruHandle, 600 &gEfiDevicePathProtocolGuid, 601 Private->DevicePath 602 ); 603 604 FreePool (Private->DevicePath); 605 } 606 607 if (Private->ExtScsiPassThruHandle != NULL) { 608 gBS->UninstallProtocolInterface ( 609 Private->ExtScsiPassThruHandle, 610 &gEfiExtScsiPassThruProtocolGuid, 611 &Private->IScsiExtScsiPassThru 612 ); 613 } 614 615 gBS->CloseEvent (Private->ExitBootServiceEvent); 616 617 FreePool (Private); 618 } 619 620 /** 621 Check wheather the Controller is configured to use DHCP protocol. 622 623 @param[in] Controller The handle of the controller. 624 625 @retval TRUE The handle of the controller need the Dhcp protocol. 626 @retval FALSE The handle of the controller does not need the Dhcp protocol. 627 628 **/ 629 BOOLEAN 630 IScsiDhcpIsConfigured ( 631 IN EFI_HANDLE Controller 632 ) 633 { 634 EFI_STATUS Status; 635 EFI_MAC_ADDRESS MacAddress; 636 UINTN HwAddressSize; 637 UINT16 VlanId; 638 CHAR16 MacString[70]; 639 ISCSI_SESSION_CONFIG_NVDATA *ConfigDataTmp; 640 641 // 642 // Get the mac string, it's the name of various variable 643 // 644 Status = NetLibGetMacAddress (Controller, &MacAddress, &HwAddressSize); 645 if (EFI_ERROR (Status)) { 646 return FALSE; 647 } 648 VlanId = NetLibGetVlanId (Controller); 649 IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, MacString); 650 651 // 652 // Get the normal configuration. 653 // 654 Status = GetVariable2 ( 655 MacString, 656 &gEfiIScsiInitiatorNameProtocolGuid, 657 (VOID**)&ConfigDataTmp, 658 NULL 659 ); 660 if (ConfigDataTmp == NULL || EFI_ERROR (Status)) { 661 return FALSE; 662 } 663 664 if (ConfigDataTmp->Enabled && ConfigDataTmp->InitiatorInfoFromDhcp) { 665 FreePool (ConfigDataTmp); 666 return TRUE; 667 } 668 669 FreePool (ConfigDataTmp); 670 return FALSE; 671 } 672 673 /** 674 Get the various configuration data of this iSCSI instance. 675 676 @param[in] Private The iSCSI driver data. 677 678 @retval EFI_SUCCESS The configuration of this instance is got. 679 @retval EFI_ABORTED The operation was aborted. 680 @retval Others Other errors as indicated. 681 **/ 682 EFI_STATUS 683 IScsiGetConfigData ( 684 IN ISCSI_DRIVER_DATA *Private 685 ) 686 { 687 EFI_STATUS Status; 688 ISCSI_SESSION *Session; 689 UINTN BufferSize; 690 EFI_MAC_ADDRESS MacAddress; 691 UINTN HwAddressSize; 692 UINT16 VlanId; 693 CHAR16 MacString[70]; 694 695 // 696 // get the iSCSI Initiator Name 697 // 698 Session = &Private->Session; 699 Session->InitiatorNameLength = ISCSI_NAME_MAX_SIZE; 700 Status = gIScsiInitiatorName.Get ( 701 &gIScsiInitiatorName, 702 &Session->InitiatorNameLength, 703 Session->InitiatorName 704 ); 705 if (EFI_ERROR (Status)) { 706 return Status; 707 } 708 709 // 710 // Get the mac string, it's the name of various variable 711 // 712 Status = NetLibGetMacAddress (Private->Controller, &MacAddress, &HwAddressSize); 713 ASSERT (Status == EFI_SUCCESS); 714 VlanId = NetLibGetVlanId (Private->Controller); 715 IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, MacString); 716 717 // 718 // Get the normal configuration. 719 // 720 BufferSize = sizeof (Session->ConfigData.NvData); 721 Status = gRT->GetVariable ( 722 MacString, 723 &gEfiIScsiInitiatorNameProtocolGuid, 724 NULL, 725 &BufferSize, 726 &Session->ConfigData.NvData 727 ); 728 if (EFI_ERROR (Status)) { 729 return Status; 730 } 731 732 if (!Session->ConfigData.NvData.Enabled) { 733 return EFI_ABORTED; 734 } 735 // 736 // Get the CHAP Auth information. 737 // 738 BufferSize = sizeof (Session->AuthData.AuthConfig); 739 Status = gRT->GetVariable ( 740 MacString, 741 &gIScsiCHAPAuthInfoGuid, 742 NULL, 743 &BufferSize, 744 &Session->AuthData.AuthConfig 745 ); 746 747 if (!EFI_ERROR (Status) && Session->ConfigData.NvData.InitiatorInfoFromDhcp) { 748 // 749 // Start dhcp. 750 // 751 Status = IScsiDoDhcp (Private->Image, Private->Controller, &Session->ConfigData); 752 } 753 754 return Status; 755 } 756 757 /** 758 Get the device path of the iSCSI tcp connection and update it. 759 760 @param[in] Private The iSCSI driver data. 761 762 @return The updated device path. 763 @retval NULL Other errors as indicated. 764 **/ 765 EFI_DEVICE_PATH_PROTOCOL * 766 IScsiGetTcpConnDevicePath ( 767 IN ISCSI_DRIVER_DATA *Private 768 ) 769 { 770 ISCSI_SESSION *Session; 771 ISCSI_CONNECTION *Conn; 772 TCP4_IO *Tcp4Io; 773 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 774 EFI_STATUS Status; 775 EFI_DEV_PATH *DPathNode; 776 777 Session = &Private->Session; 778 if (Session->State != SESSION_STATE_LOGGED_IN) { 779 return NULL; 780 } 781 782 Conn = NET_LIST_USER_STRUCT_S ( 783 Session->Conns.ForwardLink, 784 ISCSI_CONNECTION, 785 Link, 786 ISCSI_CONNECTION_SIGNATURE 787 ); 788 Tcp4Io = &Conn->Tcp4Io; 789 790 Status = gBS->HandleProtocol ( 791 Tcp4Io->Handle, 792 &gEfiDevicePathProtocolGuid, 793 (VOID **)&DevicePath 794 ); 795 if (EFI_ERROR (Status)) { 796 return NULL; 797 } 798 // 799 // Duplicate it. 800 // 801 DevicePath = DuplicateDevicePath (DevicePath); 802 if (DevicePath == NULL) { 803 return NULL; 804 } 805 806 DPathNode = (EFI_DEV_PATH *) DevicePath; 807 808 while (!IsDevicePathEnd (&DPathNode->DevPath)) { 809 if ((DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) && 810 (DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP) 811 ) { 812 813 DPathNode->Ipv4.LocalPort = 0; 814 DPathNode->Ipv4.StaticIpAddress = 815 (BOOLEAN) (!Session->ConfigData.NvData.InitiatorInfoFromDhcp); 816 817 // 818 // Add a judgement here to support previous versions of IPv4_DEVICE_PATH. 819 // In previous versions of IPv4_DEVICE_PATH, GatewayIpAddress and SubnetMask 820 // do not exist. 821 // In new version of IPv4_DEVICE_PATH, structcure length is 27. 822 // 823 if (DevicePathNodeLength (&DPathNode->Ipv4) == IP4_NODE_LEN_NEW_VERSIONS) { 824 825 IP4_COPY_ADDRESS ( 826 &DPathNode->Ipv4.GatewayIpAddress, 827 &Session->ConfigData.NvData.Gateway 828 ); 829 830 IP4_COPY_ADDRESS ( 831 &DPathNode->Ipv4.SubnetMask, 832 &Session->ConfigData.NvData.SubnetMask 833 ); 834 } 835 836 break; 837 } 838 839 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath); 840 } 841 842 return DevicePath; 843 } 844 845 /** 846 Abort the session when the transition from BS to RT is initiated. 847 848 @param[in] Event The event signaled. 849 @param[in] Context The iSCSI driver data. 850 **/ 851 VOID 852 EFIAPI 853 IScsiOnExitBootService ( 854 IN EFI_EVENT Event, 855 IN VOID *Context 856 ) 857 { 858 ISCSI_DRIVER_DATA *Private; 859 860 Private = (ISCSI_DRIVER_DATA *) Context; 861 gBS->CloseEvent (Private->ExitBootServiceEvent); 862 863 IScsiSessionAbort (&Private->Session); 864 } 865 866 /** 867 Tests whether a controller handle is being managed by IScsi driver. 868 869 This function tests whether the driver specified by DriverBindingHandle is 870 currently managing the controller specified by ControllerHandle. This test 871 is performed by evaluating if the the protocol specified by ProtocolGuid is 872 present on ControllerHandle and is was opened by DriverBindingHandle and Nic 873 Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. 874 If ProtocolGuid is NULL, then ASSERT(). 875 876 @param ControllerHandle A handle for a controller to test. 877 @param DriverBindingHandle Specifies the driver binding handle for the 878 driver. 879 @param ProtocolGuid Specifies the protocol that the driver specified 880 by DriverBindingHandle opens in its Start() 881 function. 882 883 @retval EFI_SUCCESS ControllerHandle is managed by the driver 884 specified by DriverBindingHandle. 885 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver 886 specified by DriverBindingHandle. 887 888 **/ 889 EFI_STATUS 890 EFIAPI 891 IScsiTestManagedDevice ( 892 IN EFI_HANDLE ControllerHandle, 893 IN EFI_HANDLE DriverBindingHandle, 894 IN EFI_GUID *ProtocolGuid 895 ) 896 { 897 EFI_STATUS Status; 898 VOID *ManagedInterface; 899 EFI_HANDLE NicControllerHandle; 900 901 ASSERT (ProtocolGuid != NULL); 902 903 NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid); 904 if (NicControllerHandle == NULL) { 905 return EFI_UNSUPPORTED; 906 } 907 908 Status = gBS->OpenProtocol ( 909 ControllerHandle, 910 (EFI_GUID *) ProtocolGuid, 911 &ManagedInterface, 912 DriverBindingHandle, 913 NicControllerHandle, 914 EFI_OPEN_PROTOCOL_BY_DRIVER 915 ); 916 if (!EFI_ERROR (Status)) { 917 gBS->CloseProtocol ( 918 ControllerHandle, 919 (EFI_GUID *) ProtocolGuid, 920 DriverBindingHandle, 921 NicControllerHandle 922 ); 923 return EFI_UNSUPPORTED; 924 } 925 926 if (Status != EFI_ALREADY_STARTED) { 927 return EFI_UNSUPPORTED; 928 } 929 930 return EFI_SUCCESS; 931 } 932