12 #include <gpxe/async.h>
13 #include <gpxe/scsi.h>
14 #include <gpxe/chap.h>
16 /** Default iSCSI port */
17 #define ISCSI_PORT 3260
20 * iSCSI segment lengths
22 * iSCSI uses an icky structure with one one-byte field (a dword
23 * count) and one three-byte field (a byte count). This structure,
24 * and the accompanying macros, relieve some of the pain.
26 union iscsi_segment_lengths {
28 /** The AHS length (measured in dwords) */
30 /** The data length (measured in bytes), in network
35 /** Ths data length (measured in bytes), in network byte
36 * order, with ahs_len as the first byte.
38 uint32_t ahs_and_data_len;
41 /** The length of the additional header segment, in dwords */
42 #define ISCSI_AHS_LEN( segment_lengths ) \
43 ( (segment_lengths).bytes.ahs_len )
45 /** The length of the data segment, in bytes, excluding any padding */
46 #define ISCSI_DATA_LEN( segment_lengths ) \
47 ( ntohl ( (segment_lengths).ahs_and_data_len ) & 0xffffff )
49 /** The padding of the data segment, in bytes */
50 #define ISCSI_DATA_PAD_LEN( segment_lengths ) \
51 ( ( 0 - (segment_lengths).bytes.data_len[2] ) & 0x03 )
53 /** Set additional header and data segment lengths */
54 #define ISCSI_SET_LENGTHS( segment_lengths, ahs_len, data_len ) do { \
55 (segment_lengths).ahs_and_data_len = \
56 htonl ( data_len | ( ahs_len << 24 ) ); \
60 * iSCSI basic header segment common fields
63 struct iscsi_bhs_common {
68 /** Fields specific to the PDU type */
70 /** Segment lengths */
71 union iscsi_segment_lengths lengths;
72 /** Fields specific to the PDU type */
74 /** Initiator Task Tag */
76 /** Fields specific to the PDU type */
81 #define ISCSI_OPCODE_MASK 0x3f
83 /** Immediate delivery */
84 #define ISCSI_FLAG_IMMEDIATE 0x40
86 /** Final PDU of a sequence */
87 #define ISCSI_FLAG_FINAL 0x80
90 * iSCSI basic header segment common request fields
93 struct iscsi_bhs_common_response {
98 /** Fields specific to the PDU type */
100 /** Segment lengths */
101 union iscsi_segment_lengths lengths;
102 /** Fields specific to the PDU type */
104 /** Initiator Task Tag */
106 /** Fields specific to the PDU type */
108 /** Status sequence number */
110 /** Expected command sequence number */
112 /** Fields specific to the PDU type */
117 * iSCSI login request basic header segment
120 struct iscsi_bhs_login_request {
125 /** Maximum supported version number */
127 /** Minimum supported version number */
129 /** Segment lengths */
130 union iscsi_segment_lengths lengths;
131 /** Initiator session ID (IANA format) enterprise number and flags */
132 uint32_t isid_iana_en;
133 /** Initiator session ID (IANA format) qualifier */
134 uint16_t isid_iana_qual;
135 /** Target session identifying handle */
137 /** Initiator Task Tag */
143 /** Command sequence number */
145 /** Expected status sequence number */
148 uint8_t reserved_b[16];
151 /** Login request opcode */
152 #define ISCSI_OPCODE_LOGIN_REQUEST 0x03
154 /** Willingness to transition to next stage */
155 #define ISCSI_LOGIN_FLAG_TRANSITION 0x80
157 /** Key=value pairs continued in subsequent request */
158 #define ISCSI_LOGIN_FLAG_CONTINUE 0x40
160 /* Current stage values and mask */
161 #define ISCSI_LOGIN_CSG_MASK 0x0c
162 #define ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION 0x00
163 #define ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION 0x04
164 #define ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE 0x0c
166 /* Next stage values and mask */
167 #define ISCSI_LOGIN_NSG_MASK 0x03
168 #define ISCSI_LOGIN_NSG_SECURITY_NEGOTIATION 0x00
169 #define ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION 0x01
170 #define ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE 0x03
172 /** ISID IANA format marker */
173 #define ISCSI_ISID_IANA 0x40000000
175 /** Fen Systems Ltd. IANA enterprise number
177 * Permission is hereby granted to use Fen Systems Ltd.'s IANA
178 * enterprise number with this iSCSI implementation.
180 #define IANA_EN_FEN_SYSTEMS 10019
183 * iSCSI login response basic header segment
186 struct iscsi_bhs_login_response {
191 /** Maximum supported version number */
193 /** Minimum supported version number */
195 /** Segment lengths */
196 union iscsi_segment_lengths lengths;
197 /** Initiator session ID (IANA format) enterprise number and flags */
198 uint32_t isid_iana_en;
199 /** Initiator session ID (IANA format) qualifier */
200 uint16_t isid_iana_qual;
201 /** Target session identifying handle */
203 /** Initiator Task Tag */
207 /** Status sequence number */
209 /** Expected command sequence number */
211 /** Maximum command sequence number */
214 uint8_t status_class;
216 uint8_t status_detail;
218 uint8_t reserved_b[10];
221 /** Login response opcode */
222 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
224 /* Login response status codes */
225 #define ISCSI_STATUS_SUCCESS 0x00
226 #define ISCSI_STATUS_REDIRECT 0x01
227 #define ISCSI_STATUS_INITIATOR_ERROR 0x02
228 #define ISCSI_STATUS_TARGET_ERROR 0x03
231 * iSCSI SCSI command basic header segment
234 struct iscsi_bhs_scsi_command {
241 /** Segment lengths */
242 union iscsi_segment_lengths lengths;
243 /** SCSI Logical Unit Number */
245 /** Initiator Task Tag */
247 /** Expected data transfer length */
249 /** Command sequence number */
251 /** Expected status sequence number */
253 /** SCSI Command Descriptor Block (CDB) */
257 /** SCSI command opcode */
258 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
260 /** Command will read data */
261 #define ISCSI_COMMAND_FLAG_READ 0x40
263 /** Command will write data */
264 #define ISCSI_COMMAND_FLAG_WRITE 0x20
266 /* Task attributes */
267 #define ISCSI_COMMAND_ATTR_UNTAGGED 0x00
268 #define ISCSI_COMMAND_ATTR_SIMPLE 0x01
269 #define ISCSI_COMMAND_ATTR_ORDERED 0x02
270 #define ISCSI_COMMAND_ATTR_HEAD_OF_QUEUE 0x03
271 #define ISCSI_COMMAND_ATTR_ACA 0x04
274 * iSCSI SCSI response basic header segment
277 struct iscsi_bhs_scsi_response {
284 /** SCSI status code */
286 /** Segment lengths */
287 union iscsi_segment_lengths lengths;
289 uint8_t reserved_a[8];
290 /** Initiator Task Tag */
294 /** Status sequence number */
296 /** Expected command sequence number */
298 /** Maximum command sequence number */
300 /** Expected data sequence number */
303 uint8_t reserved_b[8];
306 /** SCSI response opcode */
307 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
309 /** SCSI command completed at target */
310 #define ISCSI_RESPONSE_COMMAND_COMPLETE 0x00
312 /** SCSI target failure */
313 #define ISCSI_RESPONSE_TARGET_FAILURE 0x01
315 /** SCSI sense response code offset
317 * The SCSI response may contain unsolicited sense data in the data
318 * segment. If it does, this is the offset to the sense response code
319 * byte, which is the only byte we care about.
321 #define ISCSI_SENSE_RESPONSE_CODE_OFFSET 2
324 * iSCSI data-in basic header segment
327 struct iscsi_bhs_data_in {
334 /** SCSI status code */
336 /** Segment lengths */
337 union iscsi_segment_lengths lengths;
338 /** Logical Unit Number */
340 /** Initiator Task Tag */
342 /** Target Transfer Tag */
344 /** Status sequence number */
346 /** Expected command sequence number */
348 /** Maximum command sequence number */
350 /** Data sequence number */
354 /** Residual count */
355 uint32_t residual_count;
358 /** Data-in opcode */
359 #define ISCSI_OPCODE_DATA_IN 0x25
361 /** Data requires acknowledgement */
362 #define ISCSI_DATA_FLAG_ACKNOWLEDGE 0x40
364 /** Data overflow occurred */
365 #define ISCSI_DATA_FLAG_OVERFLOW 0x04
367 /** Data underflow occurred */
368 #define ISCSI_DATA_FLAG_UNDERFLOW 0x02
370 /** SCSI status code and overflow/underflow flags are valid */
371 #define ISCSI_DATA_FLAG_STATUS 0x01
374 * iSCSI data-out basic header segment
377 struct iscsi_bhs_data_out {
384 /** Segment lengths */
385 union iscsi_segment_lengths lengths;
386 /** Logical Unit Number */
388 /** Initiator Task Tag */
390 /** Target Transfer Tag */
394 /** Expected status sequence number */
398 /** Data sequence number */
406 /** Data-out opcode */
407 #define ISCSI_OPCODE_DATA_OUT 0x05
410 * iSCSI request to transfer basic header segment
413 struct iscsi_bhs_r2t {
420 /** Segment lengths */
421 union iscsi_segment_lengths lengths;
422 /** Logical Unit Number */
424 /** Initiator Task Tag */
426 /** Target Transfer Tag */
428 /** Status sequence number */
430 /** Expected command sequence number */
432 /** Maximum command sequence number */
434 /** R2T sequence number */
438 /** Desired data transfer length */
443 #define ISCSI_OPCODE_R2T 0x31
446 * An iSCSI basic header segment
449 struct iscsi_bhs_common common;
450 struct iscsi_bhs_common_response common_response;
451 struct iscsi_bhs_login_request login_request;
452 struct iscsi_bhs_login_response login_response;
453 struct iscsi_bhs_scsi_command scsi_command;
454 struct iscsi_bhs_scsi_response scsi_response;
455 struct iscsi_bhs_data_in data_in;
456 struct iscsi_bhs_data_out data_out;
457 struct iscsi_bhs_r2t r2t;
458 unsigned char bytes[ sizeof ( struct iscsi_bhs_common ) ];
461 /** State of an iSCSI TX engine */
462 enum iscsi_tx_state {
463 /** Nothing to send */
465 /** Sending the basic header segment */
467 /** Sending the additional header segment */
469 /** Sending the data segment */
471 /** Sending the data segment padding */
472 ISCSI_TX_DATA_PADDING,
475 /** State of an iSCSI RX engine */
476 enum iscsi_rx_state {
477 /** Receiving the basic header segment */
479 /** Receiving the additional header segment */
481 /** Receiving the data segment */
483 /** Receiving the data segment padding */
484 ISCSI_RX_DATA_PADDING,
487 /** An iSCSI session */
488 struct iscsi_session {
489 /** TCP connection for this session */
490 struct tcp_connection tcp;
493 * This is the bitwise-OR of zero or more ISCSI_STATUS_XXX
497 /** Asynchronous operation for the current iSCSI operation */
498 struct async_operation aop;
501 * Number of times that the connection has been retried.
502 * Reset upon a successful connection.
507 const char *initiator_iqn;
510 * Kept separate from the TCP connection structure because we
511 * may need to handle login redirection.
513 struct sockaddr_tcpip target;
515 const char *target_iqn;
516 /** Logical Unit Number (LUN) */
520 const char *username;
522 const char *password;
523 /** CHAP challenge/response */
524 struct chap_challenge chap;
526 /** Target session identifying handle
528 * This is assigned by the target when we first log in, and
529 * must be reused on subsequent login attempts.
532 /** Initiator task tag
534 * This is the tag of the current command. It is incremented
535 * whenever a new command is started.
538 /** Target transfer tag
540 * This is the tag attached to a sequence of data-out PDUs in
541 * response to an R2T.
547 * This is the offset for an in-progress sequence of data-out
548 * PDUs in response to an R2T.
550 uint32_t transfer_offset;
554 * This is the length for an in-progress sequence of data-out
555 * PDUs in response to an R2T.
557 uint32_t transfer_len;
558 /** Command sequence number
560 * This is the sequence number of the current command, used to
561 * fill out the CmdSN field in iSCSI request PDUs. It is
562 * updated with the value of the ExpCmdSN field whenever we
563 * receive an iSCSI response PDU containing such a field.
566 /** Status sequence number
568 * This is the most recent status sequence number present in
569 * the StatSN field of an iSCSI response PDU containing such a
570 * field. Whenever we send an iSCSI request PDU, we fill out
571 * the ExpStatSN field with this value plus one.
575 /** Basic header segment for current TX PDU */
576 union iscsi_bhs tx_bhs;
577 /** State of the TX engine */
578 enum iscsi_tx_state tx_state;
579 /** Byte offset within the current TX state */
581 /** Length of the current TX state */
584 /** Basic header segment for current RX PDU */
585 union iscsi_bhs rx_bhs;
586 /** State of the RX engine */
587 enum iscsi_rx_state rx_state;
588 /** Byte offset within the current RX state */
590 /** Length of the current RX state */
592 /** Buffer for received data (not always used) */
595 /** Current SCSI command
597 * Set to NULL when command is complete.
599 struct scsi_command *command;
602 /** iSCSI session is currently in the security negotiation phase */
603 #define ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE \
604 ( ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION | \
605 ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION )
607 /** iSCSI session is currently in the operational parameter
610 #define ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE \
611 ( ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION | \
612 ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE )
614 /** iSCSI session is currently in the full feature phase */
615 #define ISCSI_STATUS_FULL_FEATURE_PHASE ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE
617 /** Mask for all iSCSI session phases */
618 #define ISCSI_STATUS_PHASE_MASK ( ISCSI_LOGIN_CSG_MASK | ISCSI_LOGIN_NSG_MASK )
620 /** iSCSI session needs to send the initial security negotiation strings */
621 #define ISCSI_STATUS_STRINGS_SECURITY 0x0100
623 /** iSCSI session needs to send the CHAP_A string */
624 #define ISCSI_STATUS_STRINGS_CHAP_ALGORITHM 0x0200
626 /** iSCSI session needs to send the CHAP response */
627 #define ISCSI_STATUS_STRINGS_CHAP_RESPONSE 0x0400
629 /** iSCSI session needs to send the operational negotiation strings */
630 #define ISCSI_STATUS_STRINGS_OPERATIONAL 0x0800
632 /** Mask for all iSCSI "needs to send" flags */
633 #define ISCSI_STATUS_STRINGS_MASK 0xff00
635 /** iSCSI session is closing down */
636 #define ISCSI_STATUS_CLOSING 0x00010000
638 /** Maximum number of retries at connecting */
639 #define ISCSI_MAX_RETRIES 2
641 extern struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
642 struct scsi_command *command );
643 extern struct async_operation * iscsi_shutdown ( struct iscsi_session *iscsi );
645 /** An iSCSI device */
646 struct iscsi_device {
647 /** SCSI device interface */
648 struct scsi_device scsi;
649 /** iSCSI protocol instance */
650 struct iscsi_session iscsi;
653 extern int init_iscsidev ( struct iscsi_device *iscsidev );
654 extern void fini_iscsidev ( struct iscsi_device *iscsidev );
656 #endif /* _GPXE_ISCSI_H */