1 /** @file 2 Miscellaneous routines for iSCSI driver. 3 4 Copyright (c) 2004 - 2016, 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 @retval EFI_SUCCESS The clean operation is successful. 593 @retval Others Other errors as indicated. 594 595 **/ 596 EFI_STATUS 597 IScsiCleanDriverData ( 598 IN ISCSI_DRIVER_DATA *Private 599 ) 600 { 601 EFI_STATUS Status; 602 603 Status = EFI_SUCCESS; 604 605 if (Private->DevicePath != NULL) { 606 Status = gBS->UninstallProtocolInterface ( 607 Private->ExtScsiPassThruHandle, 608 &gEfiDevicePathProtocolGuid, 609 Private->DevicePath 610 ); 611 if (EFI_ERROR (Status)) { 612 goto EXIT; 613 } 614 615 FreePool (Private->DevicePath); 616 } 617 618 if (Private->ExtScsiPassThruHandle != NULL) { 619 Status = gBS->UninstallProtocolInterface ( 620 Private->ExtScsiPassThruHandle, 621 &gEfiExtScsiPassThruProtocolGuid, 622 &Private->IScsiExtScsiPassThru 623 ); 624 } 625 626 EXIT: 627 628 gBS->CloseEvent (Private->ExitBootServiceEvent); 629 630 FreePool (Private); 631 return Status; 632 } 633 634 /** 635 Check wheather the Controller is configured to use DHCP protocol. 636 637 @param[in] Controller The handle of the controller. 638 639 @retval TRUE The handle of the controller need the Dhcp protocol. 640 @retval FALSE The handle of the controller does not need the Dhcp protocol. 641 642 **/ 643 BOOLEAN 644 IScsiDhcpIsConfigured ( 645 IN EFI_HANDLE Controller 646 ) 647 { 648 EFI_STATUS Status; 649 EFI_MAC_ADDRESS MacAddress; 650 UINTN HwAddressSize; 651 UINT16 VlanId; 652 CHAR16 MacString[70]; 653 ISCSI_SESSION_CONFIG_NVDATA *ConfigDataTmp; 654 655 // 656 // Get the mac string, it's the name of various variable 657 // 658 Status = NetLibGetMacAddress (Controller, &MacAddress, &HwAddressSize); 659 if (EFI_ERROR (Status)) { 660 return FALSE; 661 } 662 VlanId = NetLibGetVlanId (Controller); 663 IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, MacString); 664 665 // 666 // Get the normal configuration. 667 // 668 Status = GetVariable2 ( 669 MacString, 670 &gEfiIScsiInitiatorNameProtocolGuid, 671 (VOID**)&ConfigDataTmp, 672 NULL 673 ); 674 if (ConfigDataTmp == NULL || EFI_ERROR (Status)) { 675 return FALSE; 676 } 677 678 if (ConfigDataTmp->Enabled && ConfigDataTmp->InitiatorInfoFromDhcp) { 679 FreePool (ConfigDataTmp); 680 return TRUE; 681 } 682 683 FreePool (ConfigDataTmp); 684 return FALSE; 685 } 686 687 /** 688 Get the various configuration data of this iSCSI instance. 689 690 @param[in] Private The iSCSI driver data. 691 692 @retval EFI_SUCCESS The configuration of this instance is got. 693 @retval EFI_ABORTED The operation was aborted. 694 @retval Others Other errors as indicated. 695 **/ 696 EFI_STATUS 697 IScsiGetConfigData ( 698 IN ISCSI_DRIVER_DATA *Private 699 ) 700 { 701 EFI_STATUS Status; 702 ISCSI_SESSION *Session; 703 UINTN BufferSize; 704 EFI_MAC_ADDRESS MacAddress; 705 UINTN HwAddressSize; 706 UINT16 VlanId; 707 CHAR16 MacString[70]; 708 709 // 710 // get the iSCSI Initiator Name 711 // 712 Session = &Private->Session; 713 Session->InitiatorNameLength = ISCSI_NAME_MAX_SIZE; 714 Status = gIScsiInitiatorName.Get ( 715 &gIScsiInitiatorName, 716 &Session->InitiatorNameLength, 717 Session->InitiatorName 718 ); 719 if (EFI_ERROR (Status)) { 720 return Status; 721 } 722 723 // 724 // Get the mac string, it's the name of various variable 725 // 726 Status = NetLibGetMacAddress (Private->Controller, &MacAddress, &HwAddressSize); 727 ASSERT (Status == EFI_SUCCESS); 728 VlanId = NetLibGetVlanId (Private->Controller); 729 IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, MacString); 730 731 // 732 // Get the normal configuration. 733 // 734 BufferSize = sizeof (Session->ConfigData.NvData); 735 Status = gRT->GetVariable ( 736 MacString, 737 &gEfiIScsiInitiatorNameProtocolGuid, 738 NULL, 739 &BufferSize, 740 &Session->ConfigData.NvData 741 ); 742 if (EFI_ERROR (Status)) { 743 return Status; 744 } 745 746 if (!Session->ConfigData.NvData.Enabled) { 747 return EFI_ABORTED; 748 } 749 // 750 // Get the CHAP Auth information. 751 // 752 BufferSize = sizeof (Session->AuthData.AuthConfig); 753 Status = gRT->GetVariable ( 754 MacString, 755 &gIScsiCHAPAuthInfoGuid, 756 NULL, 757 &BufferSize, 758 &Session->AuthData.AuthConfig 759 ); 760 761 if (!EFI_ERROR (Status) && Session->ConfigData.NvData.InitiatorInfoFromDhcp) { 762 // 763 // Start dhcp. 764 // 765 Status = IScsiDoDhcp (Private->Image, Private->Controller, &Session->ConfigData); 766 } 767 768 return Status; 769 } 770 771 /** 772 Get the device path of the iSCSI tcp connection and update it. 773 774 @param[in] Private The iSCSI driver data. 775 776 @return The updated device path. 777 @retval NULL Other errors as indicated. 778 **/ 779 EFI_DEVICE_PATH_PROTOCOL * 780 IScsiGetTcpConnDevicePath ( 781 IN ISCSI_DRIVER_DATA *Private 782 ) 783 { 784 ISCSI_SESSION *Session; 785 ISCSI_CONNECTION *Conn; 786 TCP4_IO *Tcp4Io; 787 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 788 EFI_STATUS Status; 789 EFI_DEV_PATH *DPathNode; 790 791 Session = &Private->Session; 792 if (Session->State != SESSION_STATE_LOGGED_IN) { 793 return NULL; 794 } 795 796 Conn = NET_LIST_USER_STRUCT_S ( 797 Session->Conns.ForwardLink, 798 ISCSI_CONNECTION, 799 Link, 800 ISCSI_CONNECTION_SIGNATURE 801 ); 802 Tcp4Io = &Conn->Tcp4Io; 803 804 Status = gBS->HandleProtocol ( 805 Tcp4Io->Handle, 806 &gEfiDevicePathProtocolGuid, 807 (VOID **)&DevicePath 808 ); 809 if (EFI_ERROR (Status)) { 810 return NULL; 811 } 812 // 813 // Duplicate it. 814 // 815 DevicePath = DuplicateDevicePath (DevicePath); 816 if (DevicePath == NULL) { 817 return NULL; 818 } 819 820 DPathNode = (EFI_DEV_PATH *) DevicePath; 821 822 while (!IsDevicePathEnd (&DPathNode->DevPath)) { 823 if ((DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) && 824 (DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP) 825 ) { 826 827 DPathNode->Ipv4.LocalPort = 0; 828 DPathNode->Ipv4.StaticIpAddress = 829 (BOOLEAN) (!Session->ConfigData.NvData.InitiatorInfoFromDhcp); 830 831 // 832 // Add a judgement here to support previous versions of IPv4_DEVICE_PATH. 833 // In previous versions of IPv4_DEVICE_PATH, GatewayIpAddress and SubnetMask 834 // do not exist. 835 // In new version of IPv4_DEVICE_PATH, structcure length is 27. 836 // 837 if (DevicePathNodeLength (&DPathNode->Ipv4) == IP4_NODE_LEN_NEW_VERSIONS) { 838 839 IP4_COPY_ADDRESS ( 840 &DPathNode->Ipv4.GatewayIpAddress, 841 &Session->ConfigData.NvData.Gateway 842 ); 843 844 IP4_COPY_ADDRESS ( 845 &DPathNode->Ipv4.SubnetMask, 846 &Session->ConfigData.NvData.SubnetMask 847 ); 848 } 849 850 break; 851 } 852 853 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath); 854 } 855 856 return DevicePath; 857 } 858 859 /** 860 Abort the session when the transition from BS to RT is initiated. 861 862 @param[in] Event The event signaled. 863 @param[in] Context The iSCSI driver data. 864 **/ 865 VOID 866 EFIAPI 867 IScsiOnExitBootService ( 868 IN EFI_EVENT Event, 869 IN VOID *Context 870 ) 871 { 872 ISCSI_DRIVER_DATA *Private; 873 874 Private = (ISCSI_DRIVER_DATA *) Context; 875 gBS->CloseEvent (Private->ExitBootServiceEvent); 876 877 IScsiSessionAbort (&Private->Session); 878 } 879 880 /** 881 Tests whether a controller handle is being managed by IScsi driver. 882 883 This function tests whether the driver specified by DriverBindingHandle is 884 currently managing the controller specified by ControllerHandle. This test 885 is performed by evaluating if the the protocol specified by ProtocolGuid is 886 present on ControllerHandle and is was opened by DriverBindingHandle and Nic 887 Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. 888 If ProtocolGuid is NULL, then ASSERT(). 889 890 @param ControllerHandle A handle for a controller to test. 891 @param DriverBindingHandle Specifies the driver binding handle for the 892 driver. 893 @param ProtocolGuid Specifies the protocol that the driver specified 894 by DriverBindingHandle opens in its Start() 895 function. 896 897 @retval EFI_SUCCESS ControllerHandle is managed by the driver 898 specified by DriverBindingHandle. 899 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver 900 specified by DriverBindingHandle. 901 902 **/ 903 EFI_STATUS 904 EFIAPI 905 IScsiTestManagedDevice ( 906 IN EFI_HANDLE ControllerHandle, 907 IN EFI_HANDLE DriverBindingHandle, 908 IN EFI_GUID *ProtocolGuid 909 ) 910 { 911 EFI_STATUS Status; 912 VOID *ManagedInterface; 913 EFI_HANDLE NicControllerHandle; 914 915 ASSERT (ProtocolGuid != NULL); 916 917 NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid); 918 if (NicControllerHandle == NULL) { 919 return EFI_UNSUPPORTED; 920 } 921 922 Status = gBS->OpenProtocol ( 923 ControllerHandle, 924 (EFI_GUID *) ProtocolGuid, 925 &ManagedInterface, 926 DriverBindingHandle, 927 NicControllerHandle, 928 EFI_OPEN_PROTOCOL_BY_DRIVER 929 ); 930 if (!EFI_ERROR (Status)) { 931 gBS->CloseProtocol ( 932 ControllerHandle, 933 (EFI_GUID *) ProtocolGuid, 934 DriverBindingHandle, 935 NicControllerHandle 936 ); 937 return EFI_UNSUPPORTED; 938 } 939 940 if (Status != EFI_ALREADY_STARTED) { 941 return EFI_UNSUPPORTED; 942 } 943 944 return EFI_SUCCESS; 945 } 946