[ipxe-devel] [PATCH 1/3] scsi: Improve sense code parsing
Hannes Reinecke
hare at suse.de
Fri May 30 07:18:16 UTC 2014
The SCSI sense code comes in two flavours, 'fixed' and 'descriptor'.
Each of which have the interesting portions like additonal sense code
etc at different locations.
So instead of blindly copying out some bytes we should parse the
sense code buffer and make sure to return the correct values.
Signed-off-by: Hannes Reinecke <hare at suse.de>
---
src/drivers/block/scsi.c | 35 +++++++++++++++++++++++++++++++++--
src/drivers/block/srp.c | 2 +-
src/include/ipxe/scsi.h | 9 +++++----
src/net/fcp.c | 4 ++--
src/net/tcp/iscsi.c | 5 ++---
5 files changed, 43 insertions(+), 12 deletions(-)
diff --git a/src/drivers/block/scsi.c b/src/drivers/block/scsi.c
index 4245f01..79f4365 100644
--- a/src/drivers/block/scsi.c
+++ b/src/drivers/block/scsi.c
@@ -132,6 +132,37 @@ int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun ) {
return 0;
}
+/**
+ * Parse SCSI Sense code
+ *
+ * @v buffer buffer holding the sense code
+ * @v sense Sense code structure to fill in
+ * @ret rc Return status code
+ */
+int scsi_parse_sense( const char *buffer, struct scsi_sns *sense )
+{
+ sense->code = buffer[0] & 0x7f;
+ sense->key = 0;
+ sense->asc = 0;
+ sense->ascq = 0;
+
+ if ((buffer[0] & 0x72) == 0x70) {
+ /* Fixed format sense */
+ sense->key = buffer[2] & SCSI_SENSE_KEY_MASK;
+ if (buffer[7] > 7) {
+ sense->asc = buffer[12];
+ sense->ascq = buffer[13];
+ }
+ } else if ((buffer[0] & 0x72) == 0x72) {
+ /* Descriptor format */
+ sense->key = buffer[1] & SCSI_SENSE_KEY_MASK;
+ sense->asc = buffer[2];
+ sense->ascq = buffer[3];
+ } else
+ return -EINVAL;
+
+ return 0;
+}
/******************************************************************************
*
* Interface methods
@@ -468,9 +499,9 @@ static void scsicmd_response ( struct scsi_command *scsicmd,
underrun = -(response->overrun);
DBGC ( scsidev, " underrun -%zd", underrun );
}
- DBGC ( scsidev, " sense %02x:%02x:%08x\n",
+ DBGC ( scsidev, " sense %02x:%02x:%02x:%02x\n",
response->sense.code, response->sense.key,
- ntohl ( response->sense.info ) );
+ response->sense.asc, response->sense.ascq );
/* Construct error number from sense data */
rc = -EIO_SENSE ( response->sense.key & SCSI_SENSE_KEY_MASK );
diff --git a/src/drivers/block/srp.c b/src/drivers/block/srp.c
index 70a97b2..fd8da27 100644
--- a/src/drivers/block/srp.c
+++ b/src/drivers/block/srp.c
@@ -525,7 +525,7 @@ static int srp_rsp ( struct srp_device *srpdev,
}
sense = srp_rsp_sense_data ( rsp );
if ( sense )
- memcpy ( &response.sense, sense, sizeof ( response.sense ) );
+ scsi_parse_sense(sense, &response.sense );
/* Report SCSI response */
scsi_response ( &srpcmd->scsi, &response );
diff --git a/src/include/ipxe/scsi.h b/src/include/ipxe/scsi.h
index 6dfb7f1..87bd067 100644
--- a/src/include/ipxe/scsi.h
+++ b/src/include/ipxe/scsi.h
@@ -271,12 +271,12 @@ struct scsi_cmd {
struct scsi_sns {
/** Response code */
uint8_t code;
- /** Reserved */
- uint8_t reserved;
/** Sense key */
uint8_t key;
- /** Information */
- uint32_t info;
+ /** Additional sense code */
+ uint8_t asc;
+ /** Additional sense code qualifier */
+ uint8_t ascq;
};
/** SCSI sense key mask */
@@ -293,6 +293,7 @@ struct scsi_rsp {
};
extern int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun );
+extern int scsi_parse_sense ( const char *buffer, struct scsi_sns *sense );
extern int scsi_command ( struct interface *control, struct interface *data,
struct scsi_cmd *command );
diff --git a/src/net/fcp.c b/src/net/fcp.c
index 241b546..838cf44 100644
--- a/src/net/fcp.c
+++ b/src/net/fcp.c
@@ -551,7 +551,7 @@ static int fcpcmd_recv_rsp ( struct fcp_command *fcpcmd,
struct fcp_device *fcpdev = fcpcmd->fcpdev;
struct scsi_cmd *command = &fcpcmd->command;
struct fcp_rsp *rsp = iobuf->data;
- struct scsi_sense *sense;
+ void *sense;
struct scsi_rsp response;
int rc;
@@ -608,7 +608,7 @@ static int fcpcmd_recv_rsp ( struct fcp_command *fcpcmd,
response.overrun = -response.overrun;
}
if ( ( sense = fcp_rsp_sense_data ( rsp ) ) != NULL )
- memcpy ( &response.sense, sense, sizeof ( response.sense ) );
+ scsi_parse_sense( sense, &response.sense );
/* Free buffer before sending response, to minimise
* out-of-memory errors.
diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c
index a6fcd25..00d973c 100644
--- a/src/net/tcp/iscsi.c
+++ b/src/net/tcp/iscsi.c
@@ -416,7 +416,7 @@ static int iscsi_rx_scsi_response ( struct iscsi_session *iscsi,
/* Buffer up the PDU data */
if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
- DBGC ( iscsi, "iSCSI %p could not buffer login response: %s\n",
+ DBGC ( iscsi, "iSCSI %p could not buffer scsi response: %s\n",
iscsi, strerror ( rc ) );
return rc;
}
@@ -433,8 +433,7 @@ static int iscsi_rx_scsi_response ( struct iscsi_session *iscsi,
rsp.overrun = -(residual_count);
}
if ( ISCSI_DATA_LEN ( response->lengths ) )
- memcpy ( &rsp.sense, ( iscsi->rx_buffer + 2 ),
- sizeof ( rsp.sense ) );
+ scsi_parse_sense(iscsi->rx_buffer + 2, &rsp.sense);
iscsi_rx_buffered_data_done ( iscsi );
/* Check for errors */
--
1.8.4.5
More information about the ipxe-devel
mailing list