Revision 666daa68
b/Makefile.objs | ||
---|---|---|
44 | 44 |
# system emulation, i.e. a single QEMU executable should support all |
45 | 45 |
# CPUs and machines. |
46 | 46 |
|
47 |
common-obj-y = $(block-obj-y) |
|
47 |
common-obj-y = $(block-obj-y) blockdev.o
|
|
48 | 48 |
common-obj-y += $(net-obj-y) |
49 | 49 |
common-obj-y += $(qobject-obj-y) |
50 | 50 |
common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX)) |
b/blockdev.c | ||
---|---|---|
1 |
/* |
|
2 |
* QEMU host block devices |
|
3 |
* |
|
4 |
* Copyright (c) 2003-2008 Fabrice Bellard |
|
5 |
* |
|
6 |
* This work is licensed under the terms of the GNU GPL, version 2 or |
|
7 |
* later. See the COPYING file in the top-level directory. |
|
8 |
*/ |
|
9 |
|
|
10 |
#include "block.h" |
|
11 |
#include "blockdev.h" |
|
12 |
#include "monitor.h" |
|
13 |
#include "qerror.h" |
|
14 |
#include "qemu-option.h" |
|
15 |
#include "qemu-config.h" |
|
16 |
#include "sysemu.h" |
|
17 |
|
|
18 |
struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives); |
|
19 |
|
|
20 |
QemuOpts *drive_add(const char *file, const char *fmt, ...) |
|
21 |
{ |
|
22 |
va_list ap; |
|
23 |
char optstr[1024]; |
|
24 |
QemuOpts *opts; |
|
25 |
|
|
26 |
va_start(ap, fmt); |
|
27 |
vsnprintf(optstr, sizeof(optstr), fmt, ap); |
|
28 |
va_end(ap); |
|
29 |
|
|
30 |
opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0); |
|
31 |
if (!opts) { |
|
32 |
return NULL; |
|
33 |
} |
|
34 |
if (file) |
|
35 |
qemu_opt_set(opts, "file", file); |
|
36 |
return opts; |
|
37 |
} |
|
38 |
|
|
39 |
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) |
|
40 |
{ |
|
41 |
DriveInfo *dinfo; |
|
42 |
|
|
43 |
/* seek interface, bus and unit */ |
|
44 |
|
|
45 |
QTAILQ_FOREACH(dinfo, &drives, next) { |
|
46 |
if (dinfo->type == type && |
|
47 |
dinfo->bus == bus && |
|
48 |
dinfo->unit == unit) |
|
49 |
return dinfo; |
|
50 |
} |
|
51 |
|
|
52 |
return NULL; |
|
53 |
} |
|
54 |
|
|
55 |
DriveInfo *drive_get_by_id(const char *id) |
|
56 |
{ |
|
57 |
DriveInfo *dinfo; |
|
58 |
|
|
59 |
QTAILQ_FOREACH(dinfo, &drives, next) { |
|
60 |
if (strcmp(id, dinfo->id)) |
|
61 |
continue; |
|
62 |
return dinfo; |
|
63 |
} |
|
64 |
return NULL; |
|
65 |
} |
|
66 |
|
|
67 |
int drive_get_max_bus(BlockInterfaceType type) |
|
68 |
{ |
|
69 |
int max_bus; |
|
70 |
DriveInfo *dinfo; |
|
71 |
|
|
72 |
max_bus = -1; |
|
73 |
QTAILQ_FOREACH(dinfo, &drives, next) { |
|
74 |
if(dinfo->type == type && |
|
75 |
dinfo->bus > max_bus) |
|
76 |
max_bus = dinfo->bus; |
|
77 |
} |
|
78 |
return max_bus; |
|
79 |
} |
|
80 |
|
|
81 |
const char *drive_get_serial(BlockDriverState *bdrv) |
|
82 |
{ |
|
83 |
DriveInfo *dinfo; |
|
84 |
|
|
85 |
QTAILQ_FOREACH(dinfo, &drives, next) { |
|
86 |
if (dinfo->bdrv == bdrv) |
|
87 |
return dinfo->serial; |
|
88 |
} |
|
89 |
|
|
90 |
return "\0"; |
|
91 |
} |
|
92 |
|
|
93 |
BlockInterfaceErrorAction drive_get_on_error( |
|
94 |
BlockDriverState *bdrv, int is_read) |
|
95 |
{ |
|
96 |
DriveInfo *dinfo; |
|
97 |
|
|
98 |
QTAILQ_FOREACH(dinfo, &drives, next) { |
|
99 |
if (dinfo->bdrv == bdrv) |
|
100 |
return is_read ? dinfo->on_read_error : dinfo->on_write_error; |
|
101 |
} |
|
102 |
|
|
103 |
return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC; |
|
104 |
} |
|
105 |
|
|
106 |
static void bdrv_format_print(void *opaque, const char *name) |
|
107 |
{ |
|
108 |
fprintf(stderr, " %s", name); |
|
109 |
} |
|
110 |
|
|
111 |
void drive_uninit(DriveInfo *dinfo) |
|
112 |
{ |
|
113 |
qemu_opts_del(dinfo->opts); |
|
114 |
bdrv_delete(dinfo->bdrv); |
|
115 |
QTAILQ_REMOVE(&drives, dinfo, next); |
|
116 |
qemu_free(dinfo); |
|
117 |
} |
|
118 |
|
|
119 |
static int parse_block_error_action(const char *buf, int is_read) |
|
120 |
{ |
|
121 |
if (!strcmp(buf, "ignore")) { |
|
122 |
return BLOCK_ERR_IGNORE; |
|
123 |
} else if (!is_read && !strcmp(buf, "enospc")) { |
|
124 |
return BLOCK_ERR_STOP_ENOSPC; |
|
125 |
} else if (!strcmp(buf, "stop")) { |
|
126 |
return BLOCK_ERR_STOP_ANY; |
|
127 |
} else if (!strcmp(buf, "report")) { |
|
128 |
return BLOCK_ERR_REPORT; |
|
129 |
} else { |
|
130 |
fprintf(stderr, "qemu: '%s' invalid %s error action\n", |
|
131 |
buf, is_read ? "read" : "write"); |
|
132 |
return -1; |
|
133 |
} |
|
134 |
} |
|
135 |
|
|
136 |
DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) |
|
137 |
{ |
|
138 |
const char *buf; |
|
139 |
const char *file = NULL; |
|
140 |
char devname[128]; |
|
141 |
const char *serial; |
|
142 |
const char *mediastr = ""; |
|
143 |
BlockInterfaceType type; |
|
144 |
enum { MEDIA_DISK, MEDIA_CDROM } media; |
|
145 |
int bus_id, unit_id; |
|
146 |
int cyls, heads, secs, translation; |
|
147 |
BlockDriver *drv = NULL; |
|
148 |
int max_devs; |
|
149 |
int index; |
|
150 |
int ro = 0; |
|
151 |
int bdrv_flags = 0; |
|
152 |
int on_read_error, on_write_error; |
|
153 |
const char *devaddr; |
|
154 |
DriveInfo *dinfo; |
|
155 |
int snapshot = 0; |
|
156 |
int ret; |
|
157 |
|
|
158 |
*fatal_error = 1; |
|
159 |
|
|
160 |
translation = BIOS_ATA_TRANSLATION_AUTO; |
|
161 |
|
|
162 |
if (default_to_scsi) { |
|
163 |
type = IF_SCSI; |
|
164 |
max_devs = MAX_SCSI_DEVS; |
|
165 |
pstrcpy(devname, sizeof(devname), "scsi"); |
|
166 |
} else { |
|
167 |
type = IF_IDE; |
|
168 |
max_devs = MAX_IDE_DEVS; |
|
169 |
pstrcpy(devname, sizeof(devname), "ide"); |
|
170 |
} |
|
171 |
media = MEDIA_DISK; |
|
172 |
|
|
173 |
/* extract parameters */ |
|
174 |
bus_id = qemu_opt_get_number(opts, "bus", 0); |
|
175 |
unit_id = qemu_opt_get_number(opts, "unit", -1); |
|
176 |
index = qemu_opt_get_number(opts, "index", -1); |
|
177 |
|
|
178 |
cyls = qemu_opt_get_number(opts, "cyls", 0); |
|
179 |
heads = qemu_opt_get_number(opts, "heads", 0); |
|
180 |
secs = qemu_opt_get_number(opts, "secs", 0); |
|
181 |
|
|
182 |
snapshot = qemu_opt_get_bool(opts, "snapshot", 0); |
|
183 |
ro = qemu_opt_get_bool(opts, "readonly", 0); |
|
184 |
|
|
185 |
file = qemu_opt_get(opts, "file"); |
|
186 |
serial = qemu_opt_get(opts, "serial"); |
|
187 |
|
|
188 |
if ((buf = qemu_opt_get(opts, "if")) != NULL) { |
|
189 |
pstrcpy(devname, sizeof(devname), buf); |
|
190 |
if (!strcmp(buf, "ide")) { |
|
191 |
type = IF_IDE; |
|
192 |
max_devs = MAX_IDE_DEVS; |
|
193 |
} else if (!strcmp(buf, "scsi")) { |
|
194 |
type = IF_SCSI; |
|
195 |
max_devs = MAX_SCSI_DEVS; |
|
196 |
} else if (!strcmp(buf, "floppy")) { |
|
197 |
type = IF_FLOPPY; |
|
198 |
max_devs = 0; |
|
199 |
} else if (!strcmp(buf, "pflash")) { |
|
200 |
type = IF_PFLASH; |
|
201 |
max_devs = 0; |
|
202 |
} else if (!strcmp(buf, "mtd")) { |
|
203 |
type = IF_MTD; |
|
204 |
max_devs = 0; |
|
205 |
} else if (!strcmp(buf, "sd")) { |
|
206 |
type = IF_SD; |
|
207 |
max_devs = 0; |
|
208 |
} else if (!strcmp(buf, "virtio")) { |
|
209 |
type = IF_VIRTIO; |
|
210 |
max_devs = 0; |
|
211 |
} else if (!strcmp(buf, "xen")) { |
|
212 |
type = IF_XEN; |
|
213 |
max_devs = 0; |
|
214 |
} else if (!strcmp(buf, "none")) { |
|
215 |
type = IF_NONE; |
|
216 |
max_devs = 0; |
|
217 |
} else { |
|
218 |
fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf); |
|
219 |
return NULL; |
|
220 |
} |
|
221 |
} |
|
222 |
|
|
223 |
if (cyls || heads || secs) { |
|
224 |
if (cyls < 1 || (type == IF_IDE && cyls > 16383)) { |
|
225 |
fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf); |
|
226 |
return NULL; |
|
227 |
} |
|
228 |
if (heads < 1 || (type == IF_IDE && heads > 16)) { |
|
229 |
fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf); |
|
230 |
return NULL; |
|
231 |
} |
|
232 |
if (secs < 1 || (type == IF_IDE && secs > 63)) { |
|
233 |
fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf); |
|
234 |
return NULL; |
|
235 |
} |
|
236 |
} |
|
237 |
|
|
238 |
if ((buf = qemu_opt_get(opts, "trans")) != NULL) { |
|
239 |
if (!cyls) { |
|
240 |
fprintf(stderr, |
|
241 |
"qemu: '%s' trans must be used with cyls,heads and secs\n", |
|
242 |
buf); |
|
243 |
return NULL; |
|
244 |
} |
|
245 |
if (!strcmp(buf, "none")) |
|
246 |
translation = BIOS_ATA_TRANSLATION_NONE; |
|
247 |
else if (!strcmp(buf, "lba")) |
|
248 |
translation = BIOS_ATA_TRANSLATION_LBA; |
|
249 |
else if (!strcmp(buf, "auto")) |
|
250 |
translation = BIOS_ATA_TRANSLATION_AUTO; |
|
251 |
else { |
|
252 |
fprintf(stderr, "qemu: '%s' invalid translation type\n", buf); |
|
253 |
return NULL; |
|
254 |
} |
|
255 |
} |
|
256 |
|
|
257 |
if ((buf = qemu_opt_get(opts, "media")) != NULL) { |
|
258 |
if (!strcmp(buf, "disk")) { |
|
259 |
media = MEDIA_DISK; |
|
260 |
} else if (!strcmp(buf, "cdrom")) { |
|
261 |
if (cyls || secs || heads) { |
|
262 |
fprintf(stderr, |
|
263 |
"qemu: '%s' invalid physical CHS format\n", buf); |
|
264 |
return NULL; |
|
265 |
} |
|
266 |
media = MEDIA_CDROM; |
|
267 |
} else { |
|
268 |
fprintf(stderr, "qemu: '%s' invalid media\n", buf); |
|
269 |
return NULL; |
|
270 |
} |
|
271 |
} |
|
272 |
|
|
273 |
if ((buf = qemu_opt_get(opts, "cache")) != NULL) { |
|
274 |
if (!strcmp(buf, "off") || !strcmp(buf, "none")) { |
|
275 |
bdrv_flags |= BDRV_O_NOCACHE; |
|
276 |
} else if (!strcmp(buf, "writeback")) { |
|
277 |
bdrv_flags |= BDRV_O_CACHE_WB; |
|
278 |
} else if (!strcmp(buf, "unsafe")) { |
|
279 |
bdrv_flags |= BDRV_O_CACHE_WB; |
|
280 |
bdrv_flags |= BDRV_O_NO_FLUSH; |
|
281 |
} else if (!strcmp(buf, "writethrough")) { |
|
282 |
/* this is the default */ |
|
283 |
} else { |
|
284 |
fprintf(stderr, "qemu: invalid cache option\n"); |
|
285 |
return NULL; |
|
286 |
} |
|
287 |
} |
|
288 |
|
|
289 |
#ifdef CONFIG_LINUX_AIO |
|
290 |
if ((buf = qemu_opt_get(opts, "aio")) != NULL) { |
|
291 |
if (!strcmp(buf, "native")) { |
|
292 |
bdrv_flags |= BDRV_O_NATIVE_AIO; |
|
293 |
} else if (!strcmp(buf, "threads")) { |
|
294 |
/* this is the default */ |
|
295 |
} else { |
|
296 |
fprintf(stderr, "qemu: invalid aio option\n"); |
|
297 |
return NULL; |
|
298 |
} |
|
299 |
} |
|
300 |
#endif |
|
301 |
|
|
302 |
if ((buf = qemu_opt_get(opts, "format")) != NULL) { |
|
303 |
if (strcmp(buf, "?") == 0) { |
|
304 |
fprintf(stderr, "qemu: Supported formats:"); |
|
305 |
bdrv_iterate_format(bdrv_format_print, NULL); |
|
306 |
fprintf(stderr, "\n"); |
|
307 |
return NULL; |
|
308 |
} |
|
309 |
drv = bdrv_find_whitelisted_format(buf); |
|
310 |
if (!drv) { |
|
311 |
fprintf(stderr, "qemu: '%s' invalid format\n", buf); |
|
312 |
return NULL; |
|
313 |
} |
|
314 |
} |
|
315 |
|
|
316 |
on_write_error = BLOCK_ERR_STOP_ENOSPC; |
|
317 |
if ((buf = qemu_opt_get(opts, "werror")) != NULL) { |
|
318 |
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) { |
|
319 |
fprintf(stderr, "werror is no supported by this format\n"); |
|
320 |
return NULL; |
|
321 |
} |
|
322 |
|
|
323 |
on_write_error = parse_block_error_action(buf, 0); |
|
324 |
if (on_write_error < 0) { |
|
325 |
return NULL; |
|
326 |
} |
|
327 |
} |
|
328 |
|
|
329 |
on_read_error = BLOCK_ERR_REPORT; |
|
330 |
if ((buf = qemu_opt_get(opts, "rerror")) != NULL) { |
|
331 |
if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) { |
|
332 |
fprintf(stderr, "rerror is no supported by this format\n"); |
|
333 |
return NULL; |
|
334 |
} |
|
335 |
|
|
336 |
on_read_error = parse_block_error_action(buf, 1); |
|
337 |
if (on_read_error < 0) { |
|
338 |
return NULL; |
|
339 |
} |
|
340 |
} |
|
341 |
|
|
342 |
if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) { |
|
343 |
if (type != IF_VIRTIO) { |
|
344 |
fprintf(stderr, "addr is not supported\n"); |
|
345 |
return NULL; |
|
346 |
} |
|
347 |
} |
|
348 |
|
|
349 |
/* compute bus and unit according index */ |
|
350 |
|
|
351 |
if (index != -1) { |
|
352 |
if (bus_id != 0 || unit_id != -1) { |
|
353 |
fprintf(stderr, |
|
354 |
"qemu: index cannot be used with bus and unit\n"); |
|
355 |
return NULL; |
|
356 |
} |
|
357 |
if (max_devs == 0) |
|
358 |
{ |
|
359 |
unit_id = index; |
|
360 |
bus_id = 0; |
|
361 |
} else { |
|
362 |
unit_id = index % max_devs; |
|
363 |
bus_id = index / max_devs; |
|
364 |
} |
|
365 |
} |
|
366 |
|
|
367 |
/* if user doesn't specify a unit_id, |
|
368 |
* try to find the first free |
|
369 |
*/ |
|
370 |
|
|
371 |
if (unit_id == -1) { |
|
372 |
unit_id = 0; |
|
373 |
while (drive_get(type, bus_id, unit_id) != NULL) { |
|
374 |
unit_id++; |
|
375 |
if (max_devs && unit_id >= max_devs) { |
|
376 |
unit_id -= max_devs; |
|
377 |
bus_id++; |
|
378 |
} |
|
379 |
} |
|
380 |
} |
|
381 |
|
|
382 |
/* check unit id */ |
|
383 |
|
|
384 |
if (max_devs && unit_id >= max_devs) { |
|
385 |
fprintf(stderr, "qemu: unit %d too big (max is %d)\n", |
|
386 |
unit_id, max_devs - 1); |
|
387 |
return NULL; |
|
388 |
} |
|
389 |
|
|
390 |
/* |
|
391 |
* ignore multiple definitions |
|
392 |
*/ |
|
393 |
|
|
394 |
if (drive_get(type, bus_id, unit_id) != NULL) { |
|
395 |
*fatal_error = 0; |
|
396 |
return NULL; |
|
397 |
} |
|
398 |
|
|
399 |
/* init */ |
|
400 |
|
|
401 |
dinfo = qemu_mallocz(sizeof(*dinfo)); |
|
402 |
if ((buf = qemu_opts_id(opts)) != NULL) { |
|
403 |
dinfo->id = qemu_strdup(buf); |
|
404 |
} else { |
|
405 |
/* no id supplied -> create one */ |
|
406 |
dinfo->id = qemu_mallocz(32); |
|
407 |
if (type == IF_IDE || type == IF_SCSI) |
|
408 |
mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd"; |
|
409 |
if (max_devs) |
|
410 |
snprintf(dinfo->id, 32, "%s%i%s%i", |
|
411 |
devname, bus_id, mediastr, unit_id); |
|
412 |
else |
|
413 |
snprintf(dinfo->id, 32, "%s%s%i", |
|
414 |
devname, mediastr, unit_id); |
|
415 |
} |
|
416 |
dinfo->bdrv = bdrv_new(dinfo->id); |
|
417 |
dinfo->devaddr = devaddr; |
|
418 |
dinfo->type = type; |
|
419 |
dinfo->bus = bus_id; |
|
420 |
dinfo->unit = unit_id; |
|
421 |
dinfo->on_read_error = on_read_error; |
|
422 |
dinfo->on_write_error = on_write_error; |
|
423 |
dinfo->opts = opts; |
|
424 |
if (serial) |
|
425 |
strncpy(dinfo->serial, serial, sizeof(serial)); |
|
426 |
QTAILQ_INSERT_TAIL(&drives, dinfo, next); |
|
427 |
|
|
428 |
switch(type) { |
|
429 |
case IF_IDE: |
|
430 |
case IF_SCSI: |
|
431 |
case IF_XEN: |
|
432 |
case IF_NONE: |
|
433 |
switch(media) { |
|
434 |
case MEDIA_DISK: |
|
435 |
if (cyls != 0) { |
|
436 |
bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs); |
|
437 |
bdrv_set_translation_hint(dinfo->bdrv, translation); |
|
438 |
} |
|
439 |
break; |
|
440 |
case MEDIA_CDROM: |
|
441 |
bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM); |
|
442 |
break; |
|
443 |
} |
|
444 |
break; |
|
445 |
case IF_SD: |
|
446 |
/* FIXME: This isn't really a floppy, but it's a reasonable |
|
447 |
approximation. */ |
|
448 |
case IF_FLOPPY: |
|
449 |
bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY); |
|
450 |
break; |
|
451 |
case IF_PFLASH: |
|
452 |
case IF_MTD: |
|
453 |
break; |
|
454 |
case IF_VIRTIO: |
|
455 |
/* add virtio block device */ |
|
456 |
opts = qemu_opts_create(&qemu_device_opts, NULL, 0); |
|
457 |
qemu_opt_set(opts, "driver", "virtio-blk-pci"); |
|
458 |
qemu_opt_set(opts, "drive", dinfo->id); |
|
459 |
if (devaddr) |
|
460 |
qemu_opt_set(opts, "addr", devaddr); |
|
461 |
break; |
|
462 |
case IF_COUNT: |
|
463 |
abort(); |
|
464 |
} |
|
465 |
if (!file) { |
|
466 |
*fatal_error = 0; |
|
467 |
return NULL; |
|
468 |
} |
|
469 |
if (snapshot) { |
|
470 |
/* always use cache=unsafe with snapshot */ |
|
471 |
bdrv_flags &= ~BDRV_O_CACHE_MASK; |
|
472 |
bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH); |
|
473 |
} |
|
474 |
|
|
475 |
if (media == MEDIA_CDROM) { |
|
476 |
/* CDROM is fine for any interface, don't check. */ |
|
477 |
ro = 1; |
|
478 |
} else if (ro == 1) { |
|
479 |
if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) { |
|
480 |
fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n"); |
|
481 |
return NULL; |
|
482 |
} |
|
483 |
} |
|
484 |
|
|
485 |
bdrv_flags |= ro ? 0 : BDRV_O_RDWR; |
|
486 |
|
|
487 |
ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv); |
|
488 |
if (ret < 0) { |
|
489 |
fprintf(stderr, "qemu: could not open disk image %s: %s\n", |
|
490 |
file, strerror(-ret)); |
|
491 |
return NULL; |
|
492 |
} |
|
493 |
|
|
494 |
if (bdrv_key_required(dinfo->bdrv)) |
|
495 |
autostart = 0; |
|
496 |
*fatal_error = 0; |
|
497 |
return dinfo; |
|
498 |
} |
|
499 |
|
|
500 |
void do_commit(Monitor *mon, const QDict *qdict) |
|
501 |
{ |
|
502 |
int all_devices; |
|
503 |
DriveInfo *dinfo; |
|
504 |
const char *device = qdict_get_str(qdict, "device"); |
|
505 |
|
|
506 |
all_devices = !strcmp(device, "all"); |
|
507 |
QTAILQ_FOREACH(dinfo, &drives, next) { |
|
508 |
if (!all_devices) |
|
509 |
if (strcmp(bdrv_get_device_name(dinfo->bdrv), device)) |
|
510 |
continue; |
|
511 |
bdrv_commit(dinfo->bdrv); |
|
512 |
} |
|
513 |
} |
|
514 |
|
|
515 |
static int eject_device(Monitor *mon, BlockDriverState *bs, int force) |
|
516 |
{ |
|
517 |
if (bdrv_is_inserted(bs)) { |
|
518 |
if (!force) { |
|
519 |
if (!bdrv_is_removable(bs)) { |
|
520 |
qerror_report(QERR_DEVICE_NOT_REMOVABLE, |
|
521 |
bdrv_get_device_name(bs)); |
|
522 |
return -1; |
|
523 |
} |
|
524 |
if (bdrv_is_locked(bs)) { |
|
525 |
qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs)); |
|
526 |
return -1; |
|
527 |
} |
|
528 |
} |
|
529 |
bdrv_close(bs); |
|
530 |
} |
|
531 |
return 0; |
|
532 |
} |
|
533 |
|
|
534 |
int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data) |
|
535 |
{ |
|
536 |
BlockDriverState *bs; |
|
537 |
int force = qdict_get_int(qdict, "force"); |
|
538 |
const char *filename = qdict_get_str(qdict, "device"); |
|
539 |
|
|
540 |
bs = bdrv_find(filename); |
|
541 |
if (!bs) { |
|
542 |
qerror_report(QERR_DEVICE_NOT_FOUND, filename); |
|
543 |
return -1; |
|
544 |
} |
|
545 |
return eject_device(mon, bs, force); |
|
546 |
} |
|
547 |
|
|
548 |
int do_block_set_passwd(Monitor *mon, const QDict *qdict, |
|
549 |
QObject **ret_data) |
|
550 |
{ |
|
551 |
BlockDriverState *bs; |
|
552 |
int err; |
|
553 |
|
|
554 |
bs = bdrv_find(qdict_get_str(qdict, "device")); |
|
555 |
if (!bs) { |
|
556 |
qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device")); |
|
557 |
return -1; |
|
558 |
} |
|
559 |
|
|
560 |
err = bdrv_set_key(bs, qdict_get_str(qdict, "password")); |
|
561 |
if (err == -EINVAL) { |
|
562 |
qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs)); |
|
563 |
return -1; |
|
564 |
} else if (err < 0) { |
|
565 |
qerror_report(QERR_INVALID_PASSWORD); |
|
566 |
return -1; |
|
567 |
} |
|
568 |
|
|
569 |
return 0; |
|
570 |
} |
|
571 |
|
|
572 |
int do_change_block(Monitor *mon, const char *device, |
|
573 |
const char *filename, const char *fmt) |
|
574 |
{ |
|
575 |
BlockDriverState *bs; |
|
576 |
BlockDriver *drv = NULL; |
|
577 |
int bdrv_flags; |
|
578 |
|
|
579 |
bs = bdrv_find(device); |
|
580 |
if (!bs) { |
|
581 |
qerror_report(QERR_DEVICE_NOT_FOUND, device); |
|
582 |
return -1; |
|
583 |
} |
|
584 |
if (fmt) { |
|
585 |
drv = bdrv_find_whitelisted_format(fmt); |
|
586 |
if (!drv) { |
|
587 |
qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt); |
|
588 |
return -1; |
|
589 |
} |
|
590 |
} |
|
591 |
if (eject_device(mon, bs, 0) < 0) { |
|
592 |
return -1; |
|
593 |
} |
|
594 |
bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR; |
|
595 |
if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) { |
|
596 |
qerror_report(QERR_OPEN_FILE_FAILED, filename); |
|
597 |
return -1; |
|
598 |
} |
|
599 |
return monitor_read_bdrv_key_start(mon, bs, NULL, NULL); |
|
600 |
} |
b/blockdev.h | ||
---|---|---|
1 |
/* |
|
2 |
* QEMU host block devices |
|
3 |
* |
|
4 |
* Copyright (c) 2003-2008 Fabrice Bellard |
|
5 |
* |
|
6 |
* This work is licensed under the terms of the GNU GPL, version 2 or |
|
7 |
* later. See the COPYING file in the top-level directory. |
|
8 |
*/ |
|
9 |
|
|
10 |
#ifndef BLOCKDEV_H |
|
11 |
#define BLOCKDEV_H |
|
12 |
|
|
13 |
#include "block.h" |
|
14 |
#include "qemu-queue.h" |
|
15 |
|
|
16 |
typedef enum { |
|
17 |
IF_NONE, |
|
18 |
IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, |
|
19 |
IF_COUNT |
|
20 |
} BlockInterfaceType; |
|
21 |
|
|
22 |
typedef enum { |
|
23 |
BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC, |
|
24 |
BLOCK_ERR_STOP_ANY |
|
25 |
} BlockInterfaceErrorAction; |
|
26 |
|
|
27 |
#define BLOCK_SERIAL_STRLEN 20 |
|
28 |
|
|
29 |
typedef struct DriveInfo { |
|
30 |
BlockDriverState *bdrv; |
|
31 |
char *id; |
|
32 |
const char *devaddr; |
|
33 |
BlockInterfaceType type; |
|
34 |
int bus; |
|
35 |
int unit; |
|
36 |
QemuOpts *opts; |
|
37 |
BlockInterfaceErrorAction on_read_error; |
|
38 |
BlockInterfaceErrorAction on_write_error; |
|
39 |
char serial[BLOCK_SERIAL_STRLEN + 1]; |
|
40 |
QTAILQ_ENTRY(DriveInfo) next; |
|
41 |
} DriveInfo; |
|
42 |
|
|
43 |
#define MAX_IDE_DEVS 2 |
|
44 |
#define MAX_SCSI_DEVS 7 |
|
45 |
|
|
46 |
extern QTAILQ_HEAD(drivelist, DriveInfo) drives; |
|
47 |
|
|
48 |
extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); |
|
49 |
extern DriveInfo *drive_get_by_id(const char *id); |
|
50 |
extern int drive_get_max_bus(BlockInterfaceType type); |
|
51 |
extern void drive_uninit(DriveInfo *dinfo); |
|
52 |
extern const char *drive_get_serial(BlockDriverState *bdrv); |
|
53 |
|
|
54 |
extern BlockInterfaceErrorAction drive_get_on_error( |
|
55 |
BlockDriverState *bdrv, int is_read); |
|
56 |
|
|
57 |
extern QemuOpts *drive_add(const char *file, const char *fmt, ...); |
|
58 |
extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, |
|
59 |
int *fatal_error); |
|
60 |
|
|
61 |
/* device-hotplug */ |
|
62 |
|
|
63 |
DriveInfo *add_init_drive(const char *opts); |
|
64 |
|
|
65 |
void do_commit(Monitor *mon, const QDict *qdict); |
|
66 |
int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data); |
|
67 |
int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data); |
|
68 |
int do_change_block(Monitor *mon, const char *device, |
|
69 |
const char *filename, const char *fmt); |
|
70 |
|
|
71 |
#endif |
b/hw/acpi_piix4.c | ||
---|---|---|
21 | 21 |
#include "pm_smbus.h" |
22 | 22 |
#include "pci.h" |
23 | 23 |
#include "acpi.h" |
24 |
#include "sysemu.h" |
|
24 | 25 |
|
25 | 26 |
//#define DEBUG |
26 | 27 |
|
b/hw/apb_pci.c | ||
---|---|---|
31 | 31 |
#include "pci_host.h" |
32 | 32 |
#include "rwhandler.h" |
33 | 33 |
#include "apb_pci.h" |
34 |
#include "sysemu.h" |
|
34 | 35 |
|
35 | 36 |
/* debug APB */ |
36 | 37 |
//#define DEBUG_APB |
b/hw/device-hotplug.c | ||
---|---|---|
25 | 25 |
#include "hw.h" |
26 | 26 |
#include "boards.h" |
27 | 27 |
#include "net.h" |
28 |
#include "block_int.h" |
|
29 |
#include "sysemu.h" |
|
30 | 28 |
|
31 | 29 |
DriveInfo *add_init_drive(const char *optstr) |
32 | 30 |
{ |
b/hw/fdc.c | ||
---|---|---|
29 | 29 |
|
30 | 30 |
#include "hw.h" |
31 | 31 |
#include "fdc.h" |
32 |
#include "block.h" |
|
33 | 32 |
#include "qemu-timer.h" |
34 | 33 |
#include "isa.h" |
35 | 34 |
#include "sysbus.h" |
b/hw/fdc.h | ||
---|---|---|
2 | 2 |
#define HW_FDC_H |
3 | 3 |
|
4 | 4 |
/* fdc.c */ |
5 |
#include "sysemu.h"
|
|
5 |
#include "blockdev.h"
|
|
6 | 6 |
#define MAX_FD 2 |
7 | 7 |
|
8 | 8 |
typedef struct FDCtrl FDCtrl; |
b/hw/ide/core.c | ||
---|---|---|
26 | 26 |
#include <hw/pc.h> |
27 | 27 |
#include <hw/pci.h> |
28 | 28 |
#include <hw/scsi.h> |
29 |
#include "block.h" |
|
30 |
#include "block_int.h" |
|
31 | 29 |
#include "qemu-timer.h" |
32 | 30 |
#include "sysemu.h" |
33 | 31 |
#include "dma.h" |
b/hw/ide/qdev.c | ||
---|---|---|
17 | 17 |
* License along with this library; if not, see <http://www.gnu.org/licenses/>. |
18 | 18 |
*/ |
19 | 19 |
#include <hw/hw.h> |
20 |
#include "sysemu.h" |
|
21 | 20 |
#include "dma.h" |
22 | 21 |
|
23 | 22 |
#include <hw/ide/internal.h> |
b/hw/lan9118.c | ||
---|---|---|
10 | 10 |
#include "sysbus.h" |
11 | 11 |
#include "net.h" |
12 | 12 |
#include "devices.h" |
13 |
#include "sysemu.h" |
|
13 | 14 |
/* For crc32 */ |
14 | 15 |
#include <zlib.h> |
15 | 16 |
|
b/hw/nand.c | ||
---|---|---|
13 | 13 |
|
14 | 14 |
# include "hw.h" |
15 | 15 |
# include "flash.h" |
16 |
# include "block.h" |
|
16 |
# include "blockdev.h"
|
|
17 | 17 |
/* FIXME: Pass block device as an argument. */ |
18 |
# include "sysemu.h" |
|
19 | 18 |
|
20 | 19 |
# define NAND_CMD_READ0 0x00 |
21 | 20 |
# define NAND_CMD_READ1 0x01 |
b/hw/omap2.c | ||
---|---|---|
17 | 17 |
* You should have received a copy of the GNU General Public License along |
18 | 18 |
* with this program; if not, see <http://www.gnu.org/licenses/>. |
19 | 19 |
*/ |
20 |
|
|
21 |
#include "blockdev.h" |
|
20 | 22 |
#include "hw.h" |
21 | 23 |
#include "arm-misc.h" |
22 | 24 |
#include "omap.h" |
b/hw/onenand.c | ||
---|---|---|
21 | 21 |
#include "qemu-common.h" |
22 | 22 |
#include "flash.h" |
23 | 23 |
#include "irq.h" |
24 |
#include "sysemu.h" |
|
25 |
#include "block.h" |
|
24 |
#include "blockdev.h" |
|
26 | 25 |
|
27 | 26 |
/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */ |
28 | 27 |
#define PAGE_SHIFT 11 |
b/hw/parallel.c | ||
---|---|---|
26 | 26 |
#include "qemu-char.h" |
27 | 27 |
#include "isa.h" |
28 | 28 |
#include "pc.h" |
29 |
#include "sysemu.h" |
|
29 | 30 |
|
30 | 31 |
//#define DEBUG_PARALLEL |
31 | 32 |
|
b/hw/pc.c | ||
---|---|---|
35 | 35 |
#include "elf.h" |
36 | 36 |
#include "multiboot.h" |
37 | 37 |
#include "mc146818rtc.h" |
38 |
#include "sysemu.h" |
|
38 | 39 |
|
39 | 40 |
/* output Bochs bios info messages */ |
40 | 41 |
//#define DEBUG_BIOS |
b/hw/pc_piix.c | ||
---|---|---|
32 | 32 |
#include "boards.h" |
33 | 33 |
#include "ide.h" |
34 | 34 |
#include "kvm.h" |
35 |
#include "sysemu.h" |
|
35 | 36 |
|
36 | 37 |
#define MAX_IDE_BUS 2 |
37 | 38 |
|
b/hw/pci-hotplug.c | ||
---|---|---|
26 | 26 |
#include "boards.h" |
27 | 27 |
#include "pci.h" |
28 | 28 |
#include "net.h" |
29 |
#include "sysemu.h" |
|
30 | 29 |
#include "pc.h" |
31 | 30 |
#include "monitor.h" |
32 |
#include "block_int.h" |
|
33 | 31 |
#include "scsi.h" |
34 | 32 |
#include "virtio-blk.h" |
35 | 33 |
#include "qemu-config.h" |
b/hw/pcmcia.h | ||
---|---|---|
1 | 1 |
/* PCMCIA/Cardbus */ |
2 | 2 |
|
3 | 3 |
#include "qemu-common.h" |
4 |
#include "sysemu.h"
|
|
4 |
#include "blockdev.h"
|
|
5 | 5 |
|
6 | 6 |
typedef struct { |
7 | 7 |
qemu_irq irq; |
b/hw/qdev-properties.c | ||
---|---|---|
1 |
#include "sysemu.h" |
|
2 | 1 |
#include "net.h" |
3 | 2 |
#include "qdev.h" |
4 | 3 |
#include "qerror.h" |
b/hw/qdev.h | ||
---|---|---|
2 | 2 |
#define QDEV_H |
3 | 3 |
|
4 | 4 |
#include "hw.h" |
5 |
#include "sysemu.h"
|
|
5 |
#include "blockdev.h"
|
|
6 | 6 |
#include "qemu-queue.h" |
7 | 7 |
#include "qemu-char.h" |
8 | 8 |
#include "qemu-option.h" |
b/hw/scsi-bus.c | ||
---|---|---|
2 | 2 |
#include "qemu-error.h" |
3 | 3 |
#include "scsi.h" |
4 | 4 |
#include "scsi-defs.h" |
5 |
#include "block.h" |
|
6 | 5 |
#include "qdev.h" |
7 | 6 |
|
8 | 7 |
static struct BusInfo scsi_bus_info = { |
b/hw/scsi-disk.c | ||
---|---|---|
33 | 33 |
|
34 | 34 |
#include "qemu-common.h" |
35 | 35 |
#include "qemu-error.h" |
36 |
#include "block.h" |
|
37 | 36 |
#include "scsi.h" |
38 | 37 |
#include "scsi-defs.h" |
38 |
#include "sysemu.h" |
|
39 | 39 |
|
40 | 40 |
#define SCSI_DMA_BUF_SIZE 131072 |
41 | 41 |
#define SCSI_MAX_INQUIRY_LEN 256 |
b/hw/scsi-generic.c | ||
---|---|---|
13 | 13 |
|
14 | 14 |
#include "qemu-common.h" |
15 | 15 |
#include "qemu-error.h" |
16 |
#include "block.h" |
|
17 | 16 |
#include "scsi.h" |
18 | 17 |
|
19 | 18 |
#ifdef __linux__ |
b/hw/serial.c | ||
---|---|---|
27 | 27 |
#include "isa.h" |
28 | 28 |
#include "pc.h" |
29 | 29 |
#include "qemu-timer.h" |
30 |
#include "sysemu.h" |
|
30 | 31 |
|
31 | 32 |
//#define DEBUG_SERIAL |
32 | 33 |
|
b/hw/usb-hid.c | ||
---|---|---|
25 | 25 |
#include "hw.h" |
26 | 26 |
#include "console.h" |
27 | 27 |
#include "usb.h" |
28 |
#include "sysemu.h" |
|
28 | 29 |
|
29 | 30 |
/* HID interface requests */ |
30 | 31 |
#define GET_REPORT 0xa101 |
b/hw/usb-msd.c | ||
---|---|---|
11 | 11 |
#include "qemu-option.h" |
12 | 12 |
#include "qemu-config.h" |
13 | 13 |
#include "usb.h" |
14 |
#include "block.h" |
|
15 | 14 |
#include "scsi.h" |
16 | 15 |
#include "console.h" |
17 | 16 |
#include "monitor.h" |
17 |
#include "sysemu.h" |
|
18 | 18 |
|
19 | 19 |
//#define DEBUG_MSD |
20 | 20 |
|
b/hw/virtio-blk.c | ||
---|---|---|
12 | 12 |
*/ |
13 | 13 |
|
14 | 14 |
#include <qemu-common.h> |
15 |
#include <sysemu.h> |
|
16 | 15 |
#include "virtio-blk.h" |
17 |
#include "block_int.h" |
|
18 | 16 |
#ifdef __linux__ |
19 | 17 |
# include <scsi/sg.h> |
20 | 18 |
#endif |
b/hw/virtio-pci.c | ||
---|---|---|
22 | 22 |
#include "qemu-error.h" |
23 | 23 |
#include "msix.h" |
24 | 24 |
#include "net.h" |
25 |
#include "block_int.h" |
|
26 | 25 |
#include "loader.h" |
27 | 26 |
#include "kvm.h" |
28 | 27 |
|
b/monitor.c | ||
---|---|---|
38 | 38 |
#include "monitor.h" |
39 | 39 |
#include "readline.h" |
40 | 40 |
#include "console.h" |
41 |
#include "block.h" |
|
41 |
#include "blockdev.h"
|
|
42 | 42 |
#include "audio/audio.h" |
43 | 43 |
#include "disas.h" |
44 | 44 |
#include "balloon.h" |
... | ... | |
530 | 530 |
help_cmd(mon, qdict_get_try_str(qdict, "name")); |
531 | 531 |
} |
532 | 532 |
|
533 |
static void do_commit(Monitor *mon, const QDict *qdict) |
|
534 |
{ |
|
535 |
int all_devices; |
|
536 |
DriveInfo *dinfo; |
|
537 |
const char *device = qdict_get_str(qdict, "device"); |
|
538 |
|
|
539 |
all_devices = !strcmp(device, "all"); |
|
540 |
QTAILQ_FOREACH(dinfo, &drives, next) { |
|
541 |
if (!all_devices) |
|
542 |
if (strcmp(bdrv_get_device_name(dinfo->bdrv), device)) |
|
543 |
continue; |
|
544 |
bdrv_commit(dinfo->bdrv); |
|
545 |
} |
|
546 |
} |
|
547 |
|
|
548 | 533 |
static void user_monitor_complete(void *opaque, QObject *ret_data) |
549 | 534 |
{ |
550 | 535 |
MonitorCompletionData *data = (MonitorCompletionData *)opaque; |
... | ... | |
949 | 934 |
return 0; |
950 | 935 |
} |
951 | 936 |
|
952 |
static int eject_device(Monitor *mon, BlockDriverState *bs, int force) |
|
953 |
{ |
|
954 |
if (bdrv_is_inserted(bs)) { |
|
955 |
if (!force) { |
|
956 |
if (!bdrv_is_removable(bs)) { |
|
957 |
qerror_report(QERR_DEVICE_NOT_REMOVABLE, |
|
958 |
bdrv_get_device_name(bs)); |
|
959 |
return -1; |
|
960 |
} |
|
961 |
if (bdrv_is_locked(bs)) { |
|
962 |
qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs)); |
|
963 |
return -1; |
|
964 |
} |
|
965 |
} |
|
966 |
bdrv_close(bs); |
|
967 |
} |
|
968 |
return 0; |
|
969 |
} |
|
970 |
|
|
971 |
static int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data) |
|
972 |
{ |
|
973 |
BlockDriverState *bs; |
|
974 |
int force = qdict_get_int(qdict, "force"); |
|
975 |
const char *filename = qdict_get_str(qdict, "device"); |
|
976 |
|
|
977 |
bs = bdrv_find(filename); |
|
978 |
if (!bs) { |
|
979 |
qerror_report(QERR_DEVICE_NOT_FOUND, filename); |
|
980 |
return -1; |
|
981 |
} |
|
982 |
return eject_device(mon, bs, force); |
|
983 |
} |
|
984 |
|
|
985 |
static int do_block_set_passwd(Monitor *mon, const QDict *qdict, |
|
986 |
QObject **ret_data) |
|
987 |
{ |
|
988 |
BlockDriverState *bs; |
|
989 |
int err; |
|
990 |
|
|
991 |
bs = bdrv_find(qdict_get_str(qdict, "device")); |
|
992 |
if (!bs) { |
|
993 |
qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device")); |
|
994 |
return -1; |
|
995 |
} |
|
996 |
|
|
997 |
err = bdrv_set_key(bs, qdict_get_str(qdict, "password")); |
|
998 |
if (err == -EINVAL) { |
|
999 |
qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs)); |
|
1000 |
return -1; |
|
1001 |
} else if (err < 0) { |
|
1002 |
qerror_report(QERR_INVALID_PASSWORD); |
|
1003 |
return -1; |
|
1004 |
} |
|
1005 |
|
|
1006 |
return 0; |
|
1007 |
} |
|
1008 |
|
|
1009 |
static int do_change_block(Monitor *mon, const char *device, |
|
1010 |
const char *filename, const char *fmt) |
|
1011 |
{ |
|
1012 |
BlockDriverState *bs; |
|
1013 |
BlockDriver *drv = NULL; |
|
1014 |
int bdrv_flags; |
|
1015 |
|
|
1016 |
bs = bdrv_find(device); |
|
1017 |
if (!bs) { |
|
1018 |
qerror_report(QERR_DEVICE_NOT_FOUND, device); |
|
1019 |
return -1; |
|
1020 |
} |
|
1021 |
if (fmt) { |
|
1022 |
drv = bdrv_find_whitelisted_format(fmt); |
|
1023 |
if (!drv) { |
|
1024 |
qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt); |
|
1025 |
return -1; |
|
1026 |
} |
|
1027 |
} |
|
1028 |
if (eject_device(mon, bs, 0) < 0) { |
|
1029 |
return -1; |
|
1030 |
} |
|
1031 |
bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR; |
|
1032 |
if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) { |
|
1033 |
qerror_report(QERR_OPEN_FILE_FAILED, filename); |
|
1034 |
return -1; |
|
1035 |
} |
|
1036 |
return monitor_read_bdrv_key_start(mon, bs, NULL, NULL); |
|
1037 |
} |
|
1038 |
|
|
1039 | 937 |
static int change_vnc_password(const char *password) |
1040 | 938 |
{ |
1041 | 939 |
if (vnc_display_password(NULL, password) < 0) { |
b/qemu-char.c | ||
---|---|---|
28 | 28 |
#include "sysemu.h" |
29 | 29 |
#include "qemu-timer.h" |
30 | 30 |
#include "qemu-char.h" |
31 |
#include "block.h" |
|
32 | 31 |
#include "hw/usb.h" |
33 | 32 |
#include "hw/baum.h" |
34 | 33 |
#include "hw/msmouse.h" |
b/savevm.c | ||
---|---|---|
77 | 77 |
#include "sysemu.h" |
78 | 78 |
#include "qemu-timer.h" |
79 | 79 |
#include "qemu-char.h" |
80 |
#include "block.h" |
|
80 |
#include "blockdev.h"
|
|
81 | 81 |
#include "audio/audio.h" |
82 | 82 |
#include "migration.h" |
83 | 83 |
#include "qemu_socket.h" |
b/sysemu.h | ||
---|---|---|
147 | 147 |
extern const char *prom_envs[MAX_PROM_ENVS]; |
148 | 148 |
extern unsigned int nb_prom_envs; |
149 | 149 |
|
150 |
typedef enum { |
|
151 |
IF_NONE, |
|
152 |
IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, |
|
153 |
IF_COUNT |
|
154 |
} BlockInterfaceType; |
|
155 |
|
|
156 |
typedef enum { |
|
157 |
BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC, |
|
158 |
BLOCK_ERR_STOP_ANY |
|
159 |
} BlockInterfaceErrorAction; |
|
160 |
|
|
161 |
#define BLOCK_SERIAL_STRLEN 20 |
|
162 |
|
|
163 |
typedef struct DriveInfo { |
|
164 |
BlockDriverState *bdrv; |
|
165 |
char *id; |
|
166 |
const char *devaddr; |
|
167 |
BlockInterfaceType type; |
|
168 |
int bus; |
|
169 |
int unit; |
|
170 |
QemuOpts *opts; |
|
171 |
BlockInterfaceErrorAction on_read_error; |
|
172 |
BlockInterfaceErrorAction on_write_error; |
|
173 |
char serial[BLOCK_SERIAL_STRLEN + 1]; |
|
174 |
QTAILQ_ENTRY(DriveInfo) next; |
|
175 |
} DriveInfo; |
|
176 |
|
|
177 |
#define MAX_IDE_DEVS 2 |
|
178 |
#define MAX_SCSI_DEVS 7 |
|
179 |
|
|
180 |
extern QTAILQ_HEAD(drivelist, DriveInfo) drives; |
|
181 |
|
|
182 |
extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); |
|
183 |
extern DriveInfo *drive_get_by_id(const char *id); |
|
184 |
extern int drive_get_max_bus(BlockInterfaceType type); |
|
185 |
extern void drive_uninit(DriveInfo *dinfo); |
|
186 |
extern const char *drive_get_serial(BlockDriverState *bdrv); |
|
187 |
|
|
188 |
extern BlockInterfaceErrorAction drive_get_on_error( |
|
189 |
BlockDriverState *bdrv, int is_read); |
|
190 |
|
|
191 |
extern QemuOpts *drive_add(const char *file, const char *fmt, ...); |
|
192 |
extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, |
|
193 |
int *fatal_error); |
|
194 |
|
|
195 |
/* device-hotplug */ |
|
196 |
|
|
197 |
DriveInfo *add_init_drive(const char *opts); |
|
198 |
|
|
199 | 150 |
/* pci-hotplug */ |
200 | 151 |
void pci_device_hot_add(Monitor *mon, const QDict *qdict); |
201 | 152 |
void drive_hot_add(Monitor *mon, const QDict *qdict); |
b/vl.c | ||
---|---|---|
140 | 140 |
#include "qemu-char.h" |
141 | 141 |
#include "cache-utils.h" |
142 | 142 |
#include "block.h" |
143 |
#include "block_int.h"
|
|
143 |
#include "blockdev.h"
|
|
144 | 144 |
#include "block-migration.h" |
145 | 145 |
#include "dma.h" |
146 | 146 |
#include "audio/audio.h" |
... | ... | |
172 | 172 |
|
173 | 173 |
static const char *data_dir; |
174 | 174 |
const char *bios_name = NULL; |
175 |
struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives); |
|
176 | 175 |
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; |
177 | 176 |
DisplayType display_type = DT_DEFAULT; |
178 | 177 |
const char* keyboard_layout = NULL; |
... | ... | |
651 | 650 |
#define MTD_ALIAS "if=mtd" |
652 | 651 |
#define SD_ALIAS "index=0,if=sd" |
653 | 652 |
|
654 |
QemuOpts *drive_add(const char *file, const char *fmt, ...) |
|
655 |
{ |
|
656 |
va_list ap; |
|
657 |
char optstr[1024]; |
|
658 |
QemuOpts *opts; |
|
659 |
|
|
660 |
va_start(ap, fmt); |
|
661 |
vsnprintf(optstr, sizeof(optstr), fmt, ap); |
|
662 |
va_end(ap); |
|
663 |
|
|
664 |
opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0); |
|
665 |
if (!opts) { |
|
666 |
return NULL; |
|
667 |
} |
|
668 |
if (file) |
|
669 |
qemu_opt_set(opts, "file", file); |
|
670 |
return opts; |
|
671 |
} |
|
672 |
|
|
673 |
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) |
|
674 |
{ |
|
675 |
DriveInfo *dinfo; |
|
676 |
|
|
677 |
/* seek interface, bus and unit */ |
|
678 |
|
|
679 |
QTAILQ_FOREACH(dinfo, &drives, next) { |
|
680 |
if (dinfo->type == type && |
|
681 |
dinfo->bus == bus && |
|
682 |
dinfo->unit == unit) |
|
683 |
return dinfo; |
|
684 |
} |
|
685 |
|
|
686 |
return NULL; |
|
687 |
} |
|
688 |
|
|
689 |
DriveInfo *drive_get_by_id(const char *id) |
|
690 |
{ |
|
691 |
DriveInfo *dinfo; |
|
692 |
|
|
693 |
QTAILQ_FOREACH(dinfo, &drives, next) { |
|
694 |
if (strcmp(id, dinfo->id)) |
|
695 |
continue; |
|
696 |
return dinfo; |
|
697 |
} |
|
698 |
return NULL; |
|
699 |
} |
|
700 |
|
|
701 |
int drive_get_max_bus(BlockInterfaceType type) |
|
702 |
{ |
|
703 |
int max_bus; |
|
704 |
DriveInfo *dinfo; |
|
705 |
|
|
706 |
max_bus = -1; |
|
707 |
QTAILQ_FOREACH(dinfo, &drives, next) { |
|
708 |
if(dinfo->type == type && |
|
709 |
dinfo->bus > max_bus) |
|
710 |
max_bus = dinfo->bus; |
|
711 |
} |
|
712 |
return max_bus; |
|
713 |
} |
|
714 |
|
|
715 |
const char *drive_get_serial(BlockDriverState *bdrv) |
|
716 |
{ |
|
717 |
DriveInfo *dinfo; |
|
718 |
|
|
719 |
QTAILQ_FOREACH(dinfo, &drives, next) { |
|
720 |
if (dinfo->bdrv == bdrv) |
|
721 |
return dinfo->serial; |
|
722 |
} |
|
723 |
|
|
724 |
return "\0"; |
|
725 |
} |
|
726 |
|
|
727 |
BlockInterfaceErrorAction drive_get_on_error( |
|
728 |
BlockDriverState *bdrv, int is_read) |
|
729 |
{ |
|
730 |
DriveInfo *dinfo; |
|
731 |
|
|
732 |
QTAILQ_FOREACH(dinfo, &drives, next) { |
|
733 |
if (dinfo->bdrv == bdrv) |
|
734 |
return is_read ? dinfo->on_read_error : dinfo->on_write_error; |
|
735 |
} |
|
736 |
|
|
737 |
return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC; |
|
738 |
} |
|
739 |
|
|
740 |
static void bdrv_format_print(void *opaque, const char *name) |
|
741 |
{ |
|
742 |
fprintf(stderr, " %s", name); |
|
743 |
} |
|
744 |
|
|
745 |
void drive_uninit(DriveInfo *dinfo) |
|
746 |
{ |
|
747 |
qemu_opts_del(dinfo->opts); |
|
748 |
bdrv_delete(dinfo->bdrv); |
|
749 |
QTAILQ_REMOVE(&drives, dinfo, next); |
|
750 |
qemu_free(dinfo); |
|
751 |
} |
|
752 |
|
|
753 |
static int parse_block_error_action(const char *buf, int is_read) |
|
754 |
{ |
|
755 |
if (!strcmp(buf, "ignore")) { |
|
756 |
return BLOCK_ERR_IGNORE; |
|
757 |
} else if (!is_read && !strcmp(buf, "enospc")) { |
|
758 |
return BLOCK_ERR_STOP_ENOSPC; |
|
759 |
} else if (!strcmp(buf, "stop")) { |
|
760 |
return BLOCK_ERR_STOP_ANY; |
|
761 |
} else if (!strcmp(buf, "report")) { |
|
762 |
return BLOCK_ERR_REPORT; |
|
763 |
} else { |
|
764 |
fprintf(stderr, "qemu: '%s' invalid %s error action\n", |
|
765 |
buf, is_read ? "read" : "write"); |
|
766 |
return -1; |
|
767 |
} |
|
768 |
} |
|
769 |
|
|
770 |
DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) |
|
771 |
{ |
|
772 |
const char *buf; |
|
773 |
const char *file = NULL; |
|
774 |
char devname[128]; |
|
775 |
const char *serial; |
|
776 |
const char *mediastr = ""; |
|
777 |
BlockInterfaceType type; |
|
778 |
enum { MEDIA_DISK, MEDIA_CDROM } media; |
|
779 |
int bus_id, unit_id; |
|
780 |
int cyls, heads, secs, translation; |
|
781 |
BlockDriver *drv = NULL; |
|
782 |
int max_devs; |
|
783 |
int index; |
|
784 |
int ro = 0; |
|
785 |
int bdrv_flags = 0; |
|
786 |
int on_read_error, on_write_error; |
|
787 |
const char *devaddr; |
|
788 |
DriveInfo *dinfo; |
|
789 |
int snapshot = 0; |
|
790 |
int ret; |
|
791 |
|
|
792 |
*fatal_error = 1; |
|
793 |
|
|
794 |
translation = BIOS_ATA_TRANSLATION_AUTO; |
|
795 |
|
|
796 |
if (default_to_scsi) { |
|
797 |
type = IF_SCSI; |
|
798 |
max_devs = MAX_SCSI_DEVS; |
|
799 |
pstrcpy(devname, sizeof(devname), "scsi"); |
|
800 |
} else { |
|
801 |
type = IF_IDE; |
|
802 |
max_devs = MAX_IDE_DEVS; |
|
803 |
pstrcpy(devname, sizeof(devname), "ide"); |
|
804 |
} |
|
805 |
media = MEDIA_DISK; |
|
806 |
|
|
807 |
/* extract parameters */ |
|
808 |
bus_id = qemu_opt_get_number(opts, "bus", 0); |
|
809 |
unit_id = qemu_opt_get_number(opts, "unit", -1); |
|
810 |
index = qemu_opt_get_number(opts, "index", -1); |
|
811 |
|
|
812 |
cyls = qemu_opt_get_number(opts, "cyls", 0); |
|
813 |
heads = qemu_opt_get_number(opts, "heads", 0); |
|
814 |
secs = qemu_opt_get_number(opts, "secs", 0); |
|
815 |
|
|
816 |
snapshot = qemu_opt_get_bool(opts, "snapshot", 0); |
|
817 |
ro = qemu_opt_get_bool(opts, "readonly", 0); |
|
818 |
|
|
819 |
file = qemu_opt_get(opts, "file"); |
|
820 |
serial = qemu_opt_get(opts, "serial"); |
|
821 |
|
|
822 |
if ((buf = qemu_opt_get(opts, "if")) != NULL) { |
|
823 |
pstrcpy(devname, sizeof(devname), buf); |
|
824 |
if (!strcmp(buf, "ide")) { |
|
825 |
type = IF_IDE; |
|
826 |
max_devs = MAX_IDE_DEVS; |
|
827 |
} else if (!strcmp(buf, "scsi")) { |
|
828 |
type = IF_SCSI; |
|
829 |
max_devs = MAX_SCSI_DEVS; |
|
830 |
} else if (!strcmp(buf, "floppy")) { |
|
831 |
type = IF_FLOPPY; |
|
832 |
max_devs = 0; |
|
833 |
} else if (!strcmp(buf, "pflash")) { |
|
834 |
type = IF_PFLASH; |
|
835 |
max_devs = 0; |
|
836 |
} else if (!strcmp(buf, "mtd")) { |
|
837 |
type = IF_MTD; |
|
838 |
max_devs = 0; |
|
839 |
} else if (!strcmp(buf, "sd")) { |
|
840 |
type = IF_SD; |
|
841 |
max_devs = 0; |
|
842 |
} else if (!strcmp(buf, "virtio")) { |
|
843 |
type = IF_VIRTIO; |
|
844 |
max_devs = 0; |
|
845 |
} else if (!strcmp(buf, "xen")) { |
|
846 |
type = IF_XEN; |
|
847 |
max_devs = 0; |
|
848 |
} else if (!strcmp(buf, "none")) { |
|
849 |
type = IF_NONE; |
|
850 |
max_devs = 0; |
|
851 |
} else { |
|
852 |
fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf); |
|
853 |
return NULL; |
|
854 |
} |
|
855 |
} |
|
856 |
|
|
857 |
if (cyls || heads || secs) { |
|
858 |
if (cyls < 1 || (type == IF_IDE && cyls > 16383)) { |
|
859 |
fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf); |
|
860 |
return NULL; |
|
861 |
} |
|
862 |
if (heads < 1 || (type == IF_IDE && heads > 16)) { |
|
863 |
fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf); |
|
864 |
return NULL; |
|
865 |
} |
|
866 |
if (secs < 1 || (type == IF_IDE && secs > 63)) { |
|
867 |
fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf); |
|
868 |
return NULL; |
|
869 |
} |
|
870 |
} |
|
871 |
|
|
872 |
if ((buf = qemu_opt_get(opts, "trans")) != NULL) { |
|
873 |
if (!cyls) { |
|
874 |
fprintf(stderr, |
|
875 |
"qemu: '%s' trans must be used with cyls,heads and secs\n", |
|
876 |
buf); |
Also available in: Unified diff