#include "hw/pcmcia.h"
#include "hw/pc.h"
#include "hw/isa.h"
-#include "hw/baum.h"
#include "hw/bt.h"
#include "hw/watchdog.h"
#include "hw/smbios.h"
#include "hw/xen.h"
#include "hw/qdev.h"
#include "hw/loader.h"
+#include "monitor/qdev.h"
#include "bt/bt.h"
#include "net/net.h"
#include "net/slirp.h"
#include "sysemu/blockdev.h"
#include "hw/block-common.h"
#include "migration/block.h"
+#include "tpm/tpm.h"
#include "sysemu/dma.h"
#include "audio/audio.h"
#include "migration/migration.h"
#define DEFAULT_RAM_SIZE 128
#define MAX_VIRTIO_CONSOLES 1
+#define MAX_SCLP_CONSOLES 1
-static const char *data_dir;
+static const char *data_dir[16];
+static int data_dir_idx;
const char *bios_name = NULL;
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
DisplayType display_type = DT_DEFAULT;
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
+CharDriverState *sclp_hds[MAX_SCLP_CONSOLES];
int win2k_install_hack = 0;
int singlestep = 0;
int smp_cpus = 1;
unsigned int nb_prom_envs = 0;
const char *prom_envs[MAX_PROM_ENVS];
int boot_menu;
+bool boot_strict;
uint8_t *boot_splash_filedata;
-int boot_splash_filedata_size;
+size_t boot_splash_filedata_size;
uint8_t qemu_extra_params_fw[2];
typedef struct FWBootEntry FWBootEntry;
static NotifierList machine_init_done_notifiers =
NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
-static int tcg_allowed = 1;
-int kvm_allowed = 0;
-int xen_allowed = 0;
+static bool tcg_allowed = true;
+bool kvm_allowed;
+bool xen_allowed;
uint32_t xen_domid;
enum xen_mode xen_mode = XEN_EMULATE;
static int tcg_tb_size;
static int default_serial = 1;
static int default_parallel = 1;
static int default_virtcon = 1;
+static int default_sclp = 1;
static int default_monitor = 1;
static int default_floppy = 1;
static int default_cdrom = 1;
}, {
.name = "reboot-timeout",
.type = QEMU_OPT_STRING,
+ }, {
+ .name = "strict",
+ .type = QEMU_OPT_STRING,
},
{ /*End of list */ }
},
},
};
+static QemuOptsList qemu_tpmdev_opts = {
+ .name = "tpmdev",
+ .implied_opt_name = "type",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_tpmdev_opts.head),
+ .desc = {
+ {
+ .name = "type",
+ .type = QEMU_OPT_STRING,
+ .help = "Type of TPM backend",
+ },
+ {
+ .name = "cancel-path",
+ .type = QEMU_OPT_STRING,
+ .help = "Sysfs file entry for canceling TPM commands",
+ },
+ {
+ .name = "path",
+ .type = QEMU_OPT_STRING,
+ .help = "Path to TPM device on the host",
+ },
+ { /* end of list */ }
+ },
+};
+
const char *qemu_get_vm_name(void)
{
return qemu_name;
* memory pointed by "size" is assigned total length of the array in bytes
*
*/
-char *get_boot_devices_list(uint32_t *size)
+char *get_boot_devices_list(size_t *size)
{
FWBootEntry *i;
- uint32_t total = 0;
+ size_t total = 0;
char *list = NULL;
QTAILQ_FOREACH(i, &fw_boot_order, link) {
char *devpath = NULL, *bootpath;
- int len;
+ size_t len;
if (i->dev) {
devpath = qdev_get_fw_dev_path(i->dev);
*size = total;
+ if (boot_strict && *size > 0) {
+ list[total-1] = '\n';
+ list = g_realloc(list, total + 4);
+ memcpy(&list[total], "HALT", 4);
+ *size = total + 4;
+ }
return list;
}
-static void numa_add(const char *optarg)
+static void numa_node_parse_cpus(int nodenr, const char *cpus)
{
- char option[128];
char *endptr;
unsigned long long value, endvalue;
- int nodenr;
- value = endvalue = 0ULL;
+ /* Empty CPU range strings will be considered valid, they will simply
+ * not set any bit in the CPU bitmap.
+ */
+ if (!*cpus) {
+ return;
+ }
- optarg = get_opt_name(option, 128, optarg, ',') + 1;
+ if (parse_uint(cpus, &value, &endptr, 10) < 0) {
+ goto error;
+ }
+ if (*endptr == '-') {
+ if (parse_uint_full(endptr + 1, &endvalue, 10) < 0) {
+ goto error;
+ }
+ } else if (*endptr == '\0') {
+ endvalue = value;
+ } else {
+ goto error;
+ }
+
+ if (endvalue >= MAX_CPUMASK_BITS) {
+ endvalue = MAX_CPUMASK_BITS - 1;
+ fprintf(stderr,
+ "qemu: NUMA: A max of %d VCPUs are supported\n",
+ MAX_CPUMASK_BITS);
+ }
+
+ if (endvalue < value) {
+ goto error;
+ }
+
+ bitmap_set(node_cpumask[nodenr], value, endvalue-value+1);
+ return;
+
+error:
+ fprintf(stderr, "qemu: Invalid NUMA CPU range: %s\n", cpus);
+ exit(1);
+}
+
+static void numa_add(const char *optarg)
+{
+ char option[128];
+ char *endptr;
+ unsigned long long nodenr;
+
+ optarg = get_opt_name(option, 128, optarg, ',');
+ if (*optarg == ',') {
+ optarg++;
+ }
if (!strcmp(option, "node")) {
+
+ if (nb_numa_nodes >= MAX_NODES) {
+ fprintf(stderr, "qemu: too many NUMA nodes\n");
+ exit(1);
+ }
+
if (get_param_value(option, 128, "nodeid", optarg) == 0) {
nodenr = nb_numa_nodes;
} else {
- nodenr = strtoull(option, NULL, 10);
+ if (parse_uint_full(option, &nodenr, 10) < 0) {
+ fprintf(stderr, "qemu: Invalid NUMA nodeid: %s\n", option);
+ exit(1);
+ }
+ }
+
+ if (nodenr >= MAX_NODES) {
+ fprintf(stderr, "qemu: invalid NUMA nodeid: %llu\n", nodenr);
+ exit(1);
}
if (get_param_value(option, 128, "mem", optarg) == 0) {
node_mem[nodenr] = sval;
}
if (get_param_value(option, 128, "cpus", optarg) != 0) {
- value = strtoull(option, &endptr, 10);
- if (*endptr == '-') {
- endvalue = strtoull(endptr+1, &endptr, 10);
- } else {
- endvalue = value;
- }
-
- if (!(endvalue < MAX_CPUMASK_BITS)) {
- endvalue = MAX_CPUMASK_BITS - 1;
- fprintf(stderr,
- "A max of %d CPUs are supported in a guest\n",
- MAX_CPUMASK_BITS);
- }
-
- bitmap_set(node_cpumask[nodenr], value, endvalue-value+1);
+ numa_node_parse_cpus(nodenr, option);
}
nb_numa_nodes++;
+ } else {
+ fprintf(stderr, "Invalid -numa option: %s\n", option);
+ exit(1);
}
}
int bus_num, addr;
const char *p;
- if (strstart(devname, "host:", &p))
- return usb_host_device_close(p);
+ if (strstart(devname, "host:", &p)) {
+ return -1;
+ }
if (!usb_enabled(false)) {
return -1;
}
}
-void pcmcia_info(Monitor *mon)
+void pcmcia_info(Monitor *mon, const QDict *qdict)
{
struct pcmcia_socket_entry_s *iter;
bool have_text = false;
QLIST_FOREACH(dcl, &ds->listeners, next) {
- if (dcl->dpy_refresh != NULL) {
+ if (dcl->ops->dpy_refresh != NULL) {
need_timer = true;
}
- if (dcl->dpy_gfx_update != NULL) {
+ if (dcl->ops->dpy_gfx_update != NULL) {
have_gfx = true;
}
- if (dcl->dpy_text_update != NULL) {
+ if (dcl->ops->dpy_text_update != NULL) {
have_text = true;
}
}
#else
fprintf(stderr, "Curses support is disabled\n");
exit(1);
+#endif
+ } else if (strstart(p, "gtk", &opts)) {
+#ifdef CONFIG_GTK
+ display = DT_GTK;
+#else
+ fprintf(stderr, "GTK support is disabled\n");
+ exit(1);
#endif
} else if (strstart(p, "none", &opts)) {
display = DT_NONE;
char *qemu_find_file(int type, const char *name)
{
- int len;
+ int i;
const char *subdir;
char *buf;
/* Try the name as a straight path first */
if (access(name, R_OK) == 0) {
+ trace_load_file(name, name);
return g_strdup(name);
}
+
switch (type) {
case QEMU_FILE_TYPE_BIOS:
subdir = "";
default:
abort();
}
- len = strlen(data_dir) + strlen(name) + strlen(subdir) + 2;
- buf = g_malloc0(len);
- snprintf(buf, len, "%s/%s%s", data_dir, subdir, name);
- if (access(buf, R_OK)) {
+
+ for (i = 0; i < data_dir_idx; i++) {
+ buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name);
+ if (access(buf, R_OK) == 0) {
+ trace_load_file(name, buf);
+ return buf;
+ }
g_free(buf);
- return NULL;
}
- return buf;
+ return NULL;
}
static int device_help_func(QemuOpts *opts, void *opaque)
dev = qdev_device_add(opts);
if (!dev)
return -1;
+ object_unref(OBJECT(dev));
return 0;
}
static int chardev_init_func(QemuOpts *opts, void *opaque)
{
- CharDriverState *chr;
+ Error *local_err = NULL;
- chr = qemu_chr_new_from_opts(opts, NULL);
- if (!chr)
+ qemu_chr_new_from_opts(opts, NULL, &local_err);
+ if (error_is_set(&local_err)) {
+ fprintf(stderr, "%s\n", error_get_pretty(local_err));
+ error_free(local_err);
return -1;
+ }
return 0;
}
DEV_VIRTCON, /* -virtioconsole */
DEV_DEBUGCON, /* -debugcon */
DEV_GDB, /* -gdb, -s */
+ DEV_SCLP, /* s390 sclp */
} type;
const char *cmdline;
Location loc;
return 0;
}
+static int sclp_parse(const char *devname)
+{
+ QemuOptsList *device = qemu_find_opts("device");
+ static int index = 0;
+ char label[32];
+ QemuOpts *dev_opts;
+
+ if (strcmp(devname, "none") == 0) {
+ return 0;
+ }
+ if (index == MAX_SCLP_CONSOLES) {
+ fprintf(stderr, "qemu: too many sclp consoles\n");
+ exit(1);
+ }
+
+ assert(arch_type == QEMU_ARCH_S390X);
+
+ dev_opts = qemu_opts_create(device, NULL, 0, NULL);
+ qemu_opt_set(dev_opts, "driver", "sclpconsole");
+
+ snprintf(label, sizeof(label), "sclpcon%d", index);
+ sclp_hds[index] = qemu_chr_new(label, devname, NULL);
+ if (!sclp_hds[index]) {
+ fprintf(stderr, "qemu: could not connect sclp console"
+ " to character backend '%s'\n", devname);
+ return -1;
+ }
+ qemu_opt_set(dev_opts, "chardev", label);
+
+ index++;
+ return 0;
+}
+
static int debugcon_parse(const char *devname)
{
QemuOpts *opts;
const char *name;
int (*available)(void);
int (*init)(void);
- int *allowed;
+ bool *allowed;
} accel_list[] = {
{ "tcg", "tcg", tcg_available, tcg_init, &tcg_allowed },
{ "xen", "Xen", xen_available, xen_init, &xen_allowed },
const char *p = NULL;
char buf[10];
int i, ret;
- bool accel_initialised = 0;
- bool init_failed = 0;
+ bool accel_initialised = false;
+ bool init_failed = false;
QemuOptsList *list = qemu_find_opts("machine");
if (!QTAILQ_EMPTY(&list->head)) {
p = get_opt_name(buf, sizeof (buf), p, ':');
for (i = 0; i < ARRAY_SIZE(accel_list); i++) {
if (strcmp(accel_list[i].opt_name, buf) == 0) {
- *(accel_list[i].allowed) = 1;
+ if (!accel_list[i].available()) {
+ printf("%s not supported for this target\n",
+ accel_list[i].name);
+ continue;
+ }
+ *(accel_list[i].allowed) = true;
ret = accel_list[i].init();
if (ret < 0) {
- init_failed = 1;
- if (!accel_list[i].available()) {
- printf("%s not supported for this target\n",
- accel_list[i].name);
- } else {
- fprintf(stderr, "failed to initialize %s: %s\n",
- accel_list[i].name,
- strerror(-ret));
- }
- *(accel_list[i].allowed) = 0;
+ init_failed = true;
+ fprintf(stderr, "failed to initialize %s: %s\n",
+ accel_list[i].name,
+ strerror(-ret));
+ *(accel_list[i].allowed) = false;
} else {
- accel_initialised = 1;
+ accel_initialised = true;
}
break;
}
}
if (!accel_initialised) {
- fprintf(stderr, "No accelerator found!\n");
+ if (!init_failed) {
+ fprintf(stderr, "No accelerator found!\n");
+ }
exit(1);
}
qemu_add_opts(&qemu_sandbox_opts);
qemu_add_opts(&qemu_add_fd_opts);
qemu_add_opts(&qemu_object_opts);
+ qemu_add_opts(&qemu_tpmdev_opts);
runstate_init();
drive_add(IF_MTD, -1, optarg, MTD_OPTS);
break;
case QEMU_OPTION_sd:
- drive_add(IF_SD, 0, optarg, SD_OPTS);
+ drive_add(IF_SD, -1, optarg, SD_OPTS);
break;
case QEMU_OPTION_pflash:
drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS);
}
break;
case QEMU_OPTION_numa:
- if (nb_numa_nodes >= MAX_NODES) {
- fprintf(stderr, "qemu: too many NUMA nodes\n");
- exit(1);
- }
numa_add(optarg);
break;
case QEMU_OPTION_display:
static const char * const params[] = {
"order", "once", "menu",
"splash", "splash-time",
- "reboot-timeout", NULL
+ "reboot-timeout", "strict", NULL
};
char buf[sizeof(boot_devices)];
char *standard_boot_devices;
exit(1);
}
}
- qemu_opts_parse(qemu_find_opts("boot-opts"),
- optarg, 0);
+ if (get_param_value(buf, sizeof(buf),
+ "strict", optarg)) {
+ if (!strcmp(buf, "on")) {
+ boot_strict = true;
+ } else if (!strcmp(buf, "off")) {
+ boot_strict = false;
+ } else {
+ fprintf(stderr,
+ "qemu: invalid option value '%s'\n",
+ buf);
+ exit(1);
+ }
+ }
+ if (!qemu_opts_parse(qemu_find_opts("boot-opts"),
+ optarg, 0)) {
+ exit(1);
+ }
}
}
break;
}
break;
}
+#ifdef CONFIG_TPM
+ case QEMU_OPTION_tpmdev:
+ if (tpm_config_parse(qemu_find_opts("tpmdev"), optarg) < 0) {
+ exit(1);
+ }
+ break;
+#endif
case QEMU_OPTION_mempath:
mem_path = optarg;
break;
add_device_config(DEV_GDB, optarg);
break;
case QEMU_OPTION_L:
- data_dir = optarg;
+ if (data_dir_idx < ARRAY_SIZE(data_dir)) {
+ data_dir[data_dir_idx++] = optarg;
+ }
break;
case QEMU_OPTION_bios:
bios_name = optarg;
}
opts = qemu_opts_parse(olist, optarg, 1);
if (!opts) {
- fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
break;
}
opts = qemu_opts_parse(olist, optarg, 1);
if (!opts) {
- fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
olist = qemu_find_opts("machine");
opts = qemu_opts_parse(olist, optarg, 1);
if (!opts) {
- fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
optarg = qemu_opt_get(opts, "type");
exit(1);
}
opts = qemu_opts_parse(qemu_find_opts("option-rom"), optarg, 1);
+ if (!opts) {
+ exit(1);
+ }
option_rom[nb_option_roms].name = qemu_opt_get(opts, "romfile");
option_rom[nb_option_roms].bootindex =
qemu_opt_get_number(opts, "bootindex", -1);
default_serial = 0;
default_parallel = 0;
default_virtcon = 0;
+ default_sclp = 0;
default_monitor = 0;
default_net = 0;
default_floppy = 0;
}
opts = qemu_opts_parse(olist, optarg, 0);
if (!opts) {
- fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
+ display_remote++;
break;
case QEMU_OPTION_writeconfig:
{
case QEMU_OPTION_sandbox:
opts = qemu_opts_parse(qemu_find_opts("sandbox"), optarg, 1);
if (!opts) {
- exit(0);
+ exit(1);
}
break;
case QEMU_OPTION_add_fd:
#ifndef _WIN32
opts = qemu_opts_parse(qemu_find_opts("add-fd"), optarg, 0);
if (!opts) {
- exit(0);
+ exit(1);
}
#else
error_report("File descriptor passing is disabled on this "
break;
case QEMU_OPTION_object:
opts = qemu_opts_parse(qemu_find_opts("object"), optarg, 1);
+ if (!opts) {
+ exit(1);
+ }
break;
default:
os_parse_cmd_args(popt->index, optarg);
* location or level of logging.
*/
if (log_mask) {
+ int mask;
if (log_file) {
- set_cpu_log_filename(log_file);
+ qemu_set_log_filename(log_file);
+ }
+
+ mask = qemu_str_to_log_mask(log_mask);
+ if (!mask) {
+ qemu_print_log_usage(stdout);
+ exit(1);
}
- set_cpu_log(log_mask);
+ qemu_set_log(mask);
}
if (!trace_backend_init(trace_events, trace_file)) {
/* If no data_dir is specified then try to find it relative to the
executable path. */
- if (!data_dir) {
- data_dir = os_find_datadir(argv[0]);
+ if (data_dir_idx < ARRAY_SIZE(data_dir)) {
+ data_dir[data_dir_idx] = os_find_datadir(argv[0]);
+ if (data_dir[data_dir_idx] != NULL) {
+ data_dir_idx++;
+ }
}
/* If all else fails use the install path specified when building. */
- if (!data_dir) {
- data_dir = CONFIG_QEMU_DATADIR;
+ if (data_dir_idx < ARRAY_SIZE(data_dir)) {
+ data_dir[data_dir_idx++] = CONFIG_QEMU_DATADIR;
}
/*
if (!machine->use_virtcon) {
default_virtcon = 0;
}
+ if (!machine->use_sclp) {
+ default_sclp = 0;
+ }
if (machine->no_floppy) {
default_floppy = 0;
}
add_device_config(DEV_SERIAL, "mon:stdio");
} else if (default_virtcon && default_monitor) {
add_device_config(DEV_VIRTCON, "mon:stdio");
+ } else if (default_sclp && default_monitor) {
+ add_device_config(DEV_SCLP, "mon:stdio");
} else {
if (default_serial)
add_device_config(DEV_SERIAL, "stdio");
if (default_virtcon)
add_device_config(DEV_VIRTCON, "stdio");
+ if (default_sclp) {
+ add_device_config(DEV_SCLP, "stdio");
+ }
if (default_monitor)
monitor_parse("stdio", "readline");
}
monitor_parse("vc:80Cx24C", "readline");
if (default_virtcon)
add_device_config(DEV_VIRTCON, "vc:80Cx24C");
+ if (default_sclp) {
+ add_device_config(DEV_SCLP, "vc:80Cx24C");
+ }
}
+ if (display_type == DT_DEFAULT && !display_remote) {
+#if defined(CONFIG_GTK)
+ display_type = DT_GTK;
+#elif defined(CONFIG_SDL) || defined(CONFIG_COCOA)
+ display_type = DT_SDL;
+#elif defined(CONFIG_VNC)
+ vnc_display = "localhost:0,to=99";
+ show_vnc_port = 1;
+#else
+ display_type = DT_NONE;
+#endif
+ }
+
+#if defined(CONFIG_GTK)
+ if (display_type == DT_GTK) {
+ early_gtk_display_init();
+ }
+#endif
+
socket_init();
if (qemu_opts_foreach(qemu_find_opts("chardev"), chardev_init_func, NULL, 1) != 0)
exit(1);
}
+#ifdef CONFIG_TPM
+ if (tpm_init() < 0) {
+ exit(1);
+ }
+#endif
+
/* init the bluetooth world */
if (foreach_device_config(DEV_BT, bt_parse))
exit(1);
exit(1);
if (foreach_device_config(DEV_VIRTCON, virtcon_parse) < 0)
exit(1);
+ if (foreach_device_config(DEV_SCLP, sclp_parse) < 0) {
+ exit(1);
+ }
if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
exit(1);
/* just use the first displaystate for the moment */
ds = get_displaystate();
- if (using_spice)
- display_remote++;
- if (display_type == DT_DEFAULT && !display_remote) {
-#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
- display_type = DT_SDL;
-#elif defined(CONFIG_VNC)
- vnc_display = "localhost:0,to=99";
- show_vnc_port = 1;
-#else
- display_type = DT_NONE;
-#endif
- }
-
-
/* init local displays */
switch (display_type) {
case DT_NOGRAPHIC:
case DT_SDL:
cocoa_display_init(ds, full_screen);
break;
+#endif
+#if defined(CONFIG_GTK)
+ case DT_GTK:
+ gtk_display_init(ds);
+ break;
#endif
default:
break;
bdrv_close_all();
pause_all_vcpus();
res_free();
+#ifdef CONFIG_TPM
+ tpm_cleanup();
+#endif
return 0;
}