diff --git a/block.c b/block.c index 78ab2d0462..040bbaea76 100644 --- a/block.c +++ b/block.c @@ -430,11 +430,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, } } - /* call the change callback */ - bs->media_changed = 1; - if (bs->change_cb) - bs->change_cb(bs->change_opaque); - + if (!bdrv_key_required(bs)) { + /* call the change callback */ + bs->media_changed = 1; + if (bs->change_cb) + bs->change_cb(bs->change_opaque); + } return 0; } @@ -989,7 +990,15 @@ int bdrv_set_key(BlockDriverState *bs, const char *key) if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key) return -1; ret = bs->drv->bdrv_set_key(bs, key); - bs->valid_key = (ret == 0); + if (ret < 0) { + bs->valid_key = 0; + } else if (!bs->valid_key) { + bs->valid_key = 1; + /* call the change callback now, we skipped it on open */ + bs->media_changed = 1; + if (bs->change_cb) + bs->change_cb(bs->change_opaque); + } return ret; } diff --git a/console.h b/console.h index f9f3fc7397..dcb49adad3 100644 --- a/console.h +++ b/console.h @@ -304,7 +304,11 @@ void term_flush(void); void term_print_help(void); void monitor_suspend(void); void monitor_resume(void); -int monitor_read_bdrv_key(BlockDriverState *bs); + +#include "block.h" +void monitor_read_bdrv_key_start(BlockDriverState *bs, + BlockDriverCompletionFunc *completion_cb, + void *opaque); /* readline.c */ typedef void ReadLineFunc(void *opaque, const char *str); diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 0c8d9cca83..41c92c3f1d 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -514,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev) qemu_free(s); } -USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) +USBDevice *usb_msd_init(const char *filename) { MSDState *s; BlockDriverState *bdrv; @@ -554,7 +554,6 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) if (bdrv_open2(bdrv, filename, 0, drv) < 0) goto fail; s->bs = bdrv; - *pbs = bdrv; s->dev.speed = USB_SPEED_FULL; s->dev.handle_packet = usb_generic_handle_packet; @@ -574,3 +573,10 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) qemu_free(s); return NULL; } + +BlockDriverState *usb_msd_get_bdrv(USBDevice *dev) +{ + MSDState *s = (MSDState *)dev; + + return s->bs; +} diff --git a/hw/usb.h b/hw/usb.h index 4cd832d492..a5e0d44d3b 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -253,7 +253,8 @@ USBDevice *usb_keyboard_init(void); void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *)); /* usb-msd.c */ -USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs); +USBDevice *usb_msd_init(const char *filename); +BlockDriverState *usb_msd_get_bdrv(USBDevice *dev); /* usb-net.c */ USBDevice *usb_net_init(NICInfo *nd); diff --git a/monitor.c b/monitor.c index 322cf1ae3a..183c846847 100644 --- a/monitor.c +++ b/monitor.c @@ -74,13 +74,18 @@ static const term_cmd_t info_cmds[]; static uint8_t term_outbuf[1024]; static int term_outbuf_index; +static BlockDriverCompletionFunc *password_completion_cb; +static void *password_opaque; static void monitor_start_input(void); -static void monitor_readline(const char *prompt, int is_password, - char *buf, int buf_size); static CPUState *mon_cpu = NULL; +static void monitor_read_password(ReadLineFunc *readline_func, void *opaque) +{ + readline_start("Password: ", 1, readline_func, opaque); +} + void term_flush(void) { int i; @@ -435,21 +440,29 @@ static void do_change_block(const char *device, const char *filename, const char if (eject_device(bs, 0) < 0) return; bdrv_open2(bs, filename, 0, drv); - monitor_read_bdrv_key(bs); + monitor_read_bdrv_key_start(bs, NULL, NULL); +} + +static void change_vnc_password_cb(void *opaque, const char *password) +{ + if (vnc_display_password(NULL, password) < 0) + term_printf("could not set VNC server password\n"); + + monitor_start_input(); } static void do_change_vnc(const char *target, const char *arg) { if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) { - char password[9]; if (arg) { + char password[9]; strncpy(password, arg, sizeof(password)); password[sizeof(password) - 1] = '\0'; - } else - monitor_readline("Password: ", 1, password, sizeof(password)); - if (vnc_display_password(NULL, password) < 0) - term_printf("could not set VNC server password\n"); + change_vnc_password_cb(NULL, password); + } else { + monitor_read_password(change_vnc_password_cb, NULL); + } } else { if (vnc_display_open(NULL, target) < 0) term_printf("could not start VNC server on %s\n", target); @@ -496,15 +509,7 @@ static void do_stop(void) vm_stop(EXCP_INTERRUPT); } -static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs) -{ - int *err = opaque; - - if (bdrv_key_required(bs)) - *err = monitor_read_bdrv_key(bs); - else - *err = 0; -} +static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs); static void do_cont(void) { @@ -516,6 +521,23 @@ static void do_cont(void) vm_start(); } +static void bdrv_key_cb(void *opaque, int err) +{ + /* another key was set successfully, retry to continue */ + if (!err) + do_cont(); +} + +static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs) +{ + int *err = opaque; + + if (!*err && bdrv_key_required(bs)) { + *err = -EBUSY; + monitor_read_bdrv_key_start(bs, bdrv_key_cb, NULL); + } +} + #ifdef CONFIG_GDBSTUB static void do_gdbserver(const char *port) { @@ -2835,7 +2857,7 @@ static void monitor_handle_command1(void *opaque, const char *cmdline) { monitor_handle_command(cmdline); if (!monitor_suspended) - monitor_start_input(); + readline_show_prompt(); else monitor_suspended = 2; } @@ -2898,46 +2920,36 @@ void monitor_init(CharDriverState *hd, int show_banner) readline_start("", 0, monitor_handle_command1, NULL); } -/* XXX: use threads ? */ -/* modal monitor readline */ -static int monitor_readline_started; -static char *monitor_readline_buf; -static int monitor_readline_buf_size; - -static void monitor_readline_cb(void *opaque, const char *input) +static void bdrv_password_cb(void *opaque, const char *password) { - pstrcpy(monitor_readline_buf, monitor_readline_buf_size, input); - monitor_readline_started = 0; -} + BlockDriverState *bs = opaque; + int ret = 0; -static void monitor_readline(const char *prompt, int is_password, - char *buf, int buf_size) -{ - readline_start(prompt, is_password, monitor_readline_cb, NULL); - readline_show_prompt(); - monitor_readline_buf = buf; - monitor_readline_buf_size = buf_size; - monitor_readline_started = 1; - while (monitor_readline_started) { - main_loop_wait(10); + if (bdrv_set_key(bs, password) != 0) { + term_printf("invalid password\n"); + ret = -EPERM; } + if (password_completion_cb) + password_completion_cb(password_opaque, ret); + + monitor_start_input(); } -int monitor_read_bdrv_key(BlockDriverState *bs) +void monitor_read_bdrv_key_start(BlockDriverState *bs, + BlockDriverCompletionFunc *completion_cb, + void *opaque) { - char password[256]; - int i; - - if (!bdrv_is_encrypted(bs)) - return 0; + if (!bdrv_key_required(bs)) { + if (completion_cb) + completion_cb(opaque, 0); + return; + } term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs), bdrv_get_encrypted_filename(bs)); - for(i = 0; i < 3; i++) { - monitor_readline("Password: ", 1, password, sizeof(password)); - if (bdrv_set_key(bs, password) == 0) - return 0; - term_printf("invalid password\n"); - } - return -EPERM; + + password_completion_cb = completion_cb; + password_opaque = opaque; + + monitor_read_password(bdrv_password_cb, bs); } diff --git a/vl.c b/vl.c index aaeff23faf..6c0adb5e2f 100644 --- a/vl.c +++ b/vl.c @@ -2661,6 +2661,16 @@ int usb_device_add_dev(USBDevice *dev) return 0; } +static void usb_msd_password_cb(void *opaque, int err) +{ + USBDevice *dev = opaque; + + if (!err) + usb_device_add_dev(dev); + else + dev->handle_destroy(dev); +} + static int usb_device_add(const char *devname, int is_hotplug) { const char *p; @@ -2680,14 +2690,15 @@ static int usb_device_add(const char *devname, int is_hotplug) } else if (strstart(devname, "disk:", &p)) { BlockDriverState *bs; - dev = usb_msd_init(p, &bs); + dev = usb_msd_init(p); if (!dev) return -1; + bs = usb_msd_get_bdrv(dev); if (bdrv_key_required(bs)) { autostart = 0; - if (is_hotplug && monitor_read_bdrv_key(bs) < 0) { - dev->handle_destroy(dev); - return -1; + if (is_hotplug) { + monitor_read_bdrv_key_start(bs, usb_msd_password_cb, dev); + return 0; } } } else if (!strcmp(devname, "wacom-tablet")) {