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 <kraxel@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Message-Id:
This commit is contained in:
		
							parent
							
								
									d058fe03e5
								
							
						
					
					
						commit
						f31d07d175
					
				
							
								
								
									
										78
									
								
								hw/qdev.c
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								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); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
| 
 | ||||
|  | ||||
| @ -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, | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| extern QemuOptsList qemu_drive_opts; | ||||
| extern QemuOptsList qemu_device_opts; | ||||
| 
 | ||||
| int qemu_set_option(const char *str); | ||||
|  | ||||
							
								
								
									
										31
									
								
								vl.c
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								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) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Gerd Hoffmann
						Gerd Hoffmann