+version 0.10.1:
+
+ - virtio-net: allow masking of notifications on empty queue (Alex Williamson)
+ - e1000: fix rx descriptor low threshold logic (Alex Willaimson)
+ - x86 tcg: add NULL checks to lsl instruction (Jan Kiszka)
+ - kvm vga: fix screen corruption with -std-vga and Windows (Avi Kivity)
+ - kvm vga: fix screen corruption with Ubuntu installations (Glauber Costa)
+ - virtio-net: check right return size on sg list (Alex Williamson)
+ - Make qemu_announce_self handle holes (live migration after hotplug)
+ (Marcelo Tosatti)
+ - Revert r6804-r6808 (qcow2 allocation info). This series of changes added
+ a high cost to startup for large qcow2 images (Anthony Liguori)
+ - qemu-img: fix help message (Aurelien Jarno)
+ - Fix build for non-default installs of SDL (Anthony Liguori)
+ - Fix race condition in env->interrupt_request. When using TCG and a dynticks
+ host timer, this condition could cause TCG to get stuck in an infinite
+ loop (Aurelien Jarno)
+ - Fix reading encrypted hard disk passwords during early startup (Jan Kiszka)
+ - Fix encrypted disk reporting in 'info block' (Jan Kiszka)
+ - Fix console size with tiny displays (MusicPal) (Jan Kiszka)
+ - Improve error handling in bdrv_open2 (Jan Kiszka)
+ - Avoid leaking data in mux'ed character devices (Jan Kiszka)
+ - Fix initial character device reset (no banner in monitor) (Jan Kiszka)
+ - Fix cpuid KVM crash on i386 host (Lubomir Rintel)
+ - Fix SLES10sp2 installation by adding ISTAT1 register to LSI SCSI emulation
+ (Ryan Harper)
+
version 0.10.0:
- TCG support (No longer requires GCC 3.x)
uint32_t crypt_method_header;
AES_KEY aes_encrypt_key;
AES_KEY aes_decrypt_key;
-
- int64_t highest_alloc; /* highest cluester allocated (in clusters) */
- int64_t nc_free; /* num of free clusters below highest_alloc */
-
uint64_t snapshots_offset;
int snapshots_size;
int nb_snapshots;
#ifdef DEBUG_ALLOC
static void check_refcounts(BlockDriverState *bs);
#endif
-static void scan_refcount(BlockDriverState *bs, int64_t *high, int64_t *free);
-
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
if (refcount_init(bs) < 0)
goto fail;
- scan_refcount(bs, &s->highest_alloc, &s->nc_free);
-
/* read the backing file name */
if (header.backing_file_offset != 0) {
len = header.backing_file_size;
bdi->cluster_size = s->cluster_size;
bdi->vm_state_offset = (int64_t)s->l1_vm_state_index <<
(s->cluster_bits + s->l2_bits);
- bdi->highest_alloc = s->highest_alloc << s->cluster_bits;
- bdi->num_free_bytes = s->nc_free << s->cluster_bits;
return 0;
}
return 0;
}
-static void scan_refcount(BlockDriverState *bs, int64_t *high, int64_t *free)
-{
- BDRVQcowState *s = bs->opaque;
- int64_t refcnt_index, cluster_index, cluster_end, h = 0, f = 0;
- int64_t tail = 0; /* do not count last consecutive free entries */
-
- for (refcnt_index=0; refcnt_index < s->refcount_table_size; refcnt_index++){
- if (s->refcount_table[refcnt_index] == 0) {
- f += 1 << (s->cluster_bits - REFCOUNT_SHIFT);
- tail += 1 << (s->cluster_bits - REFCOUNT_SHIFT);
- continue;
- }
- cluster_index = refcnt_index << (s->cluster_bits - REFCOUNT_SHIFT);
- cluster_end = (refcnt_index + 1) << (s->cluster_bits - REFCOUNT_SHIFT);
- for ( ; cluster_index < cluster_end; cluster_index++) {
- if (get_refcount(bs, cluster_index) == 0) {
- f++;
- tail++;
- }
- else {
- h = cluster_index;
- tail = 0;
- }
- }
- }
-
- f -= tail;
- if (free)
- *free = f;
- if (high)
- *high = (h+1);
-}
-
static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
{
BDRVQcowState *s = bs->opaque;
size,
(s->free_cluster_index - nb_clusters) << s->cluster_bits);
#endif
-
- if (s->highest_alloc < s->free_cluster_index) {
- s->nc_free += (s->free_cluster_index - s->highest_alloc);
- s->highest_alloc = s->free_cluster_index;
- }
-
return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
}
block_index = cluster_index &
((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
refcount = be16_to_cpu(s->refcount_block_cache[block_index]);
-
- if (refcount == 1 && addend == -1)
- s->nc_free += 1;
- else if (refcount == 0 && addend == 1)
- s->nc_free -= 1;
-
refcount += addend;
if (refcount < 0 || refcount > 0xffff)
return -EINVAL;
int ret;
bs = bdrv_new("");
- if (!bs)
- return -ENOMEM;
ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
if (ret < 0) {
bdrv_delete(bs);
bs->read_only = 0;
bs->is_temporary = 0;
bs->encrypted = 0;
+ bs->valid_key = 0;
if (flags & BDRV_O_SNAPSHOT) {
BlockDriverState *bs1;
/* if there is a backing file, use it */
bs1 = bdrv_new("");
- if (!bs1) {
- return -ENOMEM;
- }
- if (bdrv_open(bs1, filename, 0) < 0) {
+ ret = bdrv_open(bs1, filename, 0);
+ if (ret < 0) {
bdrv_delete(bs1);
- return -1;
+ return ret;
}
total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
else
realpath(filename, backing_filename);
- if (bdrv_create(&bdrv_qcow2, tmp_filename,
- total_size, backing_filename, 0) < 0) {
- return -1;
+ ret = bdrv_create(&bdrv_qcow2, tmp_filename,
+ total_size, backing_filename, 0);
+ if (ret < 0) {
+ return ret;
}
filename = tmp_filename;
bs->is_temporary = 1;
pstrcpy(bs->filename, sizeof(bs->filename), filename);
if (flags & BDRV_O_FILE) {
drv = find_protocol(filename);
- if (!drv)
- return -ENOENT;
- } else {
- if (!drv) {
- drv = find_image_format(filename);
- if (!drv)
- return -1;
- }
+ } else if (!drv) {
+ drv = find_image_format(filename);
+ }
+ if (!drv) {
+ ret = -ENOENT;
+ goto unlink_and_fail;
}
bs->drv = drv;
bs->opaque = qemu_mallocz(drv->instance_size);
qemu_free(bs->opaque);
bs->opaque = NULL;
bs->drv = NULL;
+ unlink_and_fail:
+ if (bs->is_temporary)
+ unlink(filename);
return ret;
}
if (drv->bdrv_getlength) {
if (bs->backing_file[0] != '\0') {
/* if there is a backing file, use it */
bs->backing_hd = bdrv_new("");
- if (!bs->backing_hd) {
- fail:
- bdrv_close(bs);
- return -ENOMEM;
- }
path_combine(backing_filename, sizeof(backing_filename),
filename, bs->backing_file);
- if (bdrv_open(bs->backing_hd, backing_filename, open_flags) < 0)
- goto fail;
+ ret = bdrv_open(bs->backing_hd, backing_filename, open_flags);
+ if (ret < 0) {
+ bdrv_close(bs);
+ return ret;
+ }
}
/* call the change callback */
return bs->encrypted;
}
+int bdrv_key_required(BlockDriverState *bs)
+{
+ BlockDriverState *backing_hd = bs->backing_hd;
+
+ if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key)
+ return 1;
+ return (bs->encrypted && !bs->valid_key);
+}
+
int bdrv_set_key(BlockDriverState *bs, const char *key)
{
int ret;
}
if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
return -1;
- return bs->drv->bdrv_set_key(bs, key);
+ ret = bs->drv->bdrv_set_key(bs, key);
+ bs->valid_key = (ret == 0);
+ return ret;
}
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
return NULL;
}
-void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
+void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
{
BlockDriverState *bs;
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
- it(opaque, bs->device_name);
+ it(opaque, bs);
}
}
}
term_printf(" ro=%d", bs->read_only);
term_printf(" drv=%s", bs->drv->format_name);
- if (bs->encrypted)
- term_printf(" encrypted");
+ term_printf(" encrypted=%d", bdrv_is_encrypted(bs));
} else {
term_printf(" [not inserted]");
}
void bdrv_info_stats (void)
{
BlockDriverState *bs;
- BlockDriverInfo bdi;
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
term_printf ("%s:"
" wr_bytes=%" PRIu64
" rd_operations=%" PRIu64
" wr_operations=%" PRIu64
- ,
+ "\n",
bs->device_name,
bs->rd_bytes, bs->wr_bytes,
bs->rd_ops, bs->wr_ops);
- if (bdrv_get_info(bs, &bdi) == 0)
- term_printf(" high=%" PRId64
- " bytes_free=%" PRId64,
- bdi.highest_alloc, bdi.num_free_bytes);
- term_printf("\n");
}
}
+const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
+{
+ if (bs->backing_hd && bs->backing_hd->encrypted)
+ return bs->backing_file;
+ else if (bs->encrypted)
+ return bs->filename;
+ else
+ return NULL;
+}
+
void bdrv_get_backing_filename(BlockDriverState *bs,
char *filename, int filename_size)
{
int cluster_size;
/* offset at which the VM state can be saved (0 if not possible) */
int64_t vm_state_offset;
- int64_t highest_alloc; /* highest allocated block offset (in bytes) */
- int64_t num_free_bytes; /* below highest_alloc */
} BlockDriverInfo;
typedef struct QEMUSnapshotInfo {
BlockDriverCompletionFunc *cb, void *opaque);
void bdrv_aio_cancel(BlockDriverAIOCB *acb);
-int qemu_key_check(BlockDriverState *bs, const char *name);
-
/* Ensure contents are flushed to disk. */
void bdrv_flush(BlockDriverState *bs);
void bdrv_flush_all(void);
void (*change_cb)(void *opaque), void *opaque);
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
BlockDriverState *bdrv_find(const char *name);
-void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque);
+void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs),
+ void *opaque);
int bdrv_is_encrypted(BlockDriverState *bs);
+int bdrv_key_required(BlockDriverState *bs);
int bdrv_set_key(BlockDriverState *bs, const char *key);
+int bdrv_query_missing_keys(void);
void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
void *opaque);
const char *bdrv_get_device_name(BlockDriverState *bs);
const uint8_t *buf, int nb_sectors);
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
+const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
void bdrv_get_backing_filename(BlockDriverState *bs,
char *filename, int filename_size);
int bdrv_snapshot_create(BlockDriverState *bs,
int removable; /* if true, the media can be removed */
int locked; /* if true, the media cannot temporarily be ejected */
int encrypted; /* if true, the media is encrypted */
+ int valid_key; /* if true, a valid encryption key has been set */
int sg; /* if true, the device is a /dev/sg* */
/* event callback when inserting/removing */
void (*change_cb)(void *opaque);
void term_print_filename(const char *filename);
void term_flush(void);
void term_print_help(void);
-void monitor_readline(const char *prompt, int is_password,
- char *buf, int buf_size);
void monitor_suspend(void);
void monitor_resume(void);
+int monitor_read_bdrv_key(BlockDriverState *bs);
/* readline.c */
typedef void ReadLineFunc(void *opaque, const char *str);
#include "config.h"
#include <setjmp.h>
#include <inttypes.h>
+#include <signal.h>
#include "osdep.h"
#include "sys-queue.h"
memory was accessed */ \
uint32_t halted; /* Nonzero if the CPU is in suspend state */ \
uint32_t interrupt_request; \
+ volatile sig_atomic_t exit_request; \
/* The meaning of the MMU modes is defined in the target code. */ \
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
target_phys_addr_t iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \
env->exception_index = -1;
}
#ifdef USE_KQEMU
- if (kqemu_is_ok(env) && env->interrupt_request == 0) {
+ if (kqemu_is_ok(env) && env->interrupt_request == 0 && env->exit_request == 0) {
int ret;
env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
ret = kqemu_cpu_exec(env);
} else if (ret == 2) {
/* softmmu execution needed */
} else {
- if (env->interrupt_request != 0) {
+ if (env->interrupt_request != 0 || env->exit_request != 0) {
/* hardware interrupt will be executed just after */
} else {
/* otherwise, we restart */
the program flow was changed */
next_tb = 0;
}
- if (interrupt_request & CPU_INTERRUPT_EXIT) {
- env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
- env->exception_index = EXCP_INTERRUPT;
- cpu_loop_exit();
- }
+ }
+ if (unlikely(env->exit_request)) {
+ env->exit_request = 0;
+ env->exception_index = EXCP_INTERRUPT;
+ cpu_loop_exit();
}
#ifdef DEBUG_EXEC
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
TB, but before it is linked into a potentially
infinite loop and becomes env->current_tb. Avoid
starting execution if there is a pending interrupt. */
- if (unlikely (env->interrupt_request & CPU_INTERRUPT_EXIT))
+ if (unlikely (env->exit_request))
env->current_tb = NULL;
while (env->current_tb) {
qemu_get_be32s(f, &env->halted);
qemu_get_be32s(f, &env->interrupt_request);
+ env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
tlb_flush(env, 1);
return 0;
#endif
int old_mask;
+ if (mask & CPU_INTERRUPT_EXIT) {
+ env->exit_request = 1;
+ mask &= ~CPU_INTERRUPT_EXIT;
+ }
+
old_mask = env->interrupt_request;
- /* FIXME: This is probably not threadsafe. A different thread could
- be in the middle of a read-modify-write operation. */
env->interrupt_request |= mask;
#if defined(USE_NPTL)
/* FIXME: TB unchaining isn't SMP safe. For now just ignore the
if (use_icount) {
env->icount_decr.u16.high = 0xffff;
#ifndef CONFIG_USER_ONLY
- /* CPU_INTERRUPT_EXIT isn't a real interrupt. It just means
- an async event happened and we need to process it. */
if (!can_do_io(env)
- && (mask & ~(old_mask | CPU_INTERRUPT_EXIT)) != 0) {
+ && (mask & ~old_mask) != 0) {
cpu_abort(env, "Raised interrupt while not in I/O function");
}
#endif
s->lfb_vram_mapped = 0;
+ cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000,
+ (s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_UNASSIGNED);
+ cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000,
+ (s->vram_offset + s->cirrus_bank_base[1]) | IO_MEM_UNASSIGNED);
if (!(s->cirrus_srcptr != s->cirrus_srcptr_end)
&& !((s->sr[0x07] & 0x01) == 0)
&& !((s->gr[0x0B] & 0x14) == 0x14)
&& !(s->gr[0x0B] & 0x02)) {
+ vga_dirty_log_stop((VGAState *)s);
cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000,
(s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_RAM);
cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000,
n = E1000_ICS_RXT0;
if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH])
rdt += s->mac_reg[RDLEN] / sizeof(desc);
- if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) << s->rxbuf_min_shift >=
- s->mac_reg[RDLEN])
+ if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) <= s->mac_reg[RDLEN] >>
+ s->rxbuf_min_shift)
n |= E1000_ICS_RXDMT0;
set_ics(s, 0, n);
CASE_GET_REG32(dsa, 0x10)
case 0x14: /* ISTAT0 */
return s->istat0;
+ case 0x15: /* ISTAT1 */
+ return s->istat1;
case 0x16: /* MBOX0 */
return s->mbox0;
case 0x17: /* MBOX1 */
#include "usb.h"
#include "block.h"
#include "scsi-disk.h"
+#include "console.h"
//#define DEBUG_MSD
qemu_free(s);
}
-USBDevice *usb_msd_init(const char *filename)
+USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
{
MSDState *s;
BlockDriverState *bdrv;
bdrv = bdrv_new("usb");
if (bdrv_open2(bdrv, filename, 0, drv) < 0)
goto fail;
- if (qemu_key_check(bdrv, filename))
- goto fail;
s->bs = bdrv;
+ *pbs = bdrv;
s->dev.speed = USB_SPEED_FULL;
s->dev.handle_packet = usb_generic_handle_packet;
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
+#include "block.h"
+
#define USB_TOKEN_SETUP 0x2d
#define USB_TOKEN_IN 0x69 /* device -> host */
#define USB_TOKEN_OUT 0xe1 /* host -> device */
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *));
/* usb-msd.c */
-USBDevice *usb_msd_init(const char *filename);
+USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs);
/* usb-net.c */
USBDevice *usb_net_init(NICInfo *nd);
return 0;
}
+static void pci_vga_write_config(PCIDevice *d,
+ uint32_t address, uint32_t val, int len)
+{
+ PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
+ VGAState *s = &pvs->vga_state;
+
+ vga_dirty_log_stop(s);
+ pci_default_write_config(d, address, val, len);
+ vga_dirty_log_start(s);
+}
+
int pci_vga_init(PCIBus *bus, uint8_t *vga_ram_base,
unsigned long vga_ram_offset, int vga_ram_size,
unsigned long vga_bios_offset, int vga_bios_size)
d = (PCIVGAState *)pci_register_device(bus, "VGA",
sizeof(PCIVGAState),
- -1, NULL, NULL);
+ -1, NULL, pci_vga_write_config);
if (!d)
return -1;
s = &d->vga_state;
}
if (elem.out_sg[0].iov_len < sizeof(ctrl) ||
- elem.out_sg[elem.in_num - 1].iov_len < sizeof(status)) {
+ elem.in_sg[elem.in_num - 1].iov_len < sizeof(status)) {
fprintf(stderr, "virtio-net ctrl header not in correct element\n");
exit(1);
}
void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
{
- /* Always notify when queue is empty */
- if ((vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx) &&
- (vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT))
+ /* Always notify when queue is empty (when feature acknowledge) */
+ if ((vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT) &&
+ (!(vdev->features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) ||
+ (vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx)))
return;
vdev->isr |= 0x01;
do {
kvm_arch_pre_run(env, run);
- if ((env->interrupt_request & CPU_INTERRUPT_EXIT)) {
+ if (env->exit_request) {
dprintf("interrupt exit requested\n");
ret = 0;
break;
}
} while (ret > 0);
- if ((env->interrupt_request & CPU_INTERRUPT_EXIT)) {
- env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
+ if (env->exit_request) {
+ env->exit_request = 0;
env->exception_index = EXCP_INTERRUPT;
}
static int term_outbuf_index;
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;
if (eject_device(bs, 0) < 0)
return;
bdrv_open2(bs, filename, 0, drv);
- qemu_key_check(bs, filename);
+ monitor_read_bdrv_key(bs);
}
static void do_change_vnc(const char *target, const char *arg)
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 do_cont(void)
{
- vm_start();
+ int err = 0;
+
+ bdrv_iterate(encrypted_bdrv_it, &err);
+ /* only resume the vm if all keys are set and valid */
+ if (!err)
+ vm_start();
}
#ifdef CONFIG_GDBSTUB
closedir(ffs);
}
-static void block_completion_it(void *opaque, const char *name)
+static void block_completion_it(void *opaque, BlockDriverState *bs)
{
+ const char *name = bdrv_get_device_name(bs);
const char *input = opaque;
if (input[0] == '\0' ||
monitor_readline_started = 0;
}
-void monitor_readline(const char *prompt, int is_password,
- char *buf, int buf_size)
+static void monitor_readline(const char *prompt, int is_password,
+ char *buf, int buf_size)
{
int i;
int old_focus[MAX_MON];
monitor_hd[i]->focus = old_focus[i];
}
}
+
+int monitor_read_bdrv_key(BlockDriverState *bs)
+{
+ char password[256];
+ int i;
+
+ if (!bdrv_is_encrypted(bs))
+ return 0;
+
+ 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;
+}
/***********************************************************/
/* character device */
+static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
+ TAILQ_HEAD_INITIALIZER(chardevs);
+static int initial_reset_issued;
+
static void qemu_chr_event(CharDriverState *s, int event)
{
if (!s->chr_event)
void qemu_chr_reset(CharDriverState *s)
{
- if (s->bh == NULL) {
+ if (s->bh == NULL && initial_reset_issued) {
s->bh = qemu_bh_new(qemu_chr_reset_bh, s);
qemu_bh_schedule(s->bh);
}
}
+void qemu_chr_initial_reset(void)
+{
+ CharDriverState *chr;
+
+ initial_reset_issued = 1;
+
+ TAILQ_FOREACH(chr, &chardevs, next) {
+ qemu_chr_reset(chr);
+ }
+}
+
int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
{
return s->chr_write(s, buf, len);
IOEventHandler *chr_event[MAX_MUX];
void *ext_opaque[MAX_MUX];
CharDriverState *drv;
- unsigned char buffer[MUX_BUFFER_SIZE];
- int prod;
- int cons;
int mux_cnt;
int term_got_escape;
int max_size;
+ /* Intermediate input buffer allows to catch escape sequences even if the
+ currently active device is not accepting any input - but only until it
+ is full as well. */
+ unsigned char buffer[MAX_MUX][MUX_BUFFER_SIZE];
+ int prod[MAX_MUX];
+ int cons[MAX_MUX];
} MuxDriver;
int m = chr->focus;
MuxDriver *d = chr->opaque;
- while (d->prod != d->cons &&
+ while (d->prod[m] != d->cons[m] &&
d->chr_can_read[m] &&
d->chr_can_read[m](d->ext_opaque[m])) {
d->chr_read[m](d->ext_opaque[m],
- &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1);
+ &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1);
}
}
{
CharDriverState *chr = opaque;
MuxDriver *d = chr->opaque;
+ int m = chr->focus;
- if ((d->prod - d->cons) < MUX_BUFFER_SIZE)
+ if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE)
return 1;
- if (d->chr_can_read[chr->focus])
- return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]);
+ if (d->chr_can_read[m])
+ return d->chr_can_read[m](d->ext_opaque[m]);
return 0;
}
for(i = 0; i < size; i++)
if (mux_proc_byte(chr, d, buf[i])) {
- if (d->prod == d->cons &&
+ if (d->prod[m] == d->cons[m] &&
d->chr_can_read[m] &&
d->chr_can_read[m](d->ext_opaque[m]))
d->chr_read[m](d->ext_opaque[m], &buf[i], 1);
else
- d->buffer[d->prod++ & MUX_BUFFER_MASK] = buf[i];
+ d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i];
}
}
return NULL;
}
-static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs
-= TAILQ_HEAD_INITIALIZER(chardevs);
-
CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s))
{
const char *p;
void *opaque);
int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
void qemu_chr_reset(CharDriverState *s);
+void qemu_chr_initial_reset(void);
int qemu_chr_can_read(CharDriverState *s);
void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
void qemu_chr_accept_input(CharDriverState *s);
" differ\n"
" 'fmt' is the disk image format. It is guessed automatically in most cases\n"
" 'size' is the disk image size in kilobytes. Optional suffixes\n"
- " 'M' (megabyte, 1024 * 1024) and 'G' (gigabyte, 1024 * 1024 * 1024) are"
- " supported any @code{k} or @code{K} is ignored\n"
+ " 'M' (megabyte, 1024 * 1024) and 'G' (gigabyte, 1024 * 1024 * 1024) are\n"
+ " supported any 'k' or 'K' is ignored\n"
" 'output_filename' is the destination disk image filename\n"
" 'output_fmt' is the destination format\n"
" '-c' indicates that target image must be compressed (qcow format only)\n"
if (bdrv_get_info(bs, &bdi) >= 0) {
if (bdi.cluster_size != 0)
printf("cluster_size: %d\n", bdi.cluster_size);
- if (bdi.highest_alloc)
- printf("highest_alloc: %" PRId64 "\n", bdi.highest_alloc);
- if (bdi.num_free_bytes)
- printf("num_free_bytes: %" PRId64 "\n", bdi.num_free_bytes);
}
bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
if (backing_filename[0] != '\0') {
VLANClientState *vc;
uint8_t buf[256];
- for (i = 0; i < nb_nics; i++) {
+ for (i = 0; i < MAX_NICS; i++) {
+ if (!nd_table[i].used)
+ continue;
len = announce_self_create(buf, nd_table[i].macaddr);
vlan = nd_table[i].vlan;
for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
#include "x_keymap.h"
#include <SDL.h>
-#include <SDL/SDL_syswm.h>
+#include <SDL_syswm.h>
#ifndef _WIN32
#include <signal.h>
#else
asm volatile("pusha \n\t"
"cpuid \n\t"
- "mov %%eax, 0(%1) \n\t"
- "mov %%ebx, 4(%1) \n\t"
- "mov %%ecx, 8(%1) \n\t"
- "mov %%edx, 12(%1) \n\t"
+ "mov %%eax, 0(%2) \n\t"
+ "mov %%ebx, 4(%2) \n\t"
+ "mov %%ecx, 8(%2) \n\t"
+ "mov %%edx, 12(%2) \n\t"
"popa"
: : "a"(function), "c"(count), "S"(vec)
: "memory", "cc");
selector = selector1 & 0xffff;
eflags = helper_cc_compute_all(CC_OP);
+ if ((selector & 0xfffc) == 0)
+ goto fail;
if (load_segment(&e1, &e2, selector) != 0)
goto fail;
rpl = selector & 3;
int nb_nics;
NICInfo nd_table[MAX_NICS];
int vm_running;
+static int autostart;
static int rtc_utc = 1;
static int rtc_date_offset = -1; /* -1 means no change */
int cirrus_vga_enabled = 1;
bdrv_flags |= BDRV_O_CACHE_WB;
else if (cache == 3) /* not specified */
bdrv_flags |= BDRV_O_CACHE_DEF;
- if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0 || qemu_key_check(bdrv, file)) {
+ if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) {
fprintf(stderr, "qemu: could not open disk image %s\n",
file);
return -1;
}
+ if (bdrv_key_required(bdrv))
+ autostart = 0;
return drives_table_idx;
}
return 0;
}
-static int usb_device_add(const char *devname)
+static int usb_device_add(const char *devname, int is_hotplug)
{
const char *p;
USBDevice *dev;
} else if (!strcmp(devname, "keyboard")) {
dev = usb_keyboard_init();
} else if (strstart(devname, "disk:", &p)) {
- dev = usb_msd_init(p);
+ BlockDriverState *bs;
+
+ dev = usb_msd_init(p, &bs);
+ if (!dev)
+ return -1;
+ if (bdrv_key_required(bs)) {
+ autostart = 0;
+ if (is_hotplug && monitor_read_bdrv_key(bs) < 0) {
+ dev->handle_destroy(dev);
+ return -1;
+ }
+ }
} else if (!strcmp(devname, "wacom-tablet")) {
dev = usb_wacom_init();
} else if (strstart(devname, "serial:", &p)) {
void do_usb_add(const char *devname)
{
- usb_device_add(devname);
+ usb_device_add(devname, 1);
}
void do_usb_del(const char *devname)
{ NULL },
};
-/* password input */
-
-int qemu_key_check(BlockDriverState *bs, const char *name)
-{
- char password[256];
- int i;
-
- if (!bdrv_is_encrypted(bs))
- return 0;
-
- term_printf("%s is encrypted.\n", name);
- 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;
-}
-
-static BlockDriverState *get_bdrv(int index)
-{
- if (index > nb_drives)
- return NULL;
- return drives_table[index].bdrv;
-}
-
-static void read_passwords(void)
-{
- BlockDriverState *bs;
- int i;
-
- for(i = 0; i < 6; i++) {
- bs = get_bdrv(i);
- if (bs)
- qemu_key_check(bs, bdrv_get_device_name(bs));
- }
-}
-
#ifdef HAS_AUDIO
struct soundhw soundhw[] = {
#ifdef HAS_AUDIO_CHOICE
int fds[2];
int tb_size;
const char *pid_file = NULL;
- int autostart;
const char *incoming = NULL;
int fd = 0;
struct passwd *pwd = NULL;
kernel_cmdline = "";
cyls = heads = secs = 0;
translation = BIOS_ATA_TRANSLATION_AUTO;
- monitor_device = "vc";
+ monitor_device = "vc:80Cx24C";
serial_devices[0] = "vc:80Cx24C";
for(i = 1; i < MAX_SERIAL_PORTS; i++)
/* init USB devices */
if (usb_enabled) {
for(i = 0; i < usb_devices_index; i++) {
- if (usb_device_add(usb_devices[i]) < 0) {
+ if (usb_device_add(usb_devices[i], 0) < 0) {
fprintf(stderr, "Warning: could not add USB device %s\n",
usb_devices[i]);
}
}
text_consoles_set_display(display_state);
+ qemu_chr_initial_reset();
if (monitor_device && monitor_hd)
monitor_init(monitor_hd, !nographic);
qemu_start_incoming_migration(incoming);
}
- {
- /* XXX: simplify init */
- read_passwords();
- if (autostart) {
- vm_start();
- }
- }
+ if (autostart)
+ vm_start();
if (daemonize) {
uint8_t status = 0;