@@ -686,6 +686,32 @@ static int sd_sec_submit(void *data, u16 spsp, u8 secp, void *buffer,
&exec_args);
return ret <= 0 ? ret : -EIO;
}
+
+static int sd_ata12_submit(void *data, u16 spsp, u8 secp, void *buffer,
+ size_t len, bool send)
+{
+ struct scsi_disk *sdkp = data;
+ struct scsi_device *sdev = sdkp->device;
+ u8 cdb[12] = { 0, };
+ const struct scsi_exec_args exec_args = {
+ .req_flags = BLK_MQ_REQ_PM,
+ };
+ int ret;
+
+ cdb[0] = ATA_12;
+ cdb[1] = (send ? 5 /* ATA_PROTOCOL_PIO_DATA_IN */ : 4 /* ATA_PROTOCOL_PIO_DATA_OUT */) << 1;
+ cdb[2] = 2 /* t_length */ | (1 << 2) /* byt_blok */ | ((send ? 0 : 1) << 3) /* t_dir */;
+ cdb[3] = secp;
+ put_unaligned_le16(len / 512, &cdb[4]);
+ put_unaligned_le16(spsp, &cdb[6]);
+ cdb[9] = send ? 0x5e /* ATA_CMD_TRUSTED_SND */: 0x5c /* ATA_CMD_TRUSTED_RCV */;
+
+ ret = scsi_execute_cmd(sdev, cdb, send ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
+ buffer, len, SD_TIMEOUT, sdkp->max_retries,
+ &exec_args);
+ return ret <= 0 ? ret : -EIO;
+}
+
#endif /* CONFIG_BLK_SED_OPAL */
/*
@@ -3699,8 +3725,11 @@ static int sd_probe(struct device *dev)
goto out;
}
- if (sdkp->security) {
- sdkp->opal_dev = init_opal_dev(sdkp, &sd_sec_submit);
+ if (sdp->security_supported) {
+ if (sdkp->security)
+ sdkp->opal_dev = init_opal_dev(sdkp, &sd_sec_submit);
+ else
+ sdkp->opal_dev = init_opal_dev(sdkp, &sd_ata12_submit);
if (sdkp->opal_dev)
sd_printk(KERN_NOTICE, sdkp, "supports TCG Opal\n");
}
@@ -209,6 +209,10 @@ static int slave_configure(struct scsi_device *sdev)
/* Do not attempt to use WRITE SAME */
sdev->no_write_same = 1;
+ /* Allow security commands (OPAL) passthrough */
+ if (!(us->fflags & US_FL_IGNORE_OPAL))
+ sdev->security_supported = 1;
+
/*
* Some disks return the total number of blocks in response
* to READ CAPACITY rather than the highest block number.
@@ -865,6 +865,11 @@ static int uas_slave_configure(struct scsi_device *sdev)
/* Some disks cannot handle WRITE_SAME */
if (devinfo->flags & US_FL_NO_SAME)
sdev->no_write_same = 1;
+
+ /* Allow security commands (OPAL) passthrough */
+ if (!(devinfo->flags & US_FL_IGNORE_OPAL))
+ sdev->security_supported = 1;
+
/*
* Some disks return the total number of blocks in response
* to READ CAPACITY rather than the highest block number.
@@ -478,7 +478,7 @@ void usb_stor_adjust_quirks(struct usb_device *udev, u64 *fflags)
US_FL_INITIAL_READ10 | US_FL_WRITE_CACHE |
US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES |
US_FL_MAX_SECTORS_240 | US_FL_NO_REPORT_LUNS |
- US_FL_ALWAYS_SYNC);
+ US_FL_ALWAYS_SYNC | US_FL_IGNORE_OPAL);
p = quirks;
while (*p) {
@@ -567,6 +567,9 @@ void usb_stor_adjust_quirks(struct usb_device *udev, u64 *fflags)
case 'y':
f |= US_FL_ALWAYS_SYNC;
break;
+ case 'z':
+ f |= US_FL_IGNORE_OPAL;
+ break;
/* Ignore unrecognized flag characters */
}
}
@@ -88,6 +88,8 @@
/* Cannot handle WRITE_SAME */ \
US_FLAG(SENSE_AFTER_SYNC, 0x80000000) \
/* Do REQUEST_SENSE after SYNCHRONIZE_CACHE */ \
+ US_FLAG(IGNORE_OPAL, 0x100000000) \
+ /* Security commands (OPAL) are broken */ \
#define US_FLAG(name, value) US_FL_##name = value ,
enum { US_DO_ALL_FLAGS };
This patch enables pass-through OPAL command for USB-attached storage (which does not support UAS or SCSI security commands). All common USB/SATA or USB/NVMe adapters I tested need this patch. USB mass storage devices that do not support SECURITY IN/OUT SCSI commands can support ATA12 pass-thru command. Internal kernel implementation for OPAL interface currently supports only SCSI SECURITY IN/OUT wrapper. USB mass storage also turns off SCSI command enumeration, so SECURITY IN/OUT in the SCSI layer will be disabled. Note: sedutils and some other OPAL tools already use ATA-12 pass-thru. This patch - enables SCSI security flag for USB mass storage and UAS device by default. - adds an optional wrapper to the SCSI layer for the ATA-12 pass-thru command as an alternative if SECURITY IN/OUT is unavailable. In short, the patch runs these steps: 1) USB drives (mass-storage, UAS) enables security driver flag by default if not disabled by quirk 2) SCSI device enumerates SECURITY IN/OUT support. If detected, SECURITY ON/OUT wrapper is used (as in the current code). If not, new ATA12 pass-thru wrapper is used instead. 3) SED OPAL code tries OPAL discovery command for device. If it receives correct reply, OPAL is enabled for the device. With the changes above, the TCG OPAL support works with USB adapters that support the ATA-12 command. As kernel OPAL code runs discover commands on initialization, on devices that do not support pass-through, OPAL remains disabled. The patch also adds a quirk flag to disable security commands for particular devices if firmware is buggy. Signed-off-by: Milan Broz <gmazyland@gmail.com> --- drivers/scsi/sd.c | 33 +++++++++++++++++++++++++++++++-- drivers/usb/storage/scsiglue.c | 4 ++++ drivers/usb/storage/uas.c | 5 +++++ drivers/usb/storage/usb.c | 5 ++++- include/linux/usb_usual.h | 2 ++ 5 files changed, 46 insertions(+), 3 deletions(-)