Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libata: implement SECURITY PROTOCOL IN/OUT

This allows us to use the generic OPAL code with ATA devices.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

Christoph Hellwig and committed by
Tejun Heo
818831c8 a0fd2454

+110
+32
drivers/ata/libata-core.c
··· 2405 2405 } 2406 2406 } 2407 2407 2408 + static void ata_dev_config_trusted(struct ata_device *dev) 2409 + { 2410 + struct ata_port *ap = dev->link->ap; 2411 + u64 trusted_cap; 2412 + unsigned int err; 2413 + 2414 + if (!ata_identify_page_supported(dev, ATA_LOG_SECURITY)) { 2415 + ata_dev_warn(dev, 2416 + "Security Log not supported\n"); 2417 + return; 2418 + } 2419 + 2420 + err = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, ATA_LOG_SECURITY, 2421 + ap->sector_buf, 1); 2422 + if (err) { 2423 + ata_dev_dbg(dev, 2424 + "failed to read Security Log, Emask 0x%x\n", err); 2425 + return; 2426 + } 2427 + 2428 + trusted_cap = get_unaligned_le64(&ap->sector_buf[40]); 2429 + if (!(trusted_cap & (1ULL << 63))) { 2430 + ata_dev_dbg(dev, 2431 + "Trusted Computing capability qword not valid!\n"); 2432 + return; 2433 + } 2434 + 2435 + if (trusted_cap & (1 << 0)) 2436 + dev->flags |= ATA_DFLAG_TRUSTED; 2437 + } 2438 + 2408 2439 /** 2409 2440 * ata_dev_configure - Configure the specified ATA/ATAPI device 2410 2441 * @dev: Target device to configure ··· 2660 2629 } 2661 2630 ata_dev_config_sense_reporting(dev); 2662 2631 ata_dev_config_zac(dev); 2632 + ata_dev_config_trusted(dev); 2663 2633 dev->cdb_len = 16; 2664 2634 } 2665 2635
+76
drivers/ata/libata-scsi.c
··· 3564 3564 dev->class == ATA_DEV_ZAC) 3565 3565 supported = 3; 3566 3566 break; 3567 + case SECURITY_PROTOCOL_IN: 3568 + case SECURITY_PROTOCOL_OUT: 3569 + if (dev->flags & ATA_DFLAG_TRUSTED) 3570 + supported = 3; 3571 + break; 3567 3572 default: 3568 3573 break; 3569 3574 } ··· 4073 4068 return 1; 4074 4069 } 4075 4070 4071 + static u8 ata_scsi_trusted_op(u32 len, bool send, bool dma) 4072 + { 4073 + if (len == 0) 4074 + return ATA_CMD_TRUSTED_NONDATA; 4075 + else if (send) 4076 + return dma ? ATA_CMD_TRUSTED_SND_DMA : ATA_CMD_TRUSTED_SND; 4077 + else 4078 + return dma ? ATA_CMD_TRUSTED_RCV_DMA : ATA_CMD_TRUSTED_RCV; 4079 + } 4080 + 4081 + static unsigned int ata_scsi_security_inout_xlat(struct ata_queued_cmd *qc) 4082 + { 4083 + struct scsi_cmnd *scmd = qc->scsicmd; 4084 + const u8 *cdb = scmd->cmnd; 4085 + struct ata_taskfile *tf = &qc->tf; 4086 + u8 secp = cdb[1]; 4087 + bool send = (cdb[0] == SECURITY_PROTOCOL_OUT); 4088 + u16 spsp = get_unaligned_be16(&cdb[2]); 4089 + u32 len = get_unaligned_be32(&cdb[6]); 4090 + bool dma = !(qc->dev->flags & ATA_DFLAG_PIO); 4091 + 4092 + /* 4093 + * We don't support the ATA "security" protocol. 4094 + */ 4095 + if (secp == 0xef) { 4096 + ata_scsi_set_invalid_field(qc->dev, scmd, 1, 0); 4097 + return 1; 4098 + } 4099 + 4100 + if (cdb[4] & 7) { /* INC_512 */ 4101 + if (len > 0xffff) { 4102 + ata_scsi_set_invalid_field(qc->dev, scmd, 6, 0); 4103 + return 1; 4104 + } 4105 + } else { 4106 + if (len > 0x01fffe00) { 4107 + ata_scsi_set_invalid_field(qc->dev, scmd, 6, 0); 4108 + return 1; 4109 + } 4110 + 4111 + /* convert to the sector-based ATA addressing */ 4112 + len = (len + 511) / 512; 4113 + } 4114 + 4115 + tf->protocol = dma ? ATA_PROT_DMA : ATA_PROT_PIO; 4116 + tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR | ATA_TFLAG_LBA; 4117 + if (send) 4118 + tf->flags |= ATA_TFLAG_WRITE; 4119 + tf->command = ata_scsi_trusted_op(len, send, dma); 4120 + tf->feature = secp; 4121 + tf->lbam = spsp & 0xff; 4122 + tf->lbah = spsp >> 8; 4123 + 4124 + if (len) { 4125 + tf->nsect = len & 0xff; 4126 + tf->lbal = len >> 8; 4127 + } else { 4128 + if (!send) 4129 + tf->lbah = (1 << 7); 4130 + } 4131 + 4132 + ata_qc_set_pc_nbytes(qc); 4133 + return 0; 4134 + } 4135 + 4076 4136 /** 4077 4137 * ata_get_xlat_func - check if SCSI to ATA translation is possible 4078 4138 * @dev: ATA device ··· 4188 4118 4189 4119 case ZBC_OUT: 4190 4120 return ata_scsi_zbc_out_xlat; 4121 + 4122 + case SECURITY_PROTOCOL_IN: 4123 + case SECURITY_PROTOCOL_OUT: 4124 + if (!(dev->flags & ATA_DFLAG_TRUSTED)) 4125 + break; 4126 + return ata_scsi_security_inout_xlat; 4191 4127 4192 4128 case START_STOP: 4193 4129 return ata_scsi_start_stop_xlat;
+1
include/linux/ata.h
··· 341 341 ATA_LOG_IDENTIFY_DEVICE = 0x30, 342 342 343 343 /* Identify device log pages: */ 344 + ATA_LOG_SECURITY = 0x06, 344 345 ATA_LOG_SATA_SETTINGS = 0x08, 345 346 ATA_LOG_ZONED_INFORMATION = 0x09, 346 347
+1
include/linux/libata.h
··· 156 156 ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */ 157 157 ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */ 158 158 ATA_DFLAG_AN = (1 << 7), /* AN configured */ 159 + ATA_DFLAG_TRUSTED = (1 << 8), /* device supports trusted send/recv */ 159 160 ATA_DFLAG_DMADIR = (1 << 10), /* device requires DMADIR */ 160 161 ATA_DFLAG_CFG_MASK = (1 << 12) - 1, 161 162