• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   The header file of iSCSI Protocol that defines many specific data structures.
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 #ifndef _ISCSI_PROTO_H_
16 #define _ISCSI_PROTO_H_
17 
18 //
19 // RFC 1982 Serial Number Arithmetic, SERIAL_BITS = 32
20 //
21 #define ISCSI_SEQ_EQ(s1, s2)  ((s1) == (s2))
22 #define ISCSI_SEQ_LT(s1, s2) \
23     ( \
24       (((INT32) (s1) < (INT32) (s2)) && (s2 - s1) < ((UINT32) 1 << 31)) || \
25       (((INT32) (s1) > (INT32) (s2)) && (s1 - s2) > ((UINT32) 1 << 31)) \
26     )
27 #define ISCSI_SEQ_GT(s1, s2) \
28     ( \
29       (((INT32) (s1) < (INT32) (s2)) && (s2 - s1) > ((UINT32) 1 << 31)) || \
30       (((INT32) (s1) > (INT32) (s2)) && (s1 - s2) < ((UINT32) 1 << 31)) \
31     )
32 
33 #define ISCSI_WELL_KNOWN_PORT                   3260
34 #define ISCSI_MAX_CONNS_PER_SESSION             1
35 
36 #define DEFAULT_MAX_RECV_DATA_SEG_LEN           8192
37 #define MAX_RECV_DATA_SEG_LEN_IN_FFP            65536
38 #define DEFAULT_MAX_OUTSTANDING_R2T             1
39 
40 #define ISCSI_VERSION_MAX                       0x00
41 #define ISCSI_VERSION_MIN                       0x00
42 
43 #define ISCSI_REDIRECT_ADDR_START_DELIMITER     '['
44 #define ISCSI_REDIRECT_ADDR_END_DELIMITER       ']'
45 
46 #define ISCSI_KEY_AUTH_METHOD                   "AuthMethod"
47 #define ISCSI_KEY_HEADER_DIGEST                 "HeaderDigest"
48 #define ISCSI_KEY_DATA_DIGEST                   "DataDigest"
49 #define ISCSI_KEY_MAX_CONNECTIONS               "MaxConnections"
50 #define ISCSI_KEY_TARGET_NAME                   "TargetName"
51 #define ISCSI_KEY_INITIATOR_NAME                "InitiatorName"
52 #define ISCSI_KEY_TARGET_ALIAS                  "TargetAlias"
53 #define ISCSI_KEY_INITIATOR_ALIAS               "InitiatorAlias"
54 #define ISCSI_KEY_TARGET_ADDRESS                "TargetAddress"
55 #define ISCSI_KEY_INITIAL_R2T                   "InitialR2T"
56 #define ISCSI_KEY_IMMEDIATE_DATA                "ImmediateData"
57 #define ISCSI_KEY_TARGET_PORTAL_GROUP_TAG       "TargetPortalGroupTag"
58 #define ISCSI_KEY_MAX_BURST_LENGTH              "MaxBurstLength"
59 #define ISCSI_KEY_FIRST_BURST_LENGTH            "FirstBurstLength"
60 #define ISCSI_KEY_DEFAULT_TIME2WAIT             "DefaultTime2Wait"
61 #define ISCSI_KEY_DEFAULT_TIME2RETAIN           "DefaultTime2Retain"
62 #define ISCSI_KEY_MAX_OUTSTANDING_R2T           "MaxOutstandingR2T"
63 #define ISCSI_KEY_DATA_PDU_IN_ORDER             "DataPDUInOrder"
64 #define ISCSI_KEY_DATA_SEQUENCE_IN_ORDER        "DataSequenceInOrder"
65 #define ISCSI_KEY_ERROR_RECOVERY_LEVEL          "ErrorRecoveryLevel"
66 #define ISCSI_KEY_SESSION_TYPE                  "SessionType"
67 #define ISCSI_KEY_MAX_RECV_DATA_SEGMENT_LENGTH  "MaxRecvDataSegmentLength"
68 
69 #define ISCSI_KEY_VALUE_NONE                    "None"
70 
71 ///
72 /// connection state for initiator
73 ///
74 
75 #define CONN_STATE_FREE                         0
76 #define CONN_STATE_XPT_WAIT                     1
77 #define CONN_STATE_IN_LOGIN                     2
78 #define CONN_STATE_LOGGED_IN                    3
79 #define CONN_STATE_IN_LOGOUT                    4
80 #define CONN_STATE_LOGOUT_REQUESTED             5
81 #define CONN_STATE_CLEANUP_WAIT                 6
82 #define CONN_STATE_IN_CLEANUP                   7
83 
84 ///
85 /// session state for initiator
86 ///
87 #define SESSION_STATE_FREE                      0
88 #define SESSION_STATE_LOGGED_IN                 1
89 #define SESSION_STATE_FAILED                    2
90 
91 #define ISCSI_RESERVED_TAG                      0xffffffff
92 
93 #define ISCSI_REQ_IMMEDIATE                     0x40
94 #define ISCSI_OPCODE_MASK                       0x3F
95 
96 #define ISCSI_SET_OPCODE(PduHdr, Op, Flgs)  ((((ISCSI_BASIC_HEADER *) (PduHdr))->OpCode) = ((Op) | (Flgs)))
97 #define ISCSI_GET_OPCODE(PduHdr)            ((((ISCSI_BASIC_HEADER *) (PduHdr))->OpCode) & ISCSI_OPCODE_MASK)
98 #define ISCSI_CHECK_OPCODE(PduHdr, Op)      ((((PduHdr)->OpCode) & ISCSI_OPCODE_MASK) == (Op))
99 #define ISCSI_IMMEDIATE_ON(PduHdr)          ((PduHdr)->OpCode & ISCSI_REQ_IMMEDIATE)
100 #define ISCSI_SET_FLAG(PduHdr, Flag)        (((ISCSI_BASIC_HEADER *) (PduHdr))->Flags |= (BOOLEAN)(Flag))
101 #define ISCSI_CLEAR_FLAG(PduHdr, Flag)      (((ISCSI_BASIC_HEADER *) (PduHdr))->Flags &= ~(Flag))
102 #define ISCSI_FLAG_ON(PduHdr, Flag)         ((BOOLEAN) ((((ISCSI_BASIC_HEADER *) (PduHdr))->Flags & (Flag)) == (Flag)))
103 #define ISCSI_SET_STAGES(PduHdr, Cur, Nxt)  ((PduHdr)->Flags = (UINT8) ((PduHdr)->Flags | ((Cur) << 2 | (Nxt))))
104 #define ISCSI_GET_CURRENT_STAGE(PduHdr)     ((UINT8) (((PduHdr)->Flags >> 2) & 0x3))
105 #define ISCSI_GET_NEXT_STAGE(PduHdr)        ((UINT8) (((PduHdr)->Flags) & 0x3))
106 
107 #define ISCSI_GET_PAD_LEN(DataLen)          ((~(DataLen) + 1) & 0x3)
108 #define ISCSI_ROUNDUP(DataLen)              (((DataLen) + 3) &~(0x3))
109 
110 #define HTON24(Dst, Src) \
111   do { \
112     (Dst)[0]  = (UINT8) ((UINT8) ((Src) >> 16) & 0xFF); \
113     (Dst)[1]  = (UINT8) ((UINT8) ((Src) >> 8) & 0xFF); \
114     (Dst)[2]  = (UINT8) ((UINT8) (Src) & 0xFF); \
115   } while (0);
116 
117 #define NTOH24(src)                         (((src)[0] << 16) | ((src)[1] << 8) | ((src)[2]))
118 
119 #define ISCSI_GET_DATASEG_LEN(PduHdr)       NTOH24 (((ISCSI_BASIC_HEADER *) (PduHdr))->DataSegmentLength)
120 #define ISCSI_SET_DATASEG_LEN(PduHdr, Len)  HTON24 (((ISCSI_BASIC_HEADER *) (PduHdr))->DataSegmentLength, (Len))
121 #define ISCSI_GET_BUFFER_OFFSET(PduHdr)     NTOHL  (((ISCSI_SCSI_DATA_IN *) (PduHdr))->BufferOffset)
122 
123 //
124 // Initiator opcodes.
125 //
126 #define ISCSI_OPCODE_NOP_OUT        0x00
127 #define ISCSI_OPCODE_SCSI_CMD       0x01
128 #define ISCSI_OPCODE_SCSI_TMF_REQ   0x02
129 #define ISCSI_OPCODE_LOGIN_REQ      0x03
130 #define ISCSI_OPCODE_TEXT_REQ       0x04
131 #define ISCSI_OPCODE_SCSI_DATA_OUT  0x05
132 #define ISCSI_OPCODE_LOGOUT_REQ     0x06
133 #define ISCSI_OPCODE_SNACK_REQ      0x10
134 #define ISCSI_OPCODE_VENDOR_I0      0x1c
135 #define ISCSI_OPCODE_VENDOR_I1      0x1d
136 #define ISCSI_OPCODE_VENDOR_I2      0x1e
137 
138 //
139 // Target opcodes.
140 //
141 #define ISCSI_OPCODE_NOP_IN       0x20
142 #define ISCSI_OPCODE_SCSI_RSP     0x21
143 #define ISCSI_OPCODE_SCSI_TMF_RSP 0x22
144 #define ISCSI_OPCODE_LOGIN_RSP    0x23
145 #define ISCSI_OPCODE_TEXT_RSP     0x24
146 #define ISCSI_OPCODE_SCSI_DATA_IN 0x25
147 #define ISCSI_OPCODE_LOGOUT_RSP   0x26
148 #define ISCSI_OPCODE_R2T          0x31
149 #define ISCSI_OPCODE_ASYNC_MSG    0x32
150 #define ISCSI_OPCODE_VENDOR_T0    0x3c
151 #define ISCSI_OPCODE_VENDOR_T1    0x3d
152 #define ISCSI_OPCODE_VENDOR_T2    0x3e
153 #define ISCSI_OPCODE_REJECT       0x3f
154 
155 #define ISCSI_BHS_FLAG_FINAL      0x80
156 
157 //
158 // Defined AHS types, others are reserved.
159 //
160 #define ISCSI_AHS_TYPE_EXT_CDB              0x1
161 #define ISCSI_AHS_TYPE_BI_EXP_READ_DATA_LEN 0x2
162 
163 #define SCSI_CMD_PDU_FLAG_READ        0x40
164 #define SCSI_CMD_PDU_FLAG_WRITE       0x20
165 
166 #define ISCSI_CMD_PDU_TASK_ATTR_MASK  0x07
167 
168 //
169 // task attributes
170 //
171 #define ISCSI_TASK_ATTR_UNTAGGED  0x00
172 #define ISCSI_TASK_ATTR_SIMPLE    0x01
173 #define ISCSI_TASK_ATTR_ORDERD    0x02
174 #define ISCSI_TASK_ATTR_HOQ       0x03
175 #define ISCSI_TASK_ATTR_ACA       0x04
176 
177 //
178 // Flag bit definitions in SCSI response.
179 //
180 #define SCSI_RSP_PDU_FLAG_BI_READ_OVERFLOW  0x10
181 #define SCSI_RSP_PDU_FLAG_BI_READ_UNDERFLOW 0x08
182 #define SCSI_RSP_PDU_FLAG_OVERFLOW          0x04
183 #define SCSI_RSP_PDU_FLAG_UNDERFLOW         0x02
184 
185 //
186 // iSCSI service response codes.
187 //
188 #define ISCSI_SERVICE_RSP_COMMAND_COMPLETE_AT_TARGET  0x00
189 #define ISCSI_SERVICE_RSP_TARGET_FAILURE              0x01
190 
191 #define ISCSI_TMF_RSP_PDU_RSP_FUNCTION_COMPLETE           0
192 #define ISCSI_TMF_RSP_PDU_RSP_TASK_NOT_EXIST              1
193 #define ISCSI_TMF_RSP_PDU_RSP_LUN_NOT_EXIST               2
194 #define ISCSI_TMF_RSP_PDU_RSP_TASK_STILL_ALLEGIANT        3
195 #define ISCSI_TMF_RSP_PDU_RSP_TASK_REASSGIN_NOT_SUPPORTED 4
196 #define ISCSI_TMF_RSP_PDU_RSP_NOT_SUPPORTED               5
197 #define ISCSI_TMF_RSP_PDU_RSP_FUNCTION_AHTH_FAILED        6
198 #define ISCSI_TMF_RSP_PDU_RSP_FUNCTION_REJECTED           255
199 
200 #define SCSI_DATA_IN_PDU_FLAG_ACKKNOWLEDGE  0x40
201 #define SCSI_DATA_IN_PDU_FLAG_OVERFLOW      SCSI_RSP_PDU_FLAG_OVERFLOW
202 #define SCSI_DATA_IN_PDU_FLAG_UNDERFLOW     SCSI_RSP_PDU_FLAG_UNDERFLOW
203 #define SCSI_DATA_IN_PDU_FLAG_STATUS_VALID  0x01
204 
205 #define ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT  0x80
206 #define ISCSI_LOGIN_REQ_PDU_FLAG_CONTINUE 0x40
207 
208 #define ISCSI_LOGIN_RSP_PDU_FLAG_TRANSIT    ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT
209 #define ISCSI_LOGIN_RSP_PDU_FLAG_CONTINUE   ISCSI_LOGIN_REQ_PDU_FLAG_CONTINUE
210 
211 #define ISCSI_LOGIN_STATUS_SUCCESS          0
212 #define ISCSI_LOGIN_STATUS_REDIRECTION      1
213 #define ISCSI_LOGIN_STATUS_INITIATOR_ERROR  2
214 #define ISCSI_LOGIN_STATUS_TARGET_ERROR     3
215 
216 #define ISCSI_LOGOUT_REASON_CLOSE_SESSION                   0
217 #define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION                1
218 #define ISCSI_LOGOUT_REASON_REMOVE_CONNECTION_FOR_RECOVERY  2
219 
220 #define ISCSI_LOGOUT_RESPONSE_SESSION_CLOSED_SUCCESS  0
221 #define ISCSI_LOGOUT_RESPONSE_CID_NOT_FOUND           1
222 #define ISCSI_LOGOUT_RESPONSE_RECOVERY_NOT_SUPPORTED  2
223 #define ISCSI_LOGOUT_RESPONSE_CLEANUP_FAILED          3
224 
225 #define ISCSI_SNACK_REQUEST_TYPE_DATA_OR_R2T  0
226 #define ISCSI_SNACK_REQUEST_TYPE_STATUS       1
227 #define ISCSI_SNACK_REQUEST_TYPE_DATA_ACK     2
228 #define ISCSI_SNACK_REQUEST_TYPE_RDATA        3
229 
230 #define ISCSI_SECURITY_NEGOTIATION          0
231 #define ISCSI_LOGIN_OPERATIONAL_NEGOTIATION 1
232 #define ISCSI_FULL_FEATURE_PHASE            3
233 
234 typedef struct _ISCSI_SESSION               ISCSI_SESSION;
235 typedef struct _ISCSI_CONNECTION            ISCSI_CONNECTION;
236 
237 typedef enum {
238   DataIn  = 0,
239   DataOut = 1,
240   DataBi  = 2
241 } DATA_DIRECTION;
242 
243 ///
244 /// iSCSI Basic Header Segment
245 ///
246 typedef struct _ISCSI_BASIC_HEADER {
247   UINT8   OpCode;
248   UINT8   Flags;
249   UINT16  OpCodeSpecific1;
250   UINT8   TotalAHSLength;
251   UINT8   DataSegmentLength[3];
252   UINT8   Lun[8];
253   UINT32  InitiatorTaskTag;
254   UINT32  OpCodeSpecific2[7];
255 } ISCSI_BASIC_HEADER;
256 
257 typedef struct _ISCSI_ADDTIONAL_HEADER {
258   UINT16  Length;
259   UINT8   Type;
260   UINT8   TypeSpecific[1];
261 } ISCSI_ADDITIONAL_HEADER;
262 
263 typedef struct _ISCSI_BI_EXP_READ_DATA_LEN_AHS {
264   UINT16  Length;
265   UINT8   Type;
266   UINT8   Reserved;
267   UINT32  ExpReadDataLength;
268 } ISCSI_BI_EXP_READ_DATA_LEN_AHS;
269 
270 ///
271 /// SCSI Command
272 ///
273 typedef struct _SCSI_COMMAND {
274   UINT8   OpCode;
275   UINT8   Flags;
276   UINT16  Reserved;
277   UINT8   TotalAHSLength;
278   UINT8   DataSegmentLength[3];
279   UINT8   Lun[8];
280   UINT32  InitiatorTaskTag;
281   UINT32  ExpDataXferLength;
282   UINT32  CmdSN;
283   UINT32  ExpStatSN;
284   UINT8   Cdb[16];
285 } SCSI_COMMAND;
286 
287 ///
288 /// SCSI Response
289 ///
290 typedef struct _SCSI_RESPONSE {
291   UINT8   OpCode;
292   UINT8   Flags;
293   UINT8   Response;
294   UINT8   Status;
295   UINT8   TotalAHSLength;
296   UINT8   DataSegmentLength[3];
297   UINT8   Reserved[8];
298   UINT32  InitiatorTaskTag;
299   UINT32  SNACKTag;
300   UINT32  StatSN;
301   UINT32  ExpCmdSN;
302   UINT32  MaxCmdSN;
303   UINT32  ExpDataSN;
304   UINT32  BiReadResidualCount;
305   UINT32  ResidualCount;
306 } SCSI_RESPONSE;
307 
308 typedef struct _ISCSI_SENSE_DATA {
309   UINT16  Length;
310   UINT8   Data[2];
311 } ISCSI_SENSE_DATA;
312 
313 ///
314 /// iSCSI Task Managment Function Request.
315 ///
316 typedef struct _ISCSI_TMF_REQUEST {
317   UINT8   OpCode;
318   UINT8   Fuction;
319   UINT16  Reserved1;
320   UINT8   TotalAHSLength;
321   UINT8   DataSegmentLength[3];
322   UINT8   Lun[8];
323   UINT32  InitiatorTaskTag;
324   UINT32  ReferencedTaskTag;
325   UINT32  CmdSN;
326   UINT32  ExpStatSN;
327   UINT32  RefCmdSN;
328   UINT32  ExpDataSN;
329   UINT32  Reserved2[2];
330 } ISCSI_TMF_REQUEST;
331 
332 ///
333 /// iSCSI Task Management Function Response.
334 ///
335 typedef struct _ISCSI_TMF_RESPONSE {
336   UINT8   OpCode;
337   UINT8   Reserved1;
338   UINT8   Response;
339   UINT8   Reserved2;
340   UINT8   TotalAHSLength;
341   UINT8   DataSegmentLength[3];
342   UINT32  Reserver3[2];
343   UINT32  InitiatorTaskTag;
344   UINT32  Reserved4;
345   UINT32  StatSN;
346   UINT32  ExpCmdSN;
347   UINT32  MaxCmdSN;
348   UINT32  Reserved[3];
349 } ISCSI_TMF_RESPONSE;
350 
351 ///
352 /// SCSI Data-Out
353 ///
354 typedef struct _ISCSI_SCSI_DATA_OUT {
355   UINT8   OpCode;
356   UINT8   Reserved1[3];
357   UINT8   TotalAHSLength;
358   UINT8   DataSegmentLength[3];
359   UINT8   Lun[8];
360   UINT32  InitiatorTaskTag;
361   UINT32  TargetTransferTag;
362   UINT32  Reserved2;
363   UINT32  ExpStatSN;
364   UINT32  Reserved3;
365   UINT32  DataSN;
366   UINT32  BufferOffset;
367   UINT32  Reserved4;
368 } ISCSI_SCSI_DATA_OUT;
369 
370 ///
371 /// SCSI Data-In
372 ///
373 typedef struct _ISCSI_SCSI_DATA_IN {
374   UINT8   OpCode;
375   UINT8   Flags;
376   UINT8   Reserved1;
377   UINT8   Status;
378   UINT8   TotalAHSLength;
379   UINT8   DataSegmentLength[3];
380   UINT8   Lun[8];
381   UINT32  InitiatorTaskTag;
382   UINT32  TargetTransferTag;
383   UINT32  StatSN;
384   UINT32  ExpCmdSN;
385   UINT32  MaxCmdSN;
386   UINT32  DataSN;
387   UINT32  BufferOffset;
388   UINT32  ResidualCount;
389 } ISCSI_SCSI_DATA_IN;
390 
391 ///
392 /// Ready To Transfer.
393 ///
394 typedef struct _ISCSI_READY_TO_TRANSFER {
395   UINT8   OpCode;
396   UINT8   Reserved1[3];
397   UINT8   TotalAHSLength;
398   UINT8   DataSegmentLength[3];
399   UINT8   Lun[8];
400   UINT32  InitiatorTaskTag;
401   UINT32  TargetTransferTag;
402   UINT32  StatSN;
403   UINT32  ExpCmdSN;
404   UINT32  MaxCmdSN;
405   UINT32  R2TSeqNum;
406   UINT32  BufferOffset;
407   UINT32  DesiredDataTransferLength;
408 } ISCSI_READY_TO_TRANSFER;
409 
410 typedef struct _ISCSI_ASYNC_MESSAGE {
411   UINT8   OpCode;
412   UINT8   Reserved1[8];
413   UINT8   TotalAHSLength;
414   UINT8   DataSegmentLength[3];
415   UINT8   Lun[8];
416   UINT32  InitiatorTaskTag;
417   UINT32  Reserved2;
418   UINT32  StatSN;
419   UINT32  ExpCmdSN;
420   UINT32  MaxCmdSN;
421   UINT8   AsyncEvent;
422   UINT8   AsyncVCode;
423   UINT16  Parameter1;
424   UINT16  Parameter2;
425   UINT16  Parameter3;
426   UINT32  Reserved3;
427 } ISCSI_ASYNC_MESSAGE;
428 
429 ///
430 /// Login Request.
431 ///
432 typedef struct _ISCSI_LOGIN_REQUEST {
433   UINT8   OpCode;
434   UINT8   Flags;
435   UINT8   VersionMax;
436   UINT8   VersionMin;
437   UINT8   TotalAHSLength;
438   UINT8   DataSegmentLength[3];
439   UINT8   Isid[6];
440   UINT16  Tsih;
441   UINT32  InitiatorTaskTag;
442   UINT16  Cid;
443   UINT16  Reserved1;
444   UINT32  CmdSN;
445   UINT32  ExpStatSN;
446   UINT32  Reserved2[4];
447 } ISCSI_LOGIN_REQUEST;
448 
449 ///
450 /// Login Response.
451 ///
452 typedef struct _ISCSI_LOGIN_RESPONSE {
453   UINT8   OpCode;
454   UINT8   Flags;
455   UINT8   VersionMax;
456   UINT8   VersionActive;
457   UINT8   TotalAHSLength;
458   UINT8   DataSegmentLength[3];
459   UINT8   Isid[6];
460   UINT16  Tsih;
461   UINT32  InitiatorTaskTag;
462   UINT32  Reserved1;
463   UINT32  StatSN;
464   UINT32  ExpCmdSN;
465   UINT32  MaxCmdSN;
466   UINT8   StatusClass;
467   UINT8   StatusDetail;
468   UINT8   Reserved2[10];
469 } ISCSI_LOGIN_RESPONSE;
470 
471 ///
472 /// Logout Request.
473 ///
474 typedef struct _ISCSI_LOGOUT_REQUEST {
475   UINT8   OpCode;
476   UINT8   ReasonCode;
477   UINT16  Reserved1;
478   UINT8   TotalAHSLength;
479   UINT8   DataSegmentLength[3];
480   UINT32  Reserved2[2];
481   UINT32  InitiatorTaskTag;
482   UINT16  Cid;
483   UINT16  Reserved3;
484   UINT32  CmdSN;
485   UINT32  ExpStatSN;
486   UINT32  Reserved4[4];
487 } ISCSI_LOGOUT_REQUEST;
488 
489 ///
490 /// Logout Response.
491 ///
492 typedef struct _ISCSI_LOGOUT_RESPONSE {
493   UINT8   OpCode;
494   UINT8   Reserved1;
495   UINT8   Response;
496   UINT8   Reserved2;
497   UINT8   TotalAHSLength;
498   UINT8   DataSegmentLength[3];
499   UINT32  Reserved3[2];
500   UINT32  InitiatorTaskTag;
501   UINT32  Reserved4;
502   UINT32  StatSN;
503   UINT32  ExpCmdSN;
504   UINT32  MaxCmdSN;
505   UINT32  Reserved5;
506   UINT16  Time2Wait;
507   UINT16  Time2Retain;
508   UINT32  Reserved6;
509 } ISCSI_LOGOUT_RESPONSE;
510 
511 ///
512 /// SNACK Request.
513 ///
514 typedef struct _ISCSI_SNACK_REQUEST {
515   UINT8   OpCode;
516   UINT8   Type;
517   UINT16  Reserved1;
518   UINT8   TotalAHSLength;
519   UINT8   DataSegmentLength[3];
520   UINT8   Lun[8];
521   UINT32  InitiatorTaskTag;
522   UINT32  TargetTransferTag;
523   UINT32  Reserved2;
524   UINT32  ExpStatSN;
525   UINT32  Reserved[2];
526   UINT32  BegRun;
527   UINT32  RunLength;
528 } ISCSI_SNACK_REQUEST;
529 
530 ///
531 /// Reject.
532 ///
533 typedef struct _ISCSI_REJECT {
534   UINT8   OpCode;
535   UINT8   Reserved1;
536   UINT8   Reason;
537   UINT8   Reserved2;
538   UINT8   TotalAHSLength;
539   UINT8   DataSegmentLength[3];
540   UINT32  Reserved3[2];
541   UINT32  InitiatorTaskTag;
542   UINT32  Reserved4;
543   UINT32  StatSN;
544   UINT32  ExpCmdSN;
545   UINT32  MaxCmdSN;
546   UINT32  DataSN;
547   UINT32  Reserved5[2];
548 } ISCSI_REJECT;
549 
550 ///
551 /// NOP-Out.
552 ///
553 typedef struct _ISCSI_NOP_OUT {
554   UINT8   OpCode;
555   UINT8   Reserved1[3];
556   UINT8   TotalAHSLength;
557   UINT8   DataSegmentLength[3];
558   UINT8   Lun[8];
559   UINT32  InitiatorTaskTag;
560   UINT32  TargetTransferTag;
561   UINT32  CmdSN;
562   UINT32  ExpStatSN;
563   UINT32  Reserved2[4];
564 } ISCSI_NOP_OUT;
565 
566 ///
567 /// NOP-In.
568 ///
569 typedef struct _ISCSI_NOP_IN {
570   UINT8   OpCode;
571   UINT8   Reserved1[3];
572   UINT8   TotalAHSLength;
573   UINT8   DataSegmentLength[3];
574   UINT8   Lun[8];
575   UINT32  InitiatorTaskTag;
576   UINT32  TargetTransferTag;
577   UINT32  StatSN;
578   UINT32  ExpCmdSN;
579   UINT32  MaxCmdSN;
580   UINT32  Reserved2[3];
581 } ISCSI_NOP_IN;
582 
583 typedef enum {
584   IScsiDigestNone,
585   IScsiDigestCRC32
586 } ISCSI_DIGEST_TYPE;
587 
588 typedef struct _ISCSI_XFER_CONTEXT {
589   UINT32  TargetTransferTag;
590   UINT32  Offset;
591   UINT32  DesiredLength;
592   UINT32  ExpDataSN;
593 } ISCSI_XFER_CONTEXT;
594 
595 typedef struct _ISCSI_IN_BUFFER_CONTEXT {
596   UINT8   *InData;
597   UINT32  InDataLen;
598 } ISCSI_IN_BUFFER_CONTEXT;
599 
600 typedef struct _ISCSI_TCB {
601   LIST_ENTRY          Link;
602 
603   BOOLEAN             SoFarInOrder;
604   UINT32              ExpDataSN;
605   BOOLEAN             FbitReceived;
606   BOOLEAN             StatusXferd;
607   UINT32              ActiveR2Ts;
608   UINT32              Response;
609   CHAR8               *Reason;
610   UINT32              InitiatorTaskTag;
611   UINT32              CmdSN;
612   UINT32              SNACKTag;
613 
614   ISCSI_XFER_CONTEXT  XferContext;
615 
616   ISCSI_CONNECTION    *Conn;
617 } ISCSI_TCB;
618 
619 typedef struct _ISCSI_KEY_VALUE_PAIR {
620   LIST_ENTRY      List;
621 
622   CHAR8           *Key;
623   CHAR8           *Value;
624 } ISCSI_KEY_VALUE_PAIR;
625 
626 /**
627   Attach the iSCSI connection to the iSCSI session.
628 
629   @param[in, out]  Session The iSCSI session.
630   @param[in, out]  Conn    The iSCSI connection.
631 
632 **/
633 VOID
634 IScsiAttatchConnection (
635   IN OUT ISCSI_SESSION     *Session,
636   IN OUT ISCSI_CONNECTION  *Conn
637   );
638 
639 /**
640   Detach the iSCSI connection from the session it belongs to.
641 
642   @param[in, out]  Conn The iSCSI connection.
643 
644 **/
645 VOID
646 IScsiDetatchConnection (
647   IN OUT ISCSI_CONNECTION  *Conn
648   );
649 
650 /**
651   This function performs the iSCSI connection login.
652 
653   @param[in, out]  Conn      The iSCSI connection to login.
654   @param           Timeout   The timeout value in milliseconds.
655 
656   @retval EFI_SUCCESS        The iSCSI connection is logged into the iSCSI target.
657   @retval EFI_TIMEOUT        Timeout occurred during the login procedure.
658   @retval Others             Other errors as indicated.
659 
660 **/
661 EFI_STATUS
662 IScsiConnLogin (
663   IN OUT ISCSI_CONNECTION    *Conn,
664   IN     UINT16              Timeout
665   );
666 
667 /**
668   Create a TCP connection for the iSCSI session.
669 
670   @param[in]  Session Points to the iSCSI session.
671 
672   @return The newly created iSCSI connection.
673 
674 **/
675 ISCSI_CONNECTION *
676 IScsiCreateConnection (
677   IN ISCSI_SESSION      *Session
678   );
679 
680 /**
681   Destroy an iSCSI connection.
682 
683   @param[in]  Conn The connection to destroy.
684 
685 **/
686 VOID
687 IScsiDestroyConnection (
688   IN ISCSI_CONNECTION  *Conn
689   );
690 
691 /**
692   Login the iSCSI session.
693 
694   @param[in]  Session           The iSCSI session
695 
696   @retval EFI_SUCCESS           The iSCSI session login procedure finished.
697   @retval EFI_OUT_OF_RESOURCES  Failed to allocate memory.
698   @retval EFI_NO_MEDIA          There was a media error.
699   @retval Others                Other errors as indicated.
700 
701 **/
702 EFI_STATUS
703 IScsiSessionLogin (
704   IN ISCSI_SESSION  *Session
705   );
706 
707 /**
708   Wait for IPsec negotiation, then try to login the iSCSI session again.
709 
710   @param[in]  Session           The iSCSI session
711 
712   @retval EFI_SUCCESS           The iSCSI session login procedure finished.
713   @retval EFI_OUT_OF_RESOURCES  Failed to allocate memory.
714   @retval EFI_PROTOCOL_ERROR    Some kind of iSCSI protocol error happened.
715 
716 **/
717 EFI_STATUS
718 IScsiSessionReLogin (
719   IN ISCSI_SESSION  *Session
720   );
721 
722 /**
723   Build and send the iSCSI login request to the iSCSI target according to
724   the current login stage.
725 
726   @param[in]  Conn             The connection in the iSCSI login phase.
727 
728   @retval EFI_SUCCESS          The iSCSI login request PDU is built and sent on this
729                                connection.
730   @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
731   @retval EFI_DEVICE_ERROR     Some kind of device error happened.
732 
733 **/
734 EFI_STATUS
735 IScsiSendLoginReq (
736   IN ISCSI_CONNECTION  *Conn
737   );
738 
739 /**
740   Receive and process the iSCSI login response.
741 
742   @param[in]  Conn             The connection in the iSCSI login phase.
743 
744   @retval EFI_SUCCESS          The iSCSI login response PDU is received and processed.
745   @retval Others               Other errors as indicated.
746 
747 **/
748 EFI_STATUS
749 IScsiReceiveLoginRsp (
750   IN ISCSI_CONNECTION  *Conn
751   );
752 
753 /**
754   Add an iSCSI key-value pair as a string into the data segment of the Login Request PDU.
755   The DataSegmentLength and the actual size of the net buffer containing this PDU will be
756   updated.
757 
758   @param[in, out]  Pdu         The iSCSI PDU whose data segment the key-value pair will
759                                be added to.
760   @param[in]       Key         The key name string.
761   @param[in]       Value       The value string.
762 
763   @retval EFI_SUCCESS          The key-valu pair is added to the PDU's datasegment and
764                                the correspondence length fields are updated.
765   @retval EFI_OUT_OF_RESOURCES There is not enough space in the PDU to add the key-value
766                                pair.
767 **/
768 EFI_STATUS
769 IScsiAddKeyValuePair (
770   IN OUT NET_BUF      *Pdu,
771   IN CHAR8            *Key,
772   IN CHAR8            *Value
773   );
774 
775 /**
776   Prepare the iSCSI login request to be sent according to the current login status.
777 
778   @param[in, out]  Conn The connection in the iSCSI login phase.
779 
780   @return The pointer to the net buffer containing the iSCSI login request built.
781   @retval NULL     Other errors as indicated.
782 
783 **/
784 NET_BUF *
785 IScsiPrepareLoginReq (
786   IN OUT ISCSI_CONNECTION  *Conn
787   );
788 
789 /**
790   Process the iSCSI Login Response.
791 
792   @param[in, out]  Conn The connection on which the iSCSI login response is received.
793   @param[in, out]  Pdu  The iSCSI login response PDU.
794 
795   @retval EFI_SUCCESS        The iSCSI login response PDU is processed and all check are passed.
796   @retval EFI_PROTOCOL_ERROR Some kind of iSCSI protocol error happened.
797   @retval EFI_MEDIA_CHANGED  Target is redirected.
798   @retval Others             Other errors as indicated.
799 
800 **/
801 EFI_STATUS
802 IScsiProcessLoginRsp (
803   IN OUT ISCSI_CONNECTION  *Conn,
804   IN OUT NET_BUF           *Pdu
805   );
806 
807 /**
808   Updated the target information according the data received in the iSCSI
809   login response with an target redirection status.
810 
811   @param[in, out] Session      The iSCSI session.
812   @param[in]      Data         The data segment which should contain the
813                                TargetAddress key-value list.
814   @param[in]      Len          Length of the data.
815 
816   @retval EFI_SUCCESS          The target address is updated.
817   @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
818   @retval EFI_NOT_FOUND        The TargetAddress key is not found.
819   @retval Others               Other errors as indicated.
820 
821 **/
822 EFI_STATUS
823 IScsiUpdateTargetAddress (
824   IN OUT ISCSI_SESSION         *Session,
825   IN     CHAR8                 *Data,
826   IN     UINT32                Len
827   );
828 
829 /**
830   The callback function to free the net buffer list.
831 
832   @param[in]  Arg The opaque parameter.
833 
834 **/
835 VOID
836 EFIAPI
837 IScsiFreeNbufList (
838   VOID *Arg
839   );
840 
841 /**
842   Receive an iSCSI response PDU. An iSCSI response PDU contains an iSCSI PDU header and
843   an optional data segment. The two parts will be put into two blocks of buffers in the
844   net buffer. The digest check will be conducted in this function if needed and the digests
845   will be trimmed from the PDU buffer.
846 
847   @param[in]  Conn         The iSCSI connection to receive data from.
848   @param[out] Pdu          The received iSCSI pdu.
849   @param[in]  Context      The context used to describe information on the caller provided
850                            buffer to receive data segment of the iSCSI pdu, it's optional.
851   @param[in]  HeaderDigest Whether there will be header digest received.
852   @param[in]  DataDigest   Whether there will be data digest.
853   @param[in]  TimeoutEvent The timeout event, it's optional.
854 
855   @retval EFI_SUCCESS          An iSCSI pdu is received.
856   @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
857   @retval EFI_PROTOCOL_ERROR   Some kind of iSCSI protocol error occurred.
858   @retval Others               Other errors as indicated.
859 
860 **/
861 EFI_STATUS
862 IScsiReceivePdu (
863   IN ISCSI_CONNECTION                      *Conn,
864   OUT NET_BUF                              **Pdu,
865   IN ISCSI_IN_BUFFER_CONTEXT               *Context, OPTIONAL
866   IN BOOLEAN                               HeaderDigest,
867   IN BOOLEAN                               DataDigest,
868   IN EFI_EVENT                             TimeoutEvent OPTIONAL
869   );
870 
871 /**
872   Check and get the result of the parameter negotiation.
873 
874   @param[in, out]  Conn          The connection in iSCSI login.
875 
876   @retval EFI_SUCCESS          The parmeter check is passed and negotiation is finished.
877   @retval EFI_PROTOCOL_ERROR   Some kind of iSCSI protocol error occurred.
878   @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
879 
880 **/
881 EFI_STATUS
882 IScsiCheckOpParams (
883   IN OUT ISCSI_CONNECTION  *Conn
884   );
885 
886 /**
887   Fill the operational parameters.
888 
889   @param[in]       Conn    The connection in iSCSI login.
890   @param[in, out]  Pdu     The iSCSI login request PDU to fill the parameters.
891 
892 **/
893 VOID
894 IScsiFillOpParams (
895   IN     ISCSI_CONNECTION  *Conn,
896   IN OUT NET_BUF           *Pdu
897   );
898 
899 /**
900   Pad the iSCSI AHS or data segment to an integer number of 4 byte words.
901 
902   @param[in, out]  Pdu         The iSCSI pdu which contains segments to pad.
903   @param[in]       Len         The length of the last semgnet in the PDU.
904 
905   @retval EFI_SUCCESS          The segment is padded or no need to pad it.
906   @retval EFI_OUT_OF_RESOURCES There is not enough remaining free space to add the
907                                padding bytes.
908 **/
909 EFI_STATUS
910 IScsiPadSegment (
911   IN OUT NET_BUF      *Pdu,
912   IN     UINT32       Len
913   );
914 
915 /**
916   Build a key-value list from the data segment.
917 
918   @param[in]  Data The data segment containing the key-value pairs.
919   @param[in]  Len  Length of the data segment.
920 
921   @return The key-value list.
922   @retval NULL Other errors as indicated.
923 
924 **/
925 LIST_ENTRY *
926 IScsiBuildKeyValueList (
927   IN CHAR8  *Data,
928   IN UINT32 Len
929   );
930 
931 /**
932   Get the value string by the key name from the key-value list. If found,
933   the key-value entry will be removed from the list.
934 
935   @param[in, out]  KeyValueList  The key-value list.
936   @param[in]       Key           The key name to find.
937 
938   @return The value string.
939   @retval NULL The key value pair can not be found.
940 
941 **/
942 CHAR8 *
943 IScsiGetValueByKeyFromList (
944   IN OUT LIST_ENTRY     *KeyValueList,
945   IN     CHAR8          *Key
946   );
947 
948 /**
949   Free the key-value list.
950 
951   @param[in]  KeyValueList The key-value list.
952 
953 **/
954 VOID
955 IScsiFreeKeyValueList (
956   IN LIST_ENTRY      *KeyValueList
957   );
958 
959 /**
960   Normalize the iSCSI name according to RFC.
961 
962   @param[in, out]  Name       The iSCSI name.
963   @param[in]       Len        length of the iSCSI name.
964 
965   @retval EFI_SUCCESS        The iSCSI name is valid and normalized.
966   @retval EFI_PROTOCOL_ERROR The iSCSI name is mal-formatted or not in the IQN format.
967 
968 **/
969 EFI_STATUS
970 IScsiNormalizeName (
971   IN OUT CHAR8      *Name,
972   IN     UINTN      Len
973   );
974 
975 /**
976   Execute the SCSI command issued through the EXT SCSI PASS THRU protocol.
977 
978   @param[in]       PassThru  The EXT SCSI PASS THRU protocol.
979   @param[in]       Target    The target ID.
980   @param[in]       Lun       The LUN.
981   @param[in, out]  Packet    The request packet containing IO request, SCSI command
982                              buffer and buffers to read/write.
983 
984   @retval EFI_SUCCES           The SCSI command is executed and the result is updated to
985                                the Packet.
986   @retval EFI_DEVICE_ERROR     Session state was not as required.
987   @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
988   @retval EFI_NOT_READY        The target can not accept new commands.
989   @retval Others               Other errors as indicated.
990 
991 **/
992 EFI_STATUS
993 IScsiExecuteScsiCommand (
994   IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL                 *PassThru,
995   IN UINT8                                           *Target,
996   IN UINT64                                          Lun,
997   IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *Packet
998   );
999 
1000 /**
1001   Reinstate the session on some error.
1002 
1003   @param[in]  Session           The iSCSI session
1004 
1005   @retval EFI_SUCCES            The session is reinstated from some error.
1006   @retval Other                 Reinstatement failed.
1007 
1008 **/
1009 EFI_STATUS
1010 IScsiSessionReinstatement (
1011   IN ISCSI_SESSION  *Session
1012   );
1013 
1014 /**
1015   Initialize some session parameters before login.
1016 
1017   @param[in, out]  Session  The iSCSI session.
1018   @param[in]       Recovery Whether the request is from a fresh new start or recovery.
1019 
1020 **/
1021 VOID
1022 IScsiSessionInit (
1023   IN OUT ISCSI_SESSION  *Session,
1024   IN BOOLEAN            Recovery
1025   );
1026 
1027 /**
1028   Abort the iSCSI session, that is, reset all the connection and free the
1029   resources.
1030 
1031   @param[in, out]  Session The iSCSI session.
1032 
1033 **/
1034 VOID
1035 IScsiSessionAbort (
1036   IN OUT ISCSI_SESSION  *Session
1037   );
1038 
1039 #endif
1040