From f31d07d175b25ecca89f5d55dfdf2b55540e5e44 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 31 Jul 2009 12:25:37 +0200 Subject: [PATCH] QemuOpts: switch over -device. Make -device switch use the QemuOpts framework. Everything should continue to work like it did before. New: "-set device.$id.$property=$value" works. Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori Message-Id: --- hw/qdev.c | 78 +++++++++++++++++++++++++-------------------------- hw/qdev.h | 5 ++-- qemu-config.c | 14 +++++++++ qemu-config.h | 1 + vl.c | 31 +++++++++++--------- 5 files changed, 73 insertions(+), 56 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index 2a61e43a19..b048020455 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -120,18 +120,33 @@ static int qdev_print_devinfo(DeviceInfo *info, char *dest, int len) return pos; } -DeviceState *qdev_device_add(const char *cmdline) +static int set_property(const char *name, const char *value, void *opaque) { + DeviceState *dev = opaque; + + if (strcmp(name, "driver") == 0) + return 0; + if (strcmp(name, "bus") == 0) + return 0; + + if (-1 == qdev_prop_parse(dev, name, value)) { + fprintf(stderr, "can't set property \"%s\" to \"%s\" for \"%s\"\n", + name, value, dev->info->name); + return -1; + } + return 0; +} + +DeviceState *qdev_device_add(QemuOpts *opts) +{ + const char *driver, *path, *id; DeviceInfo *info; DeviceState *qdev; BusState *bus; - char driver[32], path[128] = ""; - char tag[32], value[256]; - const char *params = NULL; - int n = 0; - if (1 != sscanf(cmdline, "%32[^,],%n", driver, &n)) { - fprintf(stderr, "device parse error: \"%s\"\n", cmdline); + driver = qemu_opt_get(opts, "driver"); + if (!driver) { + fprintf(stderr, "-device: no driver specified\n"); return NULL; } if (strcmp(driver, "?") == 0) { @@ -142,10 +157,8 @@ DeviceState *qdev_device_add(const char *cmdline) } return NULL; } - if (n) { - params = cmdline + n; - get_param_value(path, sizeof(path), "bus", params); - } + + /* find driver */ info = qdev_find_info(NULL, driver); if (!info) { fprintf(stderr, "Device \"%s\" not found. Try -device '?' for a list.\n", @@ -158,40 +171,26 @@ DeviceState *qdev_device_add(const char *cmdline) return NULL; } - if (strlen(path)) { + /* find bus */ + path = qemu_opt_get(opts, "bus"); + if (path != NULL) { bus = qbus_find(path); - if (!bus) - return NULL; - qdev = qdev_create(bus, driver); } else { bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info); - if (!bus) - return NULL; - qdev = qdev_create(bus, driver); } + if (!bus) + return NULL; - if (params) { - while (params[0]) { - if (2 != sscanf(params, "%31[^=]=%255[^,]%n", tag, value, &n)) { - fprintf(stderr, "parse error at \"%s\"\n", params); - break; - } - params += n; - if (params[0] == ',') - params++; - if (strcmp(tag, "bus") == 0) - continue; - if (strcmp(tag, "id") == 0) { - qdev->id = qemu_strdup(value); - continue; - } - if (-1 == qdev_prop_parse(qdev, tag, value)) { - fprintf(stderr, "can't set property \"%s\" to \"%s\" for \"%s\"\n", - tag, value, driver); - } - } + /* create device, set properties */ + qdev = qdev_create(bus, driver); + id = qemu_opts_id(opts); + if (id) { + qdev->id = id; + } + if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) { + qdev_free(qdev); + return NULL; } - qdev_init(qdev); return qdev; } @@ -208,7 +207,6 @@ void qdev_init(DeviceState *dev) void qdev_free(DeviceState *dev) { LIST_REMOVE(dev, sibling); - qemu_free(dev->id); qemu_free(dev); } diff --git a/hw/qdev.h b/hw/qdev.h index b342afbe3f..0f0acb13a9 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -3,6 +3,7 @@ #include "hw.h" #include "sys-queue.h" +#include "qemu-option.h" typedef struct Property Property; @@ -19,7 +20,7 @@ typedef struct BusInfo BusInfo; /* This structure should not be accessed directly. We declare it here so that it can be embedded in individual device state structures. */ struct DeviceState { - char *id; + const char *id; DeviceInfo *info; BusState *parent_bus; int num_gpio_out; @@ -82,7 +83,7 @@ struct CompatProperty { /*** Board API. This should go away once we have a machine config file. ***/ DeviceState *qdev_create(BusState *bus, const char *name); -DeviceState *qdev_device_add(const char *cmdline); +DeviceState *qdev_device_add(QemuOpts *opts); void qdev_init(DeviceState *dev); void qdev_free(DeviceState *dev); diff --git a/qemu-config.c b/qemu-config.c index bcfb6eb6e5..3dd473a710 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -71,8 +71,22 @@ QemuOptsList qemu_drive_opts = { }, }; +QemuOptsList qemu_device_opts = { + .name = "device", + .head = TAILQ_HEAD_INITIALIZER(qemu_device_opts.head), + .desc = { + /* + * no elements => accept any + * sanity checking will happen later + * when setting device properties + */ + { /* end if list */ } + }, +}; + static QemuOptsList *lists[] = { &qemu_drive_opts, + &qemu_device_opts, NULL, }; diff --git a/qemu-config.h b/qemu-config.h index 7faec9bdd8..08629deb99 100644 --- a/qemu-config.h +++ b/qemu-config.h @@ -1,3 +1,4 @@ extern QemuOptsList qemu_drive_opts; +extern QemuOptsList qemu_device_opts; int qemu_set_option(const char *str); diff --git a/vl.c b/vl.c index 5542df31bf..6c4a509989 100644 --- a/vl.c +++ b/vl.c @@ -4716,9 +4716,18 @@ char *qemu_find_file(int type, const char *name) return buf; } +static int device_init_func(QemuOpts *opts, void *opaque) +{ + DeviceState *dev; + + dev = qdev_device_add(opts); + if (!dev) + return -1; + return 0; +} + struct device_config { enum { - DEV_GENERIC, /* -device */ DEV_USB, /* -usbdevice */ DEV_BT, /* -bt */ } type; @@ -4752,16 +4761,6 @@ static int foreach_device_config(int type, int (*func)(const char *cmdline)) return 0; } -static int generic_parse(const char *cmdline) -{ - DeviceState *dev; - - dev = qdev_device_add(cmdline); - if (!dev) - return -1; - return 0; -} - int main(int argc, char **argv, char **envp) { const char *gdbstub_dev = NULL; @@ -4776,7 +4775,7 @@ int main(int argc, char **argv, char **envp) int cyls, heads, secs, translation; const char *net_clients[MAX_NET_CLIENTS]; int nb_net_clients; - QemuOpts *hda_opts = NULL; + QemuOpts *hda_opts = NULL, *opts; int optind; const char *r, *optarg; CharDriverState *monitor_hd = NULL; @@ -5386,7 +5385,11 @@ int main(int argc, char **argv, char **envp) add_device_config(DEV_USB, optarg); break; case QEMU_OPTION_device: - add_device_config(DEV_GENERIC, optarg); + opts = qemu_opts_parse(&qemu_device_opts, optarg, "driver"); + if (!opts) { + fprintf(stderr, "parse error: %s\n", optarg); + exit(1); + } break; case QEMU_OPTION_smp: { @@ -5922,7 +5925,7 @@ int main(int argc, char **argv, char **envp) } /* init generic devices */ - if (foreach_device_config(DEV_GENERIC, generic_parse)) + if (qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) != 0) exit(1); if (!display_state)