diff -urN qemu/Makefile.target qemu-modules/Makefile.target --- qemu/Makefile.target 2005-01-15 17:53:22.000000000 +0100 +++ qemu-modules/Makefile.target 2005-01-15 21:48:22.603025920 +0100 @@ -290,6 +290,7 @@ # must use static linking to avoid leaving stuff in virtual address space VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o +VL_OBJS+=module.o module_skeleton.o module_last.o SOUND_HW = sb16.o AUDIODRV = audio.o noaudio.o wavaudio.o diff -urN qemu/module.c qemu-modules/module.c --- qemu/module.c 1970-01-01 01:00:00.000000000 +0100 +++ qemu-modules/module.c 2005-01-15 23:10:31.273754080 +0100 @@ -0,0 +1,178 @@ +#include +#include +#include +#include + +#include "module.h" + +static void *__param_first __param_section = NULL; + +void module_list_all(void) +{ + void *first_module = &__param_first + 1; + + struct module *curr; + + for (curr = first_module; curr->name; curr++) { + + printf("%-15s %s\n", curr->name, curr->descr); + } +} + +static struct module *module_find(char *name) +{ + void *first_module = &__param_first + 1; + + struct module *curr; + + for (curr = first_module; curr->name; curr++) { + + if (strcmp(name, curr->name) == 0) { + return curr; + } + } + + return NULL; +} + +struct label { + struct label *next; + + char *name; + char *args; + struct module *module; + void *private; +}; + +struct label *module_label_first = NULL; + +static struct label *module_label_find(char *name) +{ + struct label *x; + + for (x = module_label_first; x; x = x->next) { + if (strcmp(x->name, name) == 0) { + return x; + } + } + + return NULL; +} + +void module_label_remove(const char *name) +{ + struct label *x; + struct label *p = NULL; + + for (x = module_label_first; x; x = x->next) { + if (strcmp(x->name, name) == 0) { + if (p) { + p->next = x->next; + } + else { + module_label_first = x->next; + } + + free(x->name); + free(x); + return; + } + + p = x; + } +} + + +int module_label_create(const char *str) +{ + char *s; + struct module *module; + struct label *label; + char *m, *a; + + s = strdup(str); + + if (!s) { + goto bad; + } + + a = index(s, ':'); + if (a) { + *a = '\0'; + a++; + } + else { + a = ""; + } + + m = index(s, '='); + if (m) { + *m = '\0'; + } + else { + goto bad1; + } + m++; + + module_label_remove(s); + + module = module_find(m); + + if (!module) { + goto bad1; + } + + label = malloc(sizeof(*label) + module->size_of_priv); + + if (!label) { + goto bad1; + } + + label->name = s; + label->args = a; + label->module = module; + label->private = label + 1; + + if (module->ops->check(label->private) < 0) { + goto bad2; + } + + label->next = module_label_first; + module_label_first = label; + + return 0; + + bad2: + free(label); + + bad1: + free(s); + + bad: + return -1; +} + +void module_printf(void *priv, const char *format, ...) +{ + va_list args; + struct label *label = priv; + + label--; + + printf("%s[%s]:", label->module->name, label->name); + + va_start(args, format); + + vprintf(format, args); + + va_end(args); +} + +char *module_args(void *priv) +{ + struct label *label = priv; + + label--; + + return label->args; +} diff -urN qemu/module.h qemu-modules/module.h --- qemu/module.h 1970-01-01 01:00:00.000000000 +0100 +++ qemu-modules/module.h 2005-01-15 23:00:45.006880192 +0100 @@ -0,0 +1,78 @@ + +#ifndef __MODULE_H__ +#define __MODULE_H__ + +struct module_ops { + int (*check)(void *); + int (*start)(void *); + void (*stop)(void *); +}; + +#define MODULE_OP_TYPECHECK(func, ret_ptr_type, arg) \ +static inline ret_ptr_type(*MODULE_OP_TYPECHECK_##func(void))(arg) \ +{ return(func); } + +#define MODULE_OPS(check, start, stop, priv) \ + { (void *)check, (void *)start, (void *)stop }; \ + MODULE_OP_TYPECHECK(check, int, priv *); \ + MODULE_OP_TYPECHECK(start, int, priv *); \ + MODULE_OP_TYPECHECK(stop, void, priv *) + +struct module_param { + char *name; + char *type; + char *descr; + char *deflt; + unsigned int offset; +}; + +#define MODULE_PARAM_TYPECHECK(symbol, type) \ +static inline (type) MODULE_PARAM_TYPECHECK_##symbol(void) { return(symbol); } + +#define offset_of(type,member) ((unsigned int)(&((type *)0)->member)) + +#define MODULE_PARAM(name, type, descr, deflt, priv) \ + { #name, type, descr, #deflt, offset_of(priv, name) } + +struct module { + char *name; + char *type; + char *descr; + struct module_ops *ops; + struct module_param *params; + unsigned int no_params; + unsigned int size_of_priv; +}; + +#if __GNUC__ > 3 +#define __attribute__used__ __attribute__((__used__)) +#elif __GNUC__ == 3 +#if __GNUC_MINOR__ > 3 +#define __attribute__used__ __attribute__((__used__)) +#else +#define __attribute__used__ __attribute__((__unused__)) +#endif +#elif __GNUC__ == 2 +#define __attribute__used__ __attribute__((__unused__)) +#else +#define __attribute__used__ +#endif + +#define MODULE(name, type, descr, ops, params, priv) \ + static struct module const module \ + __attribute__used__ \ + __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ + = { \ + #name, type, descr, &ops, params, \ + (sizeof(params) / sizeof(struct module_param)), sizeof(priv) \ + } + +#define __param_section __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) + +void module_printf(void *priv, const char *format, ...); +char *module_args(void *priv); + +void module_list_all(void); +int module_label_create(const char *str); + +#endif /* __MODULE_H__ */ diff -urN qemu/module_last.c qemu-modules/module_last.c --- qemu/module_last.c 1970-01-01 01:00:00.000000000 +0100 +++ qemu-modules/module_last.c 2005-01-15 21:25:16.484747928 +0100 @@ -0,0 +1,7 @@ +#include + +#include "module.h" + +/* the object file generated from this file must be placed at the end */ + +static void *__param_last __param_section = NULL; diff -urN qemu/module_skeleton.c qemu-modules/module_skeleton.c --- qemu/module_skeleton.c 1970-01-01 01:00:00.000000000 +0100 +++ qemu-modules/module_skeleton.c 2005-01-15 23:02:36.227972016 +0100 @@ -0,0 +1,33 @@ +#include "module.h" + +struct private { + unsigned int foo; + char buf[100]; + int my_bool; +}; + +static int check(struct private *p) +{ + module_printf(p, " check! my_bool = %d, args are \"%s\"\n", + p->my_bool, module_args(p)); + + return 0; +} + +static int start(struct private *p) +{ + return 0; +} + +static void stop(struct private *p) +{ +} + +static struct module_ops ops = MODULE_OPS(check, start, stop, struct private); + +static struct module_param params[] = { + MODULE_PARAM(my_bool, "bool", "a bool parameter called my_bool", + xx, struct private), +}; + +MODULE(skel, "", "a simple module skeleton", ops, params, struct private); diff -urN qemu/vl.c qemu-modules/vl.c --- qemu/vl.c 2005-01-16 00:27:05.974253432 +0100 +++ qemu-modules/vl.c 2005-01-15 23:24:54.956454352 +0100 @@ -76,6 +76,8 @@ #include "exec-all.h" +#include "module.h" + //#define DO_TB_FLUSH #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" @@ -2769,6 +2771,7 @@ " (default is CL-GD5446 PCI VGA)\n" #endif "-loadvm file start right away with a saved state (loadvm in monitor)\n" + "-x label=module[:args] create one instance of module called label\n" "\n" "During emulation, the following keys are useful:\n" "ctrl-alt-f toggle full screen\n" @@ -2792,6 +2795,11 @@ "work. Please use the 'qemu' executable to have a more accurate (but slower)\n" "PC emulation.\n"); #endif + + printf("\nAvailable modules:\n"); + module_list_all(); + + exit(1); } @@ -2848,6 +2856,7 @@ QEMU_OPTION_loadvm, QEMU_OPTION_full_screen, QEMU_OPTION_pidfile, + QEMU_OPTION_set_module, }; typedef struct QEMUOption { @@ -2915,6 +2924,7 @@ /* temporary options */ { "pci", 0, QEMU_OPTION_pci }, { "cirrusvga", 0, QEMU_OPTION_cirrusvga }, + { "x", HAS_ARG, QEMU_OPTION_set_module }, { NULL }, }; @@ -3328,6 +3338,12 @@ graphic_depth = depth; } break; + case QEMU_OPTION_set_module: + if (module_label_create(optarg) < 0) { + fprintf(stderr, "qemu: unable to create label \"%s\"\n", optarg); + exit(1); + } + break; case QEMU_OPTION_monitor: pstrcpy(monitor_device, sizeof(monitor_device), optarg); break;