Changeset 99404 in vbox for trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/IScsiDxe/IScsiProto.c
- Timestamp:
- Apr 14, 2023 3:17:44 PM (22 months ago)
- Location:
- trunk/src/VBox/Devices/EFI/FirmwareNew
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/EFI/FirmwareNew
-
Property svn:mergeinfo
changed from (toggle deleted branches)
to (toggle deleted branches)/vendor/edk2/current 103735-103757,103769-103776,129194-145445 /vendor/edk2/current 103735-103757,103769-103776,129194-156846
-
Property svn:mergeinfo
changed from (toggle deleted branches)
-
trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/IScsiDxe/IScsiProto.c
r85718 r99404 9 9 #include "IScsiImpl.h" 10 10 11 UINT32 mDataSegPad = 0;11 UINT32 mDataSegPad = 0; 12 12 13 13 /** … … 45 45 } 46 46 47 48 47 /** 49 48 Check the sequence number according to RFC3720. … … 80 79 } 81 80 } 82 83 81 84 82 /** … … 98 96 { 99 97 if (ISCSI_SEQ_LT (MaxCmdSN, ExpCmdSN - 1)) { 100 return 98 return; 101 99 } 102 100 … … 109 107 } 110 108 } 111 112 109 113 110 /** … … 124 121 EFI_STATUS 125 122 IScsiConnLogin ( 126 IN OUT ISCSI_CONNECTION 127 IN UINT16 123 IN OUT ISCSI_CONNECTION *Conn, 124 IN UINT16 Timeout 128 125 ) 129 126 { … … 172 169 } 173 170 174 175 171 /** 176 172 Reset the iSCSI connection. … … 187 183 } 188 184 189 190 185 /** 191 186 Create a TCP connection for the iSCSI session. … … 198 193 ISCSI_CONNECTION * 199 194 IScsiCreateConnection ( 200 IN ISCSI_SESSION 195 IN ISCSI_SESSION *Session 201 196 ) 202 197 { … … 246 241 // Set the default connection-only parameters. 247 242 // 248 Conn->MaxRecvDataSegmentLength 249 Conn->HeaderDigest 250 Conn->DataDigest 243 Conn->MaxRecvDataSegmentLength = DEFAULT_MAX_RECV_DATA_SEG_LEN; 244 Conn->HeaderDigest = IScsiDigestNone; 245 Conn->DataDigest = IScsiDigestNone; 251 246 252 247 if (NvData->DnsMode) { … … 260 255 } 261 256 262 if (EFI_ERROR (Status)) {263 DEBUG (( EFI_D_ERROR, "The configuration of Target address or DNS server address is invalid!\n"));257 if (EFI_ERROR (Status)) { 258 DEBUG ((DEBUG_ERROR, "The configuration of Target address or DNS server address is invalid!\n")); 264 259 FreePool (Conn); 265 260 return NULL; … … 293 288 Private->Image, 294 289 Private->Controller, 295 (UINT8) (!Conn->Ipv6Flag ? TCP_VERSION_4: TCP_VERSION_6),290 (UINT8)(!Conn->Ipv6Flag ? TCP_VERSION_4 : TCP_VERSION_6), 296 291 &TcpIoConfig, 297 292 &Conn->TcpIo … … 305 300 return Conn; 306 301 } 307 308 302 309 303 /** … … 382 376 383 377 SubnetPrefixLength = 0; 384 RouteEntry = Ip6ModeData.RouteCount;378 RouteEntry = Ip6ModeData.RouteCount; 385 379 for (Index = 0; Index < Ip6ModeData.RouteCount; Index++) { 386 380 if (NetIp6IsNetEqual (TargetIp, &Ip6ModeData.RouteTable[Index].Destination, Ip6ModeData.RouteTable[Index].PrefixLength)) { 387 381 if (SubnetPrefixLength < Ip6ModeData.RouteTable[Index].PrefixLength) { 388 382 SubnetPrefixLength = Ip6ModeData.RouteTable[Index].PrefixLength; 389 RouteEntry = Index;383 RouteEntry = Index; 390 384 } 391 385 } 392 386 } 387 393 388 if (RouteEntry != Ip6ModeData.RouteCount) { 394 389 IP6_COPY_ADDRESS (&NvData->Gateway, &Ip6ModeData.RouteTable[RouteEntry].Gateway); … … 399 394 FreePool (Ip6ModeData.AddressList); 400 395 } 401 if (Ip6ModeData.GroupTable!= NULL) { 396 397 if (Ip6ModeData.GroupTable != NULL) { 402 398 FreePool (Ip6ModeData.GroupTable); 403 399 } 404 if (Ip6ModeData.RouteTable!= NULL) { 400 401 if (Ip6ModeData.RouteTable != NULL) { 405 402 FreePool (Ip6ModeData.RouteTable); 406 403 } 407 if (Ip6ModeData.NeighborCache!= NULL) { 404 405 if (Ip6ModeData.NeighborCache != NULL) { 408 406 FreePool (Ip6ModeData.NeighborCache); 409 407 } 410 if (Ip6ModeData.PrefixTable!= NULL) { 408 409 if (Ip6ModeData.PrefixTable != NULL) { 411 410 FreePool (Ip6ModeData.PrefixTable); 412 411 } 413 if (Ip6ModeData.IcmpTypeList!= NULL) { 412 413 if (Ip6ModeData.IcmpTypeList != NULL) { 414 414 FreePool (Ip6ModeData.IcmpTypeList); 415 415 } 416 416 417 417 return Status; 418 } 419 420 /** 421 Re-set any stateful session-level authentication information that is used by 422 the leading login / leading connection. 423 424 (Note that this driver only supports a single connection per session -- see 425 ISCSI_MAX_CONNS_PER_SESSION.) 426 427 @param[in,out] Session The iSCSI session. 428 **/ 429 STATIC 430 VOID 431 IScsiSessionResetAuthData ( 432 IN OUT ISCSI_SESSION *Session 433 ) 434 { 435 if (Session->AuthType == ISCSI_AUTH_TYPE_CHAP) { 436 Session->AuthData.CHAP.Hash = NULL; 437 } 418 438 } 419 439 … … 471 491 // Login through the newly created connection. 472 492 // 493 IScsiSessionResetAuthData (Session); 473 494 Status = IScsiConnLogin (Conn, Session->ConfigData->SessionConfigData.ConnectTimeout); 474 495 if (EFI_ERROR (Status)) { … … 497 518 Conn->TcpIo.Handle, 498 519 ProtocolGuid, 499 (VOID **) 520 (VOID **)&Tcp, 500 521 Session->Private->Image, 501 522 Session->Private->ExtScsiPassThruHandle, … … 513 534 } 514 535 515 516 536 /** 517 537 Wait for IPsec negotiation, then try to login the iSCSI session again. … … 529 549 ) 530 550 { 531 532 EFI_STATUS Status; 533 EFI_STATUS TimerStatus; 534 EFI_EVENT Timer; 551 EFI_STATUS Status; 552 EFI_STATUS TimerStatus; 553 EFI_EVENT Timer; 535 554 536 555 Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer); … … 551 570 552 571 do { 553 554 572 TimerStatus = gBS->CheckEvent (Timer); 555 573 … … 557 575 Status = IScsiSessionLogin (Session); 558 576 } 559 560 577 } while (TimerStatus == EFI_NOT_READY); 561 578 … … 563 580 return Status; 564 581 } 565 566 582 567 583 /** … … 592 608 return EFI_DEVICE_ERROR; 593 609 } 610 594 611 // 595 612 // Send it to the iSCSI target. … … 601 618 return Status; 602 619 } 603 604 620 605 621 /** … … 629 645 return Status; 630 646 } 647 631 648 ASSERT (Pdu != NULL); 632 649 … … 640 657 return Status; 641 658 } 642 643 659 644 660 /** … … 660 676 EFI_STATUS 661 677 IScsiAddKeyValuePair ( 662 IN OUT NET_BUF 663 IN CHAR8 664 IN CHAR8 665 ) 666 { 667 UINT32 DataSegLen;668 UINT32 KeyLen;669 UINT32 ValueLen;670 UINT32 TotalLen;671 ISCSI_LOGIN_REQUEST *LoginReq;672 CHAR8 *Data;673 674 LoginReq = (ISCSI_LOGIN_REQUEST *)NetbufGetByte (Pdu, 0, NULL);678 IN OUT NET_BUF *Pdu, 679 IN CHAR8 *Key, 680 IN CHAR8 *Value 681 ) 682 { 683 UINT32 DataSegLen; 684 UINT32 KeyLen; 685 UINT32 ValueLen; 686 UINT32 TotalLen; 687 ISCSI_LOGIN_REQUEST *LoginReq; 688 CHAR8 *Data; 689 690 LoginReq = (ISCSI_LOGIN_REQUEST *)NetbufGetByte (Pdu, 0, NULL); 675 691 if (LoginReq == NULL) { 676 692 return EFI_PROTOCOL_ERROR; 677 693 } 678 DataSegLen = NTOH24 (LoginReq->DataSegmentLength); 679 680 KeyLen = (UINT32) AsciiStrLen (Key); 681 ValueLen = (UINT32) AsciiStrLen (Value); 694 695 DataSegLen = NTOH24 (LoginReq->DataSegmentLength); 696 697 KeyLen = (UINT32)AsciiStrLen (Key); 698 ValueLen = (UINT32)AsciiStrLen (Value); 682 699 683 700 // … … 690 707 // Allocate the space for the key-value pair. 691 708 // 692 Data = (CHAR8 *) 709 Data = (CHAR8 *)NetbufAllocSpace (Pdu, TotalLen, NET_BUF_TAIL); 693 710 if (Data == NULL) { 694 711 return EFI_OUT_OF_RESOURCES; 695 712 } 713 696 714 // 697 715 // Add the key. … … 718 736 return EFI_SUCCESS; 719 737 } 720 721 738 722 739 /** … … 734 751 ) 735 752 { 736 ISCSI_SESSION *Session;737 NET_BUF *Nbuf;738 ISCSI_LOGIN_REQUEST *LoginReq;739 EFI_STATUS Status;753 ISCSI_SESSION *Session; 754 NET_BUF *Nbuf; 755 ISCSI_LOGIN_REQUEST *LoginReq; 756 EFI_STATUS Status; 740 757 741 758 Session = Conn->Session; 742 759 743 Nbuf 760 Nbuf = NetbufAlloc (sizeof (ISCSI_LOGIN_REQUEST) + DEFAULT_MAX_RECV_DATA_SEG_LEN); 744 761 if (Nbuf == NULL) { 745 762 return NULL; 746 763 } 747 764 748 LoginReq = (ISCSI_LOGIN_REQUEST *) 765 LoginReq = (ISCSI_LOGIN_REQUEST *)NetbufAllocSpace (Nbuf, sizeof (ISCSI_LOGIN_REQUEST), NET_BUF_TAIL); 749 766 if (LoginReq == NULL) { 750 767 NetbufFree (Nbuf); 751 768 return NULL; 752 769 } 770 753 771 ZeroMem (LoginReq, sizeof (ISCSI_LOGIN_REQUEST)); 754 772 … … 758 776 ISCSI_SET_OPCODE (LoginReq, ISCSI_OPCODE_LOGIN_REQ, ISCSI_REQ_IMMEDIATE); 759 777 ISCSI_SET_STAGES (LoginReq, Conn->CurrentStage, Conn->NextStage); 760 LoginReq->VersionMax 761 LoginReq->VersionMin 762 LoginReq->Tsih 763 LoginReq->InitiatorTaskTag 764 LoginReq->Cid 765 LoginReq->CmdSN 778 LoginReq->VersionMax = ISCSI_VERSION_MAX; 779 LoginReq->VersionMin = ISCSI_VERSION_MIN; 780 LoginReq->Tsih = HTONS (Session->Tsih); 781 LoginReq->InitiatorTaskTag = HTONL (Session->InitiatorTaskTag); 782 LoginReq->Cid = HTONS (Conn->Cid); 783 LoginReq->CmdSN = HTONL (Session->CmdSN); 766 784 767 785 // … … 785 803 786 804 switch (Conn->CurrentStage) { 787 case ISCSI_SECURITY_NEGOTIATION:788 //789 // Both none authentication and CHAP authentication share the CHAP path.790 //791 //792 if (Session->AuthType != ISCSI_AUTH_TYPE_KRB) {793 Status = IScsiCHAPToSendReq (Conn, Nbuf);794 }795 796 break;797 798 case ISCSI_LOGIN_OPERATIONAL_NEGOTIATION:799 //800 // Only negotiate the parameter once.801 //802 if (!Conn->ParamNegotiated) {803 IScsiFillOpParams (Conn, Nbuf);804 }805 806 ISCSI_SET_FLAG (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);807 break;808 809 default:810 //811 // An error occurs...812 //813 Status = EFI_DEVICE_ERROR;814 break;805 case ISCSI_SECURITY_NEGOTIATION: 806 // 807 // Both none authentication and CHAP authentication share the CHAP path. 808 // 809 // 810 if (Session->AuthType != ISCSI_AUTH_TYPE_KRB) { 811 Status = IScsiCHAPToSendReq (Conn, Nbuf); 812 } 813 814 break; 815 816 case ISCSI_LOGIN_OPERATIONAL_NEGOTIATION: 817 // 818 // Only negotiate the parameter once. 819 // 820 if (!Conn->ParamNegotiated) { 821 IScsiFillOpParams (Conn, Nbuf); 822 } 823 824 ISCSI_SET_FLAG (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT); 825 break; 826 827 default: 828 // 829 // An error occurs... 830 // 831 Status = EFI_DEVICE_ERROR; 832 break; 815 833 } 816 834 … … 831 849 return Nbuf; 832 850 } 833 834 851 835 852 /** … … 861 878 UINT32 DataSegLen; 862 879 863 Status 864 Session 865 866 LoginRsp = (ISCSI_LOGIN_RESPONSE *)NetbufGetByte (Pdu, 0, NULL);880 Status = EFI_SUCCESS; 881 Session = Conn->Session; 882 883 LoginRsp = (ISCSI_LOGIN_RESPONSE *)NetbufGetByte (Pdu, 0, NULL); 867 884 if (LoginRsp == NULL) { 868 885 return EFI_PROTOCOL_ERROR; 869 886 } 887 870 888 if (!ISCSI_CHECK_OPCODE (LoginRsp, ISCSI_OPCODE_LOGIN_RSP)) { 871 889 // … … 874 892 return EFI_PROTOCOL_ERROR; 875 893 } 894 876 895 // 877 896 // Get the data segment, if any. … … 883 902 DataSeg = NULL; 884 903 } 904 885 905 // 886 906 // Check the status class in the login response PDU. 887 907 // 888 908 switch (LoginRsp->StatusClass) { 889 case ISCSI_LOGIN_STATUS_SUCCESS: 890 // 891 // Just break here; the response and the data segment will be processed later. 892 // 893 break; 894 895 case ISCSI_LOGIN_STATUS_REDIRECTION: 896 // 897 // The target may be moved to a different address. 898 // 899 if (DataSeg == NULL) { 909 case ISCSI_LOGIN_STATUS_SUCCESS: 910 // 911 // Just break here; the response and the data segment will be processed later. 912 // 913 break; 914 915 case ISCSI_LOGIN_STATUS_REDIRECTION: 916 // 917 // The target may be moved to a different address. 918 // 919 if (DataSeg == NULL) { 920 return EFI_PROTOCOL_ERROR; 921 } 922 923 // 924 // Process the TargetAddress key-value strings in the data segment to update the 925 // target address info. 926 // 927 Status = IScsiUpdateTargetAddress (Session, (CHAR8 *)DataSeg, DataSegLen); 928 if (EFI_ERROR (Status)) { 929 return Status; 930 } 931 932 // 933 // Session will be restarted on this error status because the Target is 934 // redirected by this Login Response. 935 // 936 return EFI_MEDIA_CHANGED; 937 938 default: 939 // 940 // Initiator Error, Target Error, or any other undefined error code. 941 // 900 942 return EFI_PROTOCOL_ERROR; 901 } 902 // 903 // Process the TargetAddress key-value strings in the data segment to update the 904 // target address info. 905 // 906 Status = IScsiUpdateTargetAddress (Session, (CHAR8 *) DataSeg, DataSegLen); 907 if (EFI_ERROR (Status)) { 908 return Status; 909 } 910 // 911 // Session will be restarted on this error status because the Target is 912 // redirected by this Login Response. 913 // 914 return EFI_MEDIA_CHANGED; 915 916 default: 917 // 918 // Initiator Error, Target Error, or any other undefined error code. 919 // 920 return EFI_PROTOCOL_ERROR; 921 } 943 } 944 922 945 // 923 946 // The status is success; extract the wanted fields from the header segment. 924 947 // 925 Transit 926 Continue 927 928 CurrentStage 929 NextStage 930 931 LoginRsp->InitiatorTaskTag 948 Transit = ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_TRANSIT); 949 Continue = ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_CONTINUE); 950 951 CurrentStage = ISCSI_GET_CURRENT_STAGE (LoginRsp); 952 NextStage = ISCSI_GET_NEXT_STAGE (LoginRsp); 953 954 LoginRsp->InitiatorTaskTag = NTOHL (LoginRsp->InitiatorTaskTag); 932 955 933 956 if ((Transit && Continue) || … … 937 960 (CompareMem (Session->Isid, LoginRsp->Isid, sizeof (LoginRsp->Isid)) != 0) || 938 961 (LoginRsp->InitiatorTaskTag != Session->InitiatorTaskTag) 939 ) { 962 ) 963 { 940 964 // 941 965 // A Login Response with the C bit set to 1 MUST have the T bit set to 0. … … 949 973 } 950 974 951 LoginRsp->StatSN 952 LoginRsp->ExpCmdSN 953 LoginRsp->MaxCmdSN 975 LoginRsp->StatSN = NTOHL (LoginRsp->StatSN); 976 LoginRsp->ExpCmdSN = NTOHL (LoginRsp->ExpCmdSN); 977 LoginRsp->MaxCmdSN = NTOHL (LoginRsp->MaxCmdSN); 954 978 955 979 if ((Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION) && (Conn->AuthStep == ISCSI_AUTH_INITIAL)) { … … 983 1007 } 984 1008 } 1009 985 1010 // 986 1011 // Trim off the header segment. … … 1006 1031 1007 1032 switch (CurrentStage) { 1008 case ISCSI_SECURITY_NEGOTIATION: 1009 // 1010 // In security negotiation stage, let CHAP module handle it. 1011 // 1012 if (Session->AuthType != ISCSI_AUTH_TYPE_KRB) { 1013 Status = IScsiCHAPOnRspReceived (Conn); 1014 } 1015 break; 1016 1017 case ISCSI_LOGIN_OPERATIONAL_NEGOTIATION: 1018 // 1019 // Response received with negotiation response on iSCSI parameters: check them. 1020 // 1021 Status = IScsiCheckOpParams (Conn); 1022 if (!EFI_ERROR (Status)) { 1023 Conn->ParamNegotiated = TRUE; 1024 } 1025 1026 break; 1027 1028 default: 1029 // 1030 // Should never get here. 1031 // 1032 Status = EFI_PROTOCOL_ERROR; 1033 break; 1033 case ISCSI_SECURITY_NEGOTIATION: 1034 // 1035 // In security negotiation stage, let CHAP module handle it. 1036 // 1037 if (Session->AuthType != ISCSI_AUTH_TYPE_KRB) { 1038 Status = IScsiCHAPOnRspReceived (Conn); 1039 } 1040 1041 break; 1042 1043 case ISCSI_LOGIN_OPERATIONAL_NEGOTIATION: 1044 // 1045 // Response received with negotiation response on iSCSI parameters: check them. 1046 // 1047 Status = IScsiCheckOpParams (Conn); 1048 if (!EFI_ERROR (Status)) { 1049 Conn->ParamNegotiated = TRUE; 1050 } 1051 1052 break; 1053 1054 default: 1055 // 1056 // Should never get here. 1057 // 1058 Status = EFI_PROTOCOL_ERROR; 1059 break; 1034 1060 } 1035 1061 … … 1050 1076 } 1051 1077 } 1078 1052 1079 // 1053 1080 // Flush the response(s) received. … … 1057 1084 return Status; 1058 1085 } 1059 1060 1086 1061 1087 /** … … 1076 1102 EFI_STATUS 1077 1103 IScsiUpdateTargetAddress ( 1078 IN OUT ISCSI_SESSION 1079 IN CHAR8 1080 IN UINT32 1104 IN OUT ISCSI_SESSION *Session, 1105 IN CHAR8 *Data, 1106 IN UINT32 Len 1081 1107 ) 1082 1108 { … … 1120 1146 TargetAddress++; 1121 1147 } 1122 } else if (*TargetAddress == ISCSI_REDIRECT_ADDR_START_DELIMITER) {1148 } else if (*TargetAddress == ISCSI_REDIRECT_ADDR_START_DELIMITER) { 1123 1149 // 1124 1150 // The domainname of the target is presented in a bracketed IPv6 address format. 1125 1151 // 1126 TargetAddress 1152 TargetAddress++; 1127 1153 IpStr = TargetAddress; 1128 1154 while ((*TargetAddress != '\0') && (*TargetAddress != ISCSI_REDIRECT_ADDR_END_DELIMITER)) { … … 1138 1164 1139 1165 *TargetAddress = '\0'; 1140 TargetAddress ++; 1141 1166 TargetAddress++; 1142 1167 } else { 1143 1168 // … … 1149 1174 TargetAddress++; 1150 1175 } 1176 1151 1177 NvData->DnsMode = TRUE; 1152 1178 } … … 1172 1198 continue; 1173 1199 } else { 1174 NvData->TargetPort = (UINT16) 1200 NvData->TargetPort = (UINT16)Number; 1175 1201 } 1176 1202 } else { … … 1200 1226 // do DNS resolution when creating a TCP connection. 1201 1227 // 1202 if (AsciiStrSize (IpStr) > sizeof (Session->ConfigData->SessionConfigData.TargetUrl)) {1228 if (AsciiStrSize (IpStr) > sizeof (Session->ConfigData->SessionConfigData.TargetUrl)) { 1203 1229 return EFI_INVALID_PARAMETER; 1204 1230 } 1231 1205 1232 CopyMem (&Session->ConfigData->SessionConfigData.TargetUrl, IpStr, AsciiStrSize (IpStr)); 1206 1233 } else { … … 1225 1252 } 1226 1253 1227 1228 1254 /** 1229 1255 The callback function to free the net buffer list. … … 1235 1261 EFIAPI 1236 1262 IScsiFreeNbufList ( 1237 VOID *Arg1263 VOID *Arg 1238 1264 ) 1239 1265 { 1240 1266 ASSERT (Arg != NULL); 1241 1267 1242 NetbufFreeList ((LIST_ENTRY *) 1268 NetbufFreeList ((LIST_ENTRY *)Arg); 1243 1269 FreePool (Arg); 1244 1270 } 1245 1246 1271 1247 1272 /** … … 1254 1279 EFIAPI 1255 1280 IScsiNbufExtFree ( 1256 VOID *Arg 1257 ) 1258 { 1259 } 1260 1281 VOID *Arg 1282 ) 1283 { 1284 } 1261 1285 1262 1286 /** … … 1282 1306 EFI_STATUS 1283 1307 IScsiReceivePdu ( 1284 IN ISCSI_CONNECTION 1285 OUT NET_BUF 1286 IN ISCSI_IN_BUFFER_CONTEXT *Context, OPTIONAL1287 IN BOOLEAN 1288 IN BOOLEAN 1289 IN EFI_EVENT 1290 ) 1291 { 1292 LIST_ENTRY 1293 UINT32 1294 NET_BUF 1295 UINT8 1296 EFI_STATUS 1297 UINT32 1298 UINT32 1299 NET_FRAGMENT 1300 UINT32 1301 NET_BUF 1302 UINT32 1308 IN ISCSI_CONNECTION *Conn, 1309 OUT NET_BUF **Pdu, 1310 IN ISCSI_IN_BUFFER_CONTEXT *Context OPTIONAL, 1311 IN BOOLEAN HeaderDigest, 1312 IN BOOLEAN DataDigest, 1313 IN EFI_EVENT TimeoutEvent OPTIONAL 1314 ) 1315 { 1316 LIST_ENTRY *NbufList; 1317 UINT32 Len; 1318 NET_BUF *PduHdr; 1319 UINT8 *Header; 1320 EFI_STATUS Status; 1321 UINT32 PadLen; 1322 UINT32 InDataOffset; 1323 NET_FRAGMENT Fragment[2]; 1324 UINT32 FragmentCount; 1325 NET_BUF *DataSeg; 1326 UINT32 PadAndCRC32[2]; 1303 1327 1304 1328 NbufList = AllocatePool (sizeof (LIST_ENTRY)); … … 1312 1336 // The header digest will be received together with the PDU header, if exists. 1313 1337 // 1314 Len 1315 PduHdr 1338 Len = sizeof (ISCSI_BASIC_HEADER) + (HeaderDigest ? sizeof (UINT32) : 0); 1339 PduHdr = NetbufAlloc (Len); 1316 1340 if (PduHdr == NULL) { 1317 1341 Status = EFI_OUT_OF_RESOURCES; … … 1324 1348 goto ON_EXIT; 1325 1349 } 1350 1326 1351 InsertTailList (NbufList, &PduHdr->List); 1327 1352 … … 1352 1377 goto FORM_PDU; 1353 1378 } 1379 1354 1380 // 1355 1381 // Get the length of the padding bytes of the data segment. … … 1358 1384 1359 1385 switch (ISCSI_GET_OPCODE (Header)) { 1360 case ISCSI_OPCODE_SCSI_DATA_IN: 1361 // 1362 // To reduce memory copy overhead, try to use the buffer described by Context 1363 // if the PDU is an iSCSI SCSI data. 1364 // 1365 InDataOffset = ISCSI_GET_BUFFER_OFFSET (Header); 1366 if ((Context == NULL) || ((InDataOffset + Len) > Context->InDataLen)) { 1386 case ISCSI_OPCODE_SCSI_DATA_IN: 1387 // 1388 // To reduce memory copy overhead, try to use the buffer described by Context 1389 // if the PDU is an iSCSI SCSI data. 1390 // 1391 InDataOffset = ISCSI_GET_BUFFER_OFFSET (Header); 1392 if ((Context == NULL) || ((InDataOffset + Len) > Context->InDataLen)) { 1393 Status = EFI_PROTOCOL_ERROR; 1394 goto ON_EXIT; 1395 } 1396 1397 Fragment[0].Len = Len; 1398 Fragment[0].Bulk = Context->InData + InDataOffset; 1399 1400 if (DataDigest || (PadLen != 0)) { 1401 // 1402 // The data segment is padded. Use two fragments to receive it: 1403 // the first to receive the useful data; the second to receive the padding. 1404 // 1405 Fragment[1].Len = PadLen + (DataDigest ? sizeof (UINT32) : 0); 1406 Fragment[1].Bulk = (UINT8 *)PadAndCRC32 + (4 - PadLen); 1407 1408 FragmentCount = 2; 1409 } else { 1410 FragmentCount = 1; 1411 } 1412 1413 DataSeg = NetbufFromExt (&Fragment[0], FragmentCount, 0, 0, IScsiNbufExtFree, NULL); 1414 if (DataSeg == NULL) { 1415 Status = EFI_OUT_OF_RESOURCES; 1416 goto ON_EXIT; 1417 } 1418 1419 break; 1420 1421 case ISCSI_OPCODE_SCSI_RSP: 1422 case ISCSI_OPCODE_NOP_IN: 1423 case ISCSI_OPCODE_LOGIN_RSP: 1424 case ISCSI_OPCODE_TEXT_RSP: 1425 case ISCSI_OPCODE_ASYNC_MSG: 1426 case ISCSI_OPCODE_REJECT: 1427 case ISCSI_OPCODE_VENDOR_T0: 1428 case ISCSI_OPCODE_VENDOR_T1: 1429 case ISCSI_OPCODE_VENDOR_T2: 1430 // 1431 // Allocate buffer to receive the data segment. 1432 // 1433 Len += PadLen + (DataDigest ? sizeof (UINT32) : 0); 1434 DataSeg = NetbufAlloc (Len); 1435 if (DataSeg == NULL) { 1436 Status = EFI_OUT_OF_RESOURCES; 1437 goto ON_EXIT; 1438 } 1439 1440 NetbufAllocSpace (DataSeg, Len, NET_BUF_TAIL); 1441 break; 1442 1443 default: 1367 1444 Status = EFI_PROTOCOL_ERROR; 1368 1445 goto ON_EXIT; 1369 }1370 1371 Fragment[0].Len = Len;1372 Fragment[0].Bulk = Context->InData + InDataOffset;1373 1374 if (DataDigest || (PadLen != 0)) {1375 //1376 // The data segment is padded. Use two fragments to receive it:1377 // the first to receive the useful data; the second to receive the padding.1378 //1379 Fragment[1].Len = PadLen + (DataDigest ? sizeof (UINT32) : 0);1380 Fragment[1].Bulk = (UINT8 *)PadAndCRC32 + (4 - PadLen);1381 1382 FragmentCount = 2;1383 } else {1384 FragmentCount = 1;1385 }1386 1387 DataSeg = NetbufFromExt (&Fragment[0], FragmentCount, 0, 0, IScsiNbufExtFree, NULL);1388 if (DataSeg == NULL) {1389 Status = EFI_OUT_OF_RESOURCES;1390 goto ON_EXIT;1391 }1392 1393 break;1394 1395 case ISCSI_OPCODE_SCSI_RSP:1396 case ISCSI_OPCODE_NOP_IN:1397 case ISCSI_OPCODE_LOGIN_RSP:1398 case ISCSI_OPCODE_TEXT_RSP:1399 case ISCSI_OPCODE_ASYNC_MSG:1400 case ISCSI_OPCODE_REJECT:1401 case ISCSI_OPCODE_VENDOR_T0:1402 case ISCSI_OPCODE_VENDOR_T1:1403 case ISCSI_OPCODE_VENDOR_T2:1404 //1405 // Allocate buffer to receive the data segment.1406 //1407 Len += PadLen + (DataDigest ? sizeof (UINT32) : 0);1408 DataSeg = NetbufAlloc (Len);1409 if (DataSeg == NULL) {1410 Status = EFI_OUT_OF_RESOURCES;1411 goto ON_EXIT;1412 }1413 1414 NetbufAllocSpace (DataSeg, Len, NET_BUF_TAIL);1415 break;1416 1417 default:1418 Status = EFI_PROTOCOL_ERROR;1419 goto ON_EXIT;1420 1446 } 1421 1447 … … 1466 1492 } 1467 1493 1468 1469 1494 /** 1470 1495 Check and get the result of the parameter negotiation. … … 1482 1507 ) 1483 1508 { 1484 EFI_STATUS 1485 LIST_ENTRY 1486 CHAR8 1487 UINT32 1488 ISCSI_SESSION 1489 CHAR8 1490 UINTN 1509 EFI_STATUS Status; 1510 LIST_ENTRY *KeyValueList; 1511 CHAR8 *Data; 1512 UINT32 Len; 1513 ISCSI_SESSION *Session; 1514 CHAR8 *Value; 1515 UINTN NumericValue; 1491 1516 1492 1517 ASSERT (Conn->RspQue.BufNum != 0); … … 1494 1519 Session = Conn->Session; 1495 1520 1496 Len 1497 Data 1521 Len = Conn->RspQue.BufSize; 1522 Data = AllocatePool (Len); 1498 1523 if (Data == NULL) { 1499 1524 return EFI_OUT_OF_RESOURCES; 1500 1525 } 1501 1526 1502 NetbufQueCopy (&Conn->RspQue, 0, Len, (UINT8 *) 1527 NetbufQueCopy (&Conn->RspQue, 0, Len, (UINT8 *)Data); 1503 1528 1504 1529 Status = EFI_PROTOCOL_ERROR; … … 1512 1537 return Status; 1513 1538 } 1539 1514 1540 // 1515 1541 // HeaderDigest … … 1529 1555 goto ON_ERROR; 1530 1556 } 1557 1531 1558 // 1532 1559 // DataDigest … … 1546 1573 goto ON_ERROR; 1547 1574 } 1575 1548 1576 // 1549 1577 // ErrorRecoveryLevel: result function is Minimum. … … 1559 1587 } 1560 1588 1561 Session->ErrorRecoveryLevel = (UINT8) 1589 Session->ErrorRecoveryLevel = (UINT8)MIN (Session->ErrorRecoveryLevel, NumericValue); 1562 1590 1563 1591 // … … 1570 1598 } 1571 1599 1572 Session->InitialR2T = (BOOLEAN) 1600 Session->InitialR2T = (BOOLEAN)(AsciiStrCmp (Value, "Yes") == 0); 1573 1601 } 1574 1602 … … 1581 1609 } 1582 1610 1583 Session->ImmediateData = (BOOLEAN) (Session->ImmediateData && (BOOLEAN)(AsciiStrCmp (Value, "Yes") == 0));1611 Session->ImmediateData = (BOOLEAN)(Session->ImmediateData && (BOOLEAN)(AsciiStrCmp (Value, "Yes") == 0)); 1584 1612 1585 1613 // … … 1588 1616 Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_MAX_RECV_DATA_SEGMENT_LENGTH); 1589 1617 if (Value != NULL) { 1590 Conn->MaxRecvDataSegmentLength = (UINT32) IScsiNetNtoi (Value); 1591 } 1618 Conn->MaxRecvDataSegmentLength = (UINT32)IScsiNetNtoi (Value); 1619 } 1620 1592 1621 // 1593 1622 // MaxBurstLength: result function is Minimum. … … 1599 1628 1600 1629 NumericValue = IScsiNetNtoi (Value); 1601 Session->MaxBurstLength = (UINT32) 1630 Session->MaxBurstLength = (UINT32)MIN (Session->MaxBurstLength, NumericValue); 1602 1631 1603 1632 // … … 1612 1641 1613 1642 NumericValue = IScsiNetNtoi (Value); 1614 Session->FirstBurstLength = (UINT32) 1643 Session->FirstBurstLength = (UINT32)MIN (Session->FirstBurstLength, NumericValue); 1615 1644 } 1616 1645 … … 1628 1657 } 1629 1658 1630 Session->MaxConnections = (UINT32) 1659 Session->MaxConnections = (UINT32)MIN (Session->MaxConnections, NumericValue); 1631 1660 1632 1661 // … … 1639 1668 } 1640 1669 1641 Session->DataPDUInOrder = (BOOLEAN) 1670 Session->DataPDUInOrder = (BOOLEAN)(AsciiStrCmp (Value, "Yes") == 0); 1642 1671 } 1643 1672 … … 1651 1680 } 1652 1681 1653 Session->DataSequenceInOrder = (BOOLEAN) 1682 Session->DataSequenceInOrder = (BOOLEAN)(AsciiStrCmp (Value, "Yes") == 0); 1654 1683 } 1655 1684 … … 1668 1697 goto ON_ERROR; 1669 1698 } else { 1670 Session->DefaultTime2Wait = (UINT32) MAX (Session->DefaultTime2Wait, NumericValue); 1671 } 1699 Session->DefaultTime2Wait = (UINT32)MAX (Session->DefaultTime2Wait, NumericValue); 1700 } 1701 1672 1702 // 1673 1703 // DefaultTime2Retain: result function is Minimum. … … 1684 1714 goto ON_ERROR; 1685 1715 } else { 1686 Session->DefaultTime2Retain = (UINT32) MIN (Session->DefaultTime2Retain, NumericValue); 1687 } 1716 Session->DefaultTime2Retain = (UINT32)MIN (Session->DefaultTime2Retain, NumericValue); 1717 } 1718 1688 1719 // 1689 1720 // MaxOutstandingR2T: result function is Minimum. … … 1699 1730 } 1700 1731 1701 Session->MaxOutstandingR2T = (UINT16) 1732 Session->MaxOutstandingR2T = (UINT16)MIN (Session->MaxOutstandingR2T, NumericValue); 1702 1733 1703 1734 // … … 1708 1739 IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_TARGET_PORTAL_GROUP_TAG); 1709 1740 1710 1711 1741 // 1712 1742 // Remove the key-value that may not needed for result function is OR. … … 1738 1768 return Status; 1739 1769 } 1740 1741 1770 1742 1771 /** … … 1753 1782 ) 1754 1783 { 1755 ISCSI_SESSION *Session;1756 CHAR8 Value[256];1784 ISCSI_SESSION *Session; 1785 CHAR8 Value[256]; 1757 1786 1758 1787 Session = Conn->Session; … … 1800 1829 IScsiAddKeyValuePair (Pdu, ISCSI_KEY_MAX_OUTSTANDING_R2T, Value); 1801 1830 } 1802 1803 1831 1804 1832 /** … … 1814 1842 EFI_STATUS 1815 1843 IScsiPadSegment ( 1816 IN OUT NET_BUF 1817 IN UINT32 1844 IN OUT NET_BUF *Pdu, 1845 IN UINT32 Len 1818 1846 ) 1819 1847 { … … 1835 1863 } 1836 1864 1837 1838 1865 /** 1839 1866 Build a key-value list from the data segment. … … 1848 1875 LIST_ENTRY * 1849 1876 IScsiBuildKeyValueList ( 1850 IN CHAR8 *Data,1851 IN UINT32 Len1877 IN CHAR8 *Data, 1878 IN UINT32 Len 1852 1879 ) 1853 1880 { … … 1889 1916 KeyValuePair->Value = Data; 1890 1917 1891 InsertTailList (ListHead, &KeyValuePair->List); ;1918 InsertTailList (ListHead, &KeyValuePair->List); 1892 1919 1893 1920 Data += AsciiStrLen (KeyValuePair->Value) + 1; 1894 Len -= (UINT32)AsciiStrLen (KeyValuePair->Value) + 1;1921 Len -= (UINT32)AsciiStrLen (KeyValuePair->Value) + 1; 1895 1922 } 1896 1923 … … 1903 1930 return NULL; 1904 1931 } 1905 1906 1932 1907 1933 /** … … 1918 1944 CHAR8 * 1919 1945 IScsiGetValueByKeyFromList ( 1920 IN OUT LIST_ENTRY 1921 IN CHAR8 1946 IN OUT LIST_ENTRY *KeyValueList, 1947 IN CHAR8 *Key 1922 1948 ) 1923 1949 { … … 1943 1969 } 1944 1970 1945 1946 1971 /** 1947 1972 Free the key-value list. … … 1952 1977 VOID 1953 1978 IScsiFreeKeyValueList ( 1954 IN LIST_ENTRY 1979 IN LIST_ENTRY *KeyValueList 1955 1980 ) 1956 1981 { … … 1959 1984 1960 1985 while (!IsListEmpty (KeyValueList)) { 1961 Entry 1962 KeyValuePair 1986 Entry = NetListRemoveHead (KeyValueList); 1987 KeyValuePair = NET_LIST_USER_STRUCT (Entry, ISCSI_KEY_VALUE_PAIR, List); 1963 1988 1964 1989 FreePool (KeyValuePair); … … 1967 1992 FreePool (KeyValueList); 1968 1993 } 1969 1970 1994 1971 1995 /** … … 1981 2005 EFI_STATUS 1982 2006 IScsiNormalizeName ( 1983 IN OUT CHAR8 1984 IN UINTN 1985 ) 1986 { 1987 UINTN Index;2007 IN OUT CHAR8 *Name, 2008 IN UINTN Len 2009 ) 2010 { 2011 UINTN Index; 1988 2012 1989 2013 for (Index = 0; Index < Len; Index++) { … … 1992 2016 // Convert the upper-case characters to lower-case ones. 1993 2017 // 1994 Name[Index] = (CHAR8) 2018 Name[Index] = (CHAR8)(Name[Index] - 'A' + 'a'); 1995 2019 } 1996 2020 … … 2000 2024 (Name[Index] != '.') && 2001 2025 (Name[Index] != ':') 2002 ) { 2026 ) 2027 { 2003 2028 // 2004 2029 // ASCII dash, dot, colon lower-case characters and digit characters … … 2018 2043 return EFI_SUCCESS; 2019 2044 } 2020 2021 2045 2022 2046 /** … … 2037 2061 ) 2038 2062 { 2039 ISCSI_SESSION *Session;2040 ISCSI_TCB *NewTcb;2063 ISCSI_SESSION *Session; 2064 ISCSI_TCB *NewTcb; 2041 2065 2042 2066 ASSERT (Tcb != NULL); … … 2055 2079 InitializeListHead (&NewTcb->Link); 2056 2080 2057 NewTcb->SoFarInOrder 2058 NewTcb->InitiatorTaskTag 2059 NewTcb->CmdSN 2060 NewTcb->Conn 2081 NewTcb->SoFarInOrder = TRUE; 2082 NewTcb->InitiatorTaskTag = Session->InitiatorTaskTag; 2083 NewTcb->CmdSN = Session->CmdSN; 2084 NewTcb->Conn = Conn; 2061 2085 2062 2086 InsertTailList (&Session->TcbList, &NewTcb->Link); … … 2072 2096 return EFI_SUCCESS; 2073 2097 } 2074 2075 2098 2076 2099 /** … … 2089 2112 FreePool (Tcb); 2090 2113 } 2091 2092 2114 2093 2115 /** … … 2113 2135 NET_BUF *DataSeg; 2114 2136 2115 Fragment[0].Len 2116 Fragment[0].Bulk 2117 2118 PadLen 2137 Fragment[0].Len = Len; 2138 Fragment[0].Bulk = Data; 2139 2140 PadLen = ISCSI_GET_PAD_LEN (Len); 2119 2141 if (PadLen != 0) { 2120 Fragment[1].Len 2121 Fragment[1].Bulk = (UINT8 *)&mDataSegPad;2122 2123 FragmentCount 2142 Fragment[1].Len = PadLen; 2143 Fragment[1].Bulk = (UINT8 *)&mDataSegPad; 2144 2145 FragmentCount = 2; 2124 2146 } else { 2125 2147 FragmentCount = 1; … … 2130 2152 return DataSeg; 2131 2153 } 2132 2133 2154 2134 2155 /** … … 2146 2167 NET_BUF * 2147 2168 IScsiNewScsiCmdPdu ( 2148 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,2149 IN UINT64 Lun,2150 IN ISCSI_TCB *Tcb2169 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, 2170 IN UINT64 Lun, 2171 IN ISCSI_TCB *Tcb 2151 2172 ) 2152 2173 { … … 2177 2198 // The CDB exceeds 16 bytes. An extended CDB AHS is required. 2178 2199 // 2179 AHSLength = (UINT8) 2200 AHSLength = (UINT8)(AHSLength + ISCSI_ROUNDUP (Packet->CdbLength - 16) + sizeof (ISCSI_ADDITIONAL_HEADER)); 2180 2201 } 2181 2202 … … 2186 2207 } 2187 2208 2188 ScsiCmd = (SCSI_COMMAND *) 2209 ScsiCmd = (SCSI_COMMAND *)NetbufAllocSpace (PduHeader, Length, NET_BUF_TAIL); 2189 2210 if (ScsiCmd == NULL) { 2190 2211 NetbufFree (PduHeader); 2191 2212 return NULL; 2192 2213 } 2193 Header = (ISCSI_ADDITIONAL_HEADER *) (ScsiCmd + 1); 2214 2215 Header = (ISCSI_ADDITIONAL_HEADER *)(ScsiCmd + 1); 2194 2216 2195 2217 ZeroMem (ScsiCmd, Length); … … 2202 2224 // 2203 2225 switch (Packet->DataDirection) { 2204 case DataIn:2205 ISCSI_SET_FLAG (ScsiCmd, SCSI_CMD_PDU_FLAG_READ);2206 ScsiCmd->ExpDataXferLength = NTOHL (Packet->InTransferLength);2207 break;2208 2209 case DataOut:2210 ISCSI_SET_FLAG (ScsiCmd, SCSI_CMD_PDU_FLAG_WRITE);2211 ScsiCmd->ExpDataXferLength = NTOHL (Packet->OutTransferLength);2212 break;2213 2214 case DataBi:2215 ISCSI_SET_FLAG (ScsiCmd, SCSI_CMD_PDU_FLAG_READ | SCSI_CMD_PDU_FLAG_WRITE);2216 ScsiCmd->ExpDataXferLength = NTOHL (Packet->OutTransferLength);2217 2218 //2219 // Fill the bidirectional expected read data length AHS.2220 //2221 BiExpReadDataLenAHS = (ISCSI_BI_EXP_READ_DATA_LEN_AHS *)Header;2222 Header = (ISCSI_ADDITIONAL_HEADER *)(BiExpReadDataLenAHS + 1);2223 2224 BiExpReadDataLenAHS->Length= NTOHS (5);2225 BiExpReadDataLenAHS->Type= ISCSI_AHS_TYPE_BI_EXP_READ_DATA_LEN;2226 BiExpReadDataLenAHS->ExpReadDataLength = NTOHL (Packet->InTransferLength);2227 2228 break;2226 case DataIn: 2227 ISCSI_SET_FLAG (ScsiCmd, SCSI_CMD_PDU_FLAG_READ); 2228 ScsiCmd->ExpDataXferLength = NTOHL (Packet->InTransferLength); 2229 break; 2230 2231 case DataOut: 2232 ISCSI_SET_FLAG (ScsiCmd, SCSI_CMD_PDU_FLAG_WRITE); 2233 ScsiCmd->ExpDataXferLength = NTOHL (Packet->OutTransferLength); 2234 break; 2235 2236 case DataBi: 2237 ISCSI_SET_FLAG (ScsiCmd, SCSI_CMD_PDU_FLAG_READ | SCSI_CMD_PDU_FLAG_WRITE); 2238 ScsiCmd->ExpDataXferLength = NTOHL (Packet->OutTransferLength); 2239 2240 // 2241 // Fill the bidirectional expected read data length AHS. 2242 // 2243 BiExpReadDataLenAHS = (ISCSI_BI_EXP_READ_DATA_LEN_AHS *)Header; 2244 Header = (ISCSI_ADDITIONAL_HEADER *)(BiExpReadDataLenAHS + 1); 2245 2246 BiExpReadDataLenAHS->Length = NTOHS (5); 2247 BiExpReadDataLenAHS->Type = ISCSI_AHS_TYPE_BI_EXP_READ_DATA_LEN; 2248 BiExpReadDataLenAHS->ExpReadDataLength = NTOHL (Packet->InTransferLength); 2249 2250 break; 2229 2251 } 2230 2252 … … 2238 2260 2239 2261 if (Packet->CdbLength > 16) { 2240 Header->Length = NTOHS ((UINT16)(Packet->CdbLength - 15));2241 Header->Type 2242 2243 CopyMem (Header + 1, (UINT8 *) 2244 } 2245 2246 Pdu 2247 Session 2248 ImmediateDataLen 2262 Header->Length = NTOHS ((UINT16)(Packet->CdbLength - 15)); 2263 Header->Type = ISCSI_AHS_TYPE_EXT_CDB; 2264 2265 CopyMem (Header + 1, (UINT8 *)Packet->Cdb + 16, Packet->CdbLength - 16); 2266 } 2267 2268 Pdu = PduHeader; 2269 Session = Tcb->Conn->Session; 2270 ImmediateDataLen = 0; 2249 2271 2250 2272 if (Session->ImmediateData && (Packet->OutTransferLength != 0)) { … … 2254 2276 // the MaxRecvdataSegmentLength on this connection. 2255 2277 // 2256 ImmediateDataLen 2257 ImmediateDataLen 2278 ImmediateDataLen = MIN (Session->FirstBurstLength, Packet->OutTransferLength); 2279 ImmediateDataLen = MIN (ImmediateDataLen, Tcb->Conn->MaxRecvDataSegmentLength); 2258 2280 2259 2281 // … … 2265 2287 // Create the data segment. 2266 2288 // 2267 DataSeg = IScsiNewDataSegment ((UINT8 *) 2289 DataSeg = IScsiNewDataSegment ((UINT8 *)Packet->OutDataBuffer, ImmediateDataLen, FALSE); 2268 2290 if (DataSeg == NULL) { 2269 2291 NetbufFree (PduHeader); … … 2294 2316 (ImmediateDataLen == Session->FirstBurstLength) || 2295 2317 (ImmediateDataLen == Packet->OutTransferLength) 2296 ) { 2318 ) 2319 { 2297 2320 // 2298 2321 // Unsolicited data out sequence is not allowed, … … 2309 2332 return Pdu; 2310 2333 } 2311 2312 2334 2313 2335 /** … … 2333 2355 ) 2334 2356 { 2335 LIST_ENTRY *NbufList;2336 NET_BUF *PduHdr;2337 NET_BUF *DataSeg;2338 NET_BUF *Pdu;2339 ISCSI_SCSI_DATA_OUT *DataOutHdr;2340 ISCSI_XFER_CONTEXT *XferContext;2357 LIST_ENTRY *NbufList; 2358 NET_BUF *PduHdr; 2359 NET_BUF *DataSeg; 2360 NET_BUF *Pdu; 2361 ISCSI_SCSI_DATA_OUT *DataOutHdr; 2362 ISCSI_XFER_CONTEXT *XferContext; 2341 2363 2342 2364 NbufList = AllocatePool (sizeof (LIST_ENTRY)); … … 2355 2377 return NULL; 2356 2378 } 2379 2357 2380 // 2358 2381 // Insert the BHS into the buffer list. … … 2360 2383 InsertTailList (NbufList, &PduHdr->List); 2361 2384 2362 DataOutHdr = (ISCSI_SCSI_DATA_OUT *)NetbufAllocSpace (PduHdr, sizeof (ISCSI_SCSI_DATA_OUT), NET_BUF_TAIL);2385 DataOutHdr = (ISCSI_SCSI_DATA_OUT *)NetbufAllocSpace (PduHdr, sizeof (ISCSI_SCSI_DATA_OUT), NET_BUF_TAIL); 2363 2386 if (DataOutHdr == NULL) { 2364 2387 IScsiFreeNbufList (NbufList); 2365 2388 return NULL; 2366 2389 } 2390 2367 2391 XferContext = &Tcb->XferContext; 2368 2392 … … 2384 2408 CopyMem (&DataOutHdr->Lun, &Lun, sizeof (DataOutHdr->Lun)); 2385 2409 } 2410 2386 2411 // 2387 2412 // Build the data segment for this Data Out PDU. … … 2392 2417 return NULL; 2393 2418 } 2419 2394 2420 // 2395 2421 // Put the data segment into the buffer list and combine it with the BHS … … 2404 2430 return Pdu; 2405 2431 } 2406 2407 2432 2408 2433 /** … … 2466 2491 // Update the context and DataSN. 2467 2492 // 2468 Data += DataLen;2469 XferContext->Offset += DataLen;2493 Data += DataLen; 2494 XferContext->Offset += DataLen; 2470 2495 XferContext->DesiredLength -= DataLen; 2471 2496 DataSN++; 2472 2497 } 2498 2473 2499 // 2474 2500 // Set the F bit for the last data out PDU in this sequence. … … 2507 2533 ) 2508 2534 { 2509 LIST_ENTRY 2510 LIST_ENTRY 2511 NET_BUF 2512 EFI_STATUS 2535 LIST_ENTRY *DataOutPduList; 2536 LIST_ENTRY *Entry; 2537 NET_BUF *Pdu; 2538 EFI_STATUS Status; 2513 2539 2514 2540 // … … 2526 2552 // 2527 2553 NET_LIST_FOR_EACH (Entry, DataOutPduList) { 2528 Pdu 2554 Pdu = NET_LIST_USER_STRUCT (Entry, NET_BUF, List); 2529 2555 2530 2556 Status = TcpIoTransmit (&Tcb->Conn->TcpIo, Pdu); … … 2539 2565 return Status; 2540 2566 } 2541 2542 2567 2543 2568 /** … … 2565 2590 EFI_STATUS Status; 2566 2591 2567 DataInHdr = (ISCSI_SCSI_DATA_IN *)NetbufGetByte (Pdu, 0, NULL);2592 DataInHdr = (ISCSI_SCSI_DATA_IN *)NetbufGetByte (Pdu, 0, NULL); 2568 2593 if (DataInHdr == NULL) { 2569 2594 return EFI_PROTOCOL_ERROR; … … 2586 2611 return EFI_PROTOCOL_ERROR; 2587 2612 } 2613 2588 2614 // 2589 2615 // Update the command related sequence numbers. … … 2607 2633 return EFI_PROTOCOL_ERROR; 2608 2634 } 2635 2609 2636 // 2610 2637 // S bit is on, the StatSN is valid. … … 2620 2647 if (ISCSI_FLAG_ON (DataInHdr, SCSI_RSP_PDU_FLAG_OVERFLOW)) { 2621 2648 Packet->InTransferLength += NTOHL (DataInHdr->ResidualCount); 2622 Status = EFI_BAD_BUFFER_SIZE;2649 Status = EFI_BAD_BUFFER_SIZE; 2623 2650 } 2624 2651 … … 2630 2657 return Status; 2631 2658 } 2632 2633 2659 2634 2660 /** … … 2653 2679 ) 2654 2680 { 2655 ISCSI_READY_TO_TRANSFER *R2THdr;2656 EFI_STATUS Status;2657 ISCSI_XFER_CONTEXT *XferContext;2658 UINT8 *Data;2659 2660 R2THdr = (ISCSI_READY_TO_TRANSFER *) 2681 ISCSI_READY_TO_TRANSFER *R2THdr; 2682 EFI_STATUS Status; 2683 ISCSI_XFER_CONTEXT *XferContext; 2684 UINT8 *Data; 2685 2686 R2THdr = (ISCSI_READY_TO_TRANSFER *)NetbufGetByte (Pdu, 0, NULL); 2661 2687 if (R2THdr == NULL) { 2662 2688 return EFI_PROTOCOL_ERROR; 2663 2689 } 2664 2690 2665 R2THdr->InitiatorTaskTag = NTOHL (R2THdr->InitiatorTaskTag);2666 R2THdr->TargetTransferTag = NTOHL (R2THdr->TargetTransferTag);2667 R2THdr->StatSN = NTOHL (R2THdr->StatSN);2668 R2THdr->R2TSeqNum = NTOHL (R2THdr->R2TSeqNum);2669 R2THdr->BufferOffset = NTOHL (R2THdr->BufferOffset);2691 R2THdr->InitiatorTaskTag = NTOHL (R2THdr->InitiatorTaskTag); 2692 R2THdr->TargetTransferTag = NTOHL (R2THdr->TargetTransferTag); 2693 R2THdr->StatSN = NTOHL (R2THdr->StatSN); 2694 R2THdr->R2TSeqNum = NTOHL (R2THdr->R2TSeqNum); 2695 R2THdr->BufferOffset = NTOHL (R2THdr->BufferOffset); 2670 2696 R2THdr->DesiredDataTransferLength = NTOHL (R2THdr->DesiredDataTransferLength); 2671 2697 2672 2698 if ((R2THdr->InitiatorTaskTag != Tcb->InitiatorTaskTag) || !ISCSI_SEQ_EQ (R2THdr->StatSN, Tcb->Conn->ExpStatSN)) { 2673 return EFI_PROTOCOL_ERROR;; 2674 } 2699 return EFI_PROTOCOL_ERROR; 2700 } 2701 2675 2702 // 2676 2703 // Check the sequence number. … … 2681 2708 } 2682 2709 2683 XferContext 2684 XferContext->TargetTransferTag 2685 XferContext->Offset 2686 XferContext->DesiredLength 2710 XferContext = &Tcb->XferContext; 2711 XferContext->TargetTransferTag = R2THdr->TargetTransferTag; 2712 XferContext->Offset = R2THdr->BufferOffset; 2713 XferContext->DesiredLength = R2THdr->DesiredDataTransferLength; 2687 2714 2688 2715 if (((XferContext->Offset + XferContext->DesiredLength) > Packet->OutTransferLength) || 2689 2716 (XferContext->DesiredLength > Tcb->Conn->Session->MaxBurstLength) 2690 ) { 2717 ) 2718 { 2691 2719 return EFI_PROTOCOL_ERROR; 2692 2720 } 2721 2693 2722 // 2694 2723 // Send the data solicited by this R2T. 2695 2724 // 2696 Data = (UINT8 *)Packet->OutDataBuffer + XferContext->Offset;2697 Status 2725 Data = (UINT8 *)Packet->OutDataBuffer + XferContext->Offset; 2726 Status = IScsiSendDataOutPduSequence (Data, Lun, Tcb); 2698 2727 2699 2728 return Status; 2700 2729 } 2701 2702 2730 2703 2731 /** … … 2726 2754 UINT32 DataSegLen; 2727 2755 2728 ScsiRspHdr = (SCSI_RESPONSE *)NetbufGetByte (Pdu, 0, NULL);2756 ScsiRspHdr = (SCSI_RESPONSE *)NetbufGetByte (Pdu, 0, NULL); 2729 2757 if (ScsiRspHdr == NULL) { 2730 2758 return EFI_PROTOCOL_ERROR; 2731 2759 } 2732 2760 2733 ScsiRspHdr->InitiatorTaskTag 2761 ScsiRspHdr->InitiatorTaskTag = NTOHL (ScsiRspHdr->InitiatorTaskTag); 2734 2762 if (ScsiRspHdr->InitiatorTaskTag != Tcb->InitiatorTaskTag) { 2735 2763 return EFI_PROTOCOL_ERROR; 2736 2764 } 2737 2765 2738 ScsiRspHdr->StatSN 2739 2740 Status 2766 ScsiRspHdr->StatSN = NTOHL (ScsiRspHdr->StatSN); 2767 2768 Status = IScsiCheckSN (&Tcb->Conn->ExpStatSN, ScsiRspHdr->StatSN); 2741 2769 if (EFI_ERROR (Status)) { 2742 2770 return Status; 2743 2771 } 2744 2772 2745 ScsiRspHdr->MaxCmdSN 2746 ScsiRspHdr->ExpCmdSN 2773 ScsiRspHdr->MaxCmdSN = NTOHL (ScsiRspHdr->MaxCmdSN); 2774 ScsiRspHdr->ExpCmdSN = NTOHL (ScsiRspHdr->ExpCmdSN); 2747 2775 IScsiUpdateCmdSN (Tcb->Conn->Session, ScsiRspHdr->MaxCmdSN, ScsiRspHdr->ExpCmdSN); 2748 2776 2749 Tcb->StatusXferd 2777 Tcb->StatusXferd = TRUE; 2750 2778 2751 2779 Packet->HostAdapterStatus = ScsiRspHdr->Response; … … 2758 2786 if (ISCSI_FLAG_ON (ScsiRspHdr, SCSI_RSP_PDU_FLAG_BI_READ_OVERFLOW | SCSI_RSP_PDU_FLAG_BI_READ_UNDERFLOW) || 2759 2787 ISCSI_FLAG_ON (ScsiRspHdr, SCSI_RSP_PDU_FLAG_OVERFLOW | SCSI_RSP_PDU_FLAG_UNDERFLOW) 2760 ) { 2788 ) 2789 { 2761 2790 return EFI_PROTOCOL_ERROR; 2762 2791 } … … 2764 2793 if (ISCSI_FLAG_ON (ScsiRspHdr, SCSI_RSP_PDU_FLAG_BI_READ_OVERFLOW)) { 2765 2794 Packet->InTransferLength += NTOHL (ScsiRspHdr->BiReadResidualCount); 2766 Status = EFI_BAD_BUFFER_SIZE;2795 Status = EFI_BAD_BUFFER_SIZE; 2767 2796 } 2768 2797 … … 2791 2820 DataSegLen = ISCSI_GET_DATASEG_LEN (ScsiRspHdr); 2792 2821 if (DataSegLen != 0) { 2793 SenseData = (ISCSI_SENSE_DATA *)NetbufGetByte (Pdu, sizeof (SCSI_RESPONSE), NULL);2822 SenseData = (ISCSI_SENSE_DATA *)NetbufGetByte (Pdu, sizeof (SCSI_RESPONSE), NULL); 2794 2823 if (SenseData == NULL) { 2795 2824 return EFI_PROTOCOL_ERROR; 2796 2825 } 2797 2826 2798 SenseData->Length 2799 2800 Packet->SenseDataLength = (UINT8) 2827 SenseData->Length = NTOHS (SenseData->Length); 2828 2829 Packet->SenseDataLength = (UINT8)MIN (SenseData->Length, Packet->SenseDataLength); 2801 2830 if (Packet->SenseDataLength != 0) { 2802 2831 CopyMem (Packet->SenseData, &SenseData->Data[0], Packet->SenseDataLength); … … 2808 2837 return Status; 2809 2838 } 2810 2811 2839 2812 2840 /** … … 2830 2858 EFI_STATUS Status; 2831 2859 2832 NopInHdr = (ISCSI_NOP_IN *)NetbufGetByte (Pdu, 0, NULL);2860 NopInHdr = (ISCSI_NOP_IN *)NetbufGetByte (Pdu, 0, NULL); 2833 2861 if (NopInHdr == NULL) { 2834 2862 return EFI_PROTOCOL_ERROR; 2835 2863 } 2836 2864 2837 NopInHdr->StatSN 2838 NopInHdr->ExpCmdSN 2839 NopInHdr->MaxCmdSN 2865 NopInHdr->StatSN = NTOHL (NopInHdr->StatSN); 2866 NopInHdr->ExpCmdSN = NTOHL (NopInHdr->ExpCmdSN); 2867 NopInHdr->MaxCmdSN = NTOHL (NopInHdr->MaxCmdSN); 2840 2868 2841 2869 if (NopInHdr->InitiatorTaskTag == ISCSI_RESERVED_TAG) { … … 2854 2882 return EFI_SUCCESS; 2855 2883 } 2856 2857 2884 2858 2885 /** … … 2882 2909 ) 2883 2910 { 2884 EFI_STATUS Status;2885 ISCSI_DRIVER_DATA *Private;2886 ISCSI_SESSION *Session;2887 EFI_EVENT TimeoutEvent;2888 ISCSI_CONNECTION *Conn;2889 ISCSI_TCB *Tcb;2890 NET_BUF *Pdu;2891 ISCSI_XFER_CONTEXT *XferContext;2892 UINT8 *Data;2893 ISCSI_IN_BUFFER_CONTEXT InBufferContext;2894 UINT64 Timeout;2895 UINT8 *PduHdr;2896 2897 Private 2898 Session 2899 Status 2900 Tcb 2901 TimeoutEvent 2902 Timeout 2911 EFI_STATUS Status; 2912 ISCSI_DRIVER_DATA *Private; 2913 ISCSI_SESSION *Session; 2914 EFI_EVENT TimeoutEvent; 2915 ISCSI_CONNECTION *Conn; 2916 ISCSI_TCB *Tcb; 2917 NET_BUF *Pdu; 2918 ISCSI_XFER_CONTEXT *XferContext; 2919 UINT8 *Data; 2920 ISCSI_IN_BUFFER_CONTEXT InBufferContext; 2921 UINT64 Timeout; 2922 UINT8 *PduHdr; 2923 2924 Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru); 2925 Session = Private->Session; 2926 Status = EFI_SUCCESS; 2927 Tcb = NULL; 2928 TimeoutEvent = NULL; 2929 Timeout = 0; 2903 2930 2904 2931 if (Session->State != SESSION_STATE_LOGGED_IN) { … … 2922 2949 goto ON_EXIT; 2923 2950 } 2951 2924 2952 // 2925 2953 // Encapsulate the SCSI request packet into an iSCSI SCSI Command PDU. … … 2931 2959 } 2932 2960 2933 XferContext 2934 PduHdr 2961 XferContext = &Tcb->XferContext; 2962 PduHdr = NetbufGetByte (Pdu, 0, NULL); 2935 2963 if (PduHdr == NULL) { 2936 2964 Status = EFI_PROTOCOL_ERROR; … … 2938 2966 goto ON_EXIT; 2939 2967 } 2968 2940 2969 XferContext->Offset = ISCSI_GET_DATASEG_LEN (PduHdr); 2941 2970 … … 2954 2983 (XferContext->Offset < Session->FirstBurstLength) && 2955 2984 (XferContext->Offset < Packet->OutTransferLength) 2956 ) { 2985 ) 2986 { 2957 2987 // 2958 2988 // Unsolicited Data-Out sequence is allowed. There is remaining SCSI … … 2960 2990 // 2961 2991 XferContext->TargetTransferTag = ISCSI_RESERVED_TAG; 2962 XferContext->DesiredLength = MIN (2963 Session->FirstBurstLength,2964 Packet->OutTransferLength - XferContext->Offset2965 );2966 2967 Data = (UINT8 *)Packet->OutDataBuffer + XferContext->Offset;2968 Status 2992 XferContext->DesiredLength = MIN ( 2993 Session->FirstBurstLength, 2994 Packet->OutTransferLength - XferContext->Offset 2995 ); 2996 2997 Data = (UINT8 *)Packet->OutDataBuffer + XferContext->Offset; 2998 Status = IScsiSendDataOutPduSequence (Data, Lun, Tcb); 2969 2999 if (EFI_ERROR (Status)) { 2970 3000 goto ON_EXIT; … … 2972 3002 } 2973 3003 2974 InBufferContext.InData = (UINT8 *) 3004 InBufferContext.InData = (UINT8 *)Packet->InDataBuffer; 2975 3005 InBufferContext.InDataLen = Packet->InTransferLength; 2976 3006 … … 3002 3032 goto ON_EXIT; 3003 3033 } 3034 3004 3035 switch (ISCSI_GET_OPCODE (PduHdr)) { 3005 case ISCSI_OPCODE_SCSI_DATA_IN:3006 Status = IScsiOnDataInRcvd (Pdu, Tcb, Packet);3007 break;3008 3009 case ISCSI_OPCODE_R2T:3010 Status = IScsiOnR2TRcvd (Pdu, Tcb, Lun, Packet);3011 break;3012 3013 case ISCSI_OPCODE_SCSI_RSP:3014 Status = IScsiOnScsiRspRcvd (Pdu, Tcb, Packet);3015 break;3016 3017 case ISCSI_OPCODE_NOP_IN:3018 Status = IScsiOnNopInRcvd (Pdu, Tcb);3019 break;3020 3021 case ISCSI_OPCODE_VENDOR_T0:3022 case ISCSI_OPCODE_VENDOR_T1:3023 case ISCSI_OPCODE_VENDOR_T2:3024 //3025 // These messages are vendor specific. Skip them.3026 //3027 break;3028 3029 default:3030 Status = EFI_PROTOCOL_ERROR;3031 break;3036 case ISCSI_OPCODE_SCSI_DATA_IN: 3037 Status = IScsiOnDataInRcvd (Pdu, Tcb, Packet); 3038 break; 3039 3040 case ISCSI_OPCODE_R2T: 3041 Status = IScsiOnR2TRcvd (Pdu, Tcb, Lun, Packet); 3042 break; 3043 3044 case ISCSI_OPCODE_SCSI_RSP: 3045 Status = IScsiOnScsiRspRcvd (Pdu, Tcb, Packet); 3046 break; 3047 3048 case ISCSI_OPCODE_NOP_IN: 3049 Status = IScsiOnNopInRcvd (Pdu, Tcb); 3050 break; 3051 3052 case ISCSI_OPCODE_VENDOR_T0: 3053 case ISCSI_OPCODE_VENDOR_T1: 3054 case ISCSI_OPCODE_VENDOR_T2: 3055 // 3056 // These messages are vendor specific. Skip them. 3057 // 3058 break; 3059 3060 default: 3061 Status = EFI_PROTOCOL_ERROR; 3062 break; 3032 3063 } 3033 3064 … … 3051 3082 return Status; 3052 3083 } 3053 3054 3084 3055 3085 /** … … 3067 3097 ) 3068 3098 { 3069 EFI_STATUS 3099 EFI_STATUS Status; 3070 3100 3071 3101 ASSERT (Session->State != SESSION_STATE_FREE); … … 3084 3114 return Status; 3085 3115 } 3086 3087 3116 3088 3117 /** … … 3100 3129 { 3101 3130 if (!Recovery) { 3102 Session->Signature 3103 Session->State 3131 Session->Signature = ISCSI_SESSION_SIGNATURE; 3132 Session->State = SESSION_STATE_FREE; 3104 3133 3105 3134 InitializeListHead (&Session->Conns); … … 3107 3136 } 3108 3137 3109 Session->Tsih 3110 3111 Session->CmdSN 3112 Session->InitiatorTaskTag 3113 Session->NextCid 3138 Session->Tsih = 0; 3139 3140 Session->CmdSN = 1; 3141 Session->InitiatorTaskTag = 1; 3142 Session->NextCid = 1; 3114 3143 3115 3144 Session->TargetPortalGroupTag = 0; … … 3127 3156 } 3128 3157 3129 3130 3158 /** 3131 3159 Abort the iSCSI session. That is, reset all the connection(s), and free the … … 3144 3172 3145 3173 if (Session->State != SESSION_STATE_LOGGED_IN) { 3146 return 3174 return; 3147 3175 } 3148 3176 … … 3177 3205 Session->State = SESSION_STATE_FAILED; 3178 3206 3179 return 3180 } 3207 return; 3208 }
Note:
See TracChangeset
for help on using the changeset viewer.