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;
|
BlockIOLimit io_limits;
|
||||||
int snapshot = 0;
|
int snapshot = 0;
|
||||||
bool copy_on_read;
|
bool copy_on_read;
|
||||||
|
bool locked;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
translation = BIOS_ATA_TRANSLATION_AUTO;
|
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);
|
ro = qemu_opt_get_bool(opts, "readonly", 0);
|
||||||
copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false);
|
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");
|
file = qemu_opt_get(opts, "file");
|
||||||
serial = qemu_opt_get(opts, "serial");
|
serial = qemu_opt_get(opts, "serial");
|
||||||
|
|
||||||
|
@ -541,6 +544,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
||||||
dinfo->opts = opts;
|
dinfo->opts = opts;
|
||||||
dinfo->refcount = 1;
|
dinfo->refcount = 1;
|
||||||
dinfo->serial = serial;
|
dinfo->serial = serial;
|
||||||
|
dinfo->locked = locked;
|
||||||
QTAILQ_INSERT_TAIL(&drives, dinfo, next);
|
QTAILQ_INSERT_TAIL(&drives, dinfo, next);
|
||||||
|
|
||||||
bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
|
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 auto_del; /* see blockdev_mark_auto_del() */
|
||||||
int media_cd;
|
int media_cd;
|
||||||
int cyls, heads, secs, trans;
|
int cyls, heads, secs, trans;
|
||||||
|
bool locked;
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
const char *serial;
|
const char *serial;
|
||||||
QTAILQ_ENTRY(DriveInfo) next;
|
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,
|
int blkconf_geometry(BlockConf *conf, int *ptrans,
|
||||||
unsigned cyls_max, unsigned heads_max, unsigned secs_max)
|
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 */
|
/* Configuration helpers */
|
||||||
|
|
||||||
void blkconf_serial(BlockConf *conf, char **serial);
|
void blkconf_serial(BlockConf *conf, char **serial);
|
||||||
|
void blkconf_locked(BlockConf *conf, bool *locked);
|
||||||
int blkconf_geometry(BlockConf *conf, int *trans,
|
int blkconf_geometry(BlockConf *conf, int *trans,
|
||||||
unsigned cyls_max, unsigned heads_max, unsigned secs_max);
|
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 int ide_handle_rw_error(IDEState *s, int error, int op);
|
||||||
static void ide_dummy_transfer_stop(IDEState *s);
|
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)
|
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 + 110, s->wwn >> 16);
|
||||||
put_le16(p + 111, s->wwn);
|
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) {
|
if (dev && dev->conf.discard_granularity) {
|
||||||
put_le16(p + 169, 1); /* TRIM support */
|
put_le16(p + 169, 1); /* TRIM support */
|
||||||
}
|
}
|
||||||
|
@ -1026,6 +1035,7 @@ static const uint8_t ide_cmd_table[0x100] = {
|
||||||
[IBM_SENSE_CONDITION] = CFA_OK,
|
[IBM_SENSE_CONDITION] = CFA_OK,
|
||||||
[CFA_WEAR_LEVEL] = HD_CFA_OK,
|
[CFA_WEAR_LEVEL] = HD_CFA_OK,
|
||||||
[WIN_READ_NATIVE_MAX] = ALL_OK,
|
[WIN_READ_NATIVE_MAX] = ALL_OK,
|
||||||
|
[WIN_SECURITY_UNLOCK] = ALL_OK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool ide_cmd_permitted(IDEState *s, uint32_t cmd)
|
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_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
|
||||||
ide_atapi_cmd);
|
ide_atapi_cmd);
|
||||||
break;
|
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 */
|
/* CF-ATA commands */
|
||||||
case CFA_REQ_EXT_ERROR_CODE:
|
case CFA_REQ_EXT_ERROR_CODE:
|
||||||
s->error = 0x09; /* miscellaneous error */
|
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)
|
static bool ide_is_pio_out(IDEState *s)
|
||||||
{
|
{
|
||||||
if (s->end_transfer_func == ide_sector_write ||
|
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;
|
return false;
|
||||||
} else if (s->end_transfer_func == ide_sector_read ||
|
} else if (s->end_transfer_func == ide_sector_read ||
|
||||||
s->end_transfer_func == ide_transfer_stop ||
|
s->end_transfer_func == ide_transfer_stop ||
|
||||||
|
@ -1812,6 +1829,17 @@ static void ide_dummy_transfer_stop(IDEState *s)
|
||||||
s->io_buffer[3] = 0xff;
|
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)
|
static void ide_reset(IDEState *s)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_IDE
|
#ifdef DEBUG_IDE
|
||||||
|
@ -2129,6 +2157,7 @@ static EndTransferFunc* transfer_end_table[] = {
|
||||||
ide_transfer_stop,
|
ide_transfer_stop,
|
||||||
ide_atapi_cmd_reply_end,
|
ide_atapi_cmd_reply_end,
|
||||||
ide_atapi_cmd,
|
ide_atapi_cmd,
|
||||||
|
ide_security_cmd,
|
||||||
ide_dummy_transfer_stop,
|
ide_dummy_transfer_stop,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -481,6 +481,7 @@ struct IDEDevice {
|
||||||
char *serial;
|
char *serial;
|
||||||
char *model;
|
char *model;
|
||||||
uint64_t wwn;
|
uint64_t wwn;
|
||||||
|
bool locked;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BM_STATUS_DMAING 0x01
|
#define BM_STATUS_DMAING 0x01
|
||||||
|
|
|
@ -148,6 +148,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blkconf_locked(&dev->conf, &dev->locked);
|
||||||
blkconf_serial(&dev->conf, &dev->serial);
|
blkconf_serial(&dev->conf, &dev->serial);
|
||||||
if (kind != IDE_CD
|
if (kind != IDE_CD
|
||||||
&& blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255) < 0) {
|
&& blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255) < 0) {
|
||||||
|
|
|
@ -114,6 +114,10 @@ static QemuOptsList qemu_drive_opts = {
|
||||||
.name = "copy-on-read",
|
.name = "copy-on-read",
|
||||||
.type = QEMU_OPT_BOOL,
|
.type = QEMU_OPT_BOOL,
|
||||||
.help = "copy read data from backing file into image file",
|
.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 */ }
|
{ /* end of list */ }
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue