mirror of https://github.com/xemu-project/xemu.git
ide security: support passing in if a drive is 'locked' and stub the unlock command
This commit is contained in:
parent
cd5a59724d
commit
cf634db86a
|
@ -296,6 +296,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
|||
BlockIOLimit io_limits;
|
||||
int snapshot = 0;
|
||||
bool copy_on_read;
|
||||
bool locked;
|
||||
int ret;
|
||||
|
||||
translation = BIOS_ATA_TRANSLATION_AUTO;
|
||||
|
@ -314,6 +315,8 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
|||
ro = qemu_opt_get_bool(opts, "readonly", 0);
|
||||
copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false);
|
||||
|
||||
locked = qemu_opt_get_bool(opts, "locked", false);
|
||||
|
||||
file = qemu_opt_get(opts, "file");
|
||||
serial = qemu_opt_get(opts, "serial");
|
||||
|
||||
|
@ -541,6 +544,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
|||
dinfo->opts = opts;
|
||||
dinfo->refcount = 1;
|
||||
dinfo->serial = serial;
|
||||
dinfo->locked = locked;
|
||||
QTAILQ_INSERT_TAIL(&drives, dinfo, next);
|
||||
|
||||
bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
|
||||
|
|
|
@ -34,6 +34,7 @@ struct DriveInfo {
|
|||
int auto_del; /* see blockdev_mark_auto_del() */
|
||||
int media_cd;
|
||||
int cyls, heads, secs, trans;
|
||||
bool locked;
|
||||
QemuOpts *opts;
|
||||
const char *serial;
|
||||
QTAILQ_ENTRY(DriveInfo) next;
|
||||
|
|
|
@ -24,6 +24,14 @@ void blkconf_serial(BlockConf *conf, char **serial)
|
|||
}
|
||||
}
|
||||
|
||||
void blkconf_locked(BlockConf *conf, bool *locked)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
|
||||
dinfo = drive_get_by_blockdev(conf->bs);
|
||||
*locked = dinfo->locked;
|
||||
}
|
||||
|
||||
int blkconf_geometry(BlockConf *conf, int *ptrans,
|
||||
unsigned cyls_max, unsigned heads_max, unsigned secs_max)
|
||||
{
|
||||
|
|
|
@ -60,6 +60,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
|
|||
/* Configuration helpers */
|
||||
|
||||
void blkconf_serial(BlockConf *conf, char **serial);
|
||||
void blkconf_locked(BlockConf *conf, bool *locked);
|
||||
int blkconf_geometry(BlockConf *conf, int *trans,
|
||||
unsigned cyls_max, unsigned heads_max, unsigned secs_max);
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ static const int smart_attributes[][12] = {
|
|||
|
||||
static int ide_handle_rw_error(IDEState *s, int error, int op);
|
||||
static void ide_dummy_transfer_stop(IDEState *s);
|
||||
static void ide_security_cmd(IDEState *s);
|
||||
|
||||
static void padstr(char *str, const char *src, int len)
|
||||
{
|
||||
|
@ -176,6 +177,14 @@ static void ide_identify(IDEState *s)
|
|||
put_le16(p + 110, s->wwn >> 16);
|
||||
put_le16(p + 111, s->wwn);
|
||||
}
|
||||
|
||||
/* 2: locked, 1: security enabled, 0: security supported */
|
||||
if (dev && dev->locked) {
|
||||
put_le16(p + 128, (1 << 2) | (1 << 1) | 1);
|
||||
} else {
|
||||
put_le16(p + 128, (1 << 0));
|
||||
}
|
||||
|
||||
if (dev && dev->conf.discard_granularity) {
|
||||
put_le16(p + 169, 1); /* TRIM support */
|
||||
}
|
||||
|
@ -1026,6 +1035,7 @@ static const uint8_t ide_cmd_table[0x100] = {
|
|||
[IBM_SENSE_CONDITION] = CFA_OK,
|
||||
[CFA_WEAR_LEVEL] = HD_CFA_OK,
|
||||
[WIN_READ_NATIVE_MAX] = ALL_OK,
|
||||
[WIN_SECURITY_UNLOCK] = ALL_OK,
|
||||
};
|
||||
|
||||
static bool ide_cmd_permitted(IDEState *s, uint32_t cmd)
|
||||
|
@ -1343,6 +1353,12 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
|
|||
ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
|
||||
ide_atapi_cmd);
|
||||
break;
|
||||
case WIN_SECURITY_UNLOCK:
|
||||
s->error = 0;
|
||||
s->status = READY_STAT | SEEK_STAT;
|
||||
ide_transfer_start(s, s->io_buffer, 512,
|
||||
ide_security_cmd);
|
||||
break;
|
||||
/* CF-ATA commands */
|
||||
case CFA_REQ_EXT_ERROR_CODE:
|
||||
s->error = 0x09; /* miscellaneous error */
|
||||
|
@ -1706,7 +1722,8 @@ void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
|
|||
static bool ide_is_pio_out(IDEState *s)
|
||||
{
|
||||
if (s->end_transfer_func == ide_sector_write ||
|
||||
s->end_transfer_func == ide_atapi_cmd) {
|
||||
s->end_transfer_func == ide_atapi_cmd ||
|
||||
s->end_transfer_func == ide_security_cmd) {
|
||||
return false;
|
||||
} else if (s->end_transfer_func == ide_sector_read ||
|
||||
s->end_transfer_func == ide_transfer_stop ||
|
||||
|
@ -1812,6 +1829,17 @@ static void ide_dummy_transfer_stop(IDEState *s)
|
|||
s->io_buffer[3] = 0xff;
|
||||
}
|
||||
|
||||
static void ide_security_cmd(IDEState *s)
|
||||
{
|
||||
/* XXX: Actually verify the password... */
|
||||
|
||||
put_le16((uint16_t *)s->identify_data + 128, (1 << 1) | 1);
|
||||
|
||||
s->error = 0;
|
||||
s->status = READY_STAT | SEEK_STAT;
|
||||
ide_set_irq(s->bus);
|
||||
}
|
||||
|
||||
static void ide_reset(IDEState *s)
|
||||
{
|
||||
#ifdef DEBUG_IDE
|
||||
|
@ -2129,6 +2157,7 @@ static EndTransferFunc* transfer_end_table[] = {
|
|||
ide_transfer_stop,
|
||||
ide_atapi_cmd_reply_end,
|
||||
ide_atapi_cmd,
|
||||
ide_security_cmd,
|
||||
ide_dummy_transfer_stop,
|
||||
};
|
||||
|
||||
|
|
|
@ -481,6 +481,7 @@ struct IDEDevice {
|
|||
char *serial;
|
||||
char *model;
|
||||
uint64_t wwn;
|
||||
bool locked;
|
||||
};
|
||||
|
||||
#define BM_STATUS_DMAING 0x01
|
||||
|
|
|
@ -148,6 +148,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
|
|||
return -1;
|
||||
}
|
||||
|
||||
blkconf_locked(&dev->conf, &dev->locked);
|
||||
blkconf_serial(&dev->conf, &dev->serial);
|
||||
if (kind != IDE_CD
|
||||
&& blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255) < 0) {
|
||||
|
|
|
@ -114,6 +114,10 @@ static QemuOptsList qemu_drive_opts = {
|
|||
.name = "copy-on-read",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "copy read data from backing file into image file",
|
||||
},{
|
||||
.name = "locked",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "emulate a security locked drive",
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue