1 /* 2 * QEMU Module Infrastructure 3 * 4 * Copyright IBM, Corp. 2009 5 * 6 * Authors: 7 * Anthony Liguori <aliguori@us.ibm.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2. See 10 * the COPYING file in the top-level directory. 11 * 12 * Contributions after 2012-01-13 are licensed under the terms of the 13 * GNU GPL, version 2 or (at your option) any later version. 14 */ 15 16 #include "qemu/osdep.h" 17 #include "qemu-common.h" 18 #ifdef CONFIG_MODULES 19 #include <gmodule.h> 20 #endif 21 #include "qemu/queue.h" 22 #include "qemu/module.h" 23 24 typedef struct ModuleEntry 25 { 26 void (*init)(void); 27 QTAILQ_ENTRY(ModuleEntry) node; 28 module_init_type type; 29 } ModuleEntry; 30 31 typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList; 32 33 static ModuleTypeList init_type_list[MODULE_INIT_MAX]; 34 35 static ModuleTypeList dso_init_list; 36 37 static void init_lists(void) 38 { 39 static int inited; 40 int i; 41 42 if (inited) { 43 return; 44 } 45 46 for (i = 0; i < MODULE_INIT_MAX; i++) { 47 QTAILQ_INIT(&init_type_list[i]); 48 } 49 50 QTAILQ_INIT(&dso_init_list); 51 52 inited = 1; 53 } 54 55 56 static ModuleTypeList *find_type(module_init_type type) 57 { 58 init_lists(); 59 60 return &init_type_list[type]; 61 } 62 63 void register_module_init(void (*fn)(void), module_init_type type) 64 { 65 ModuleEntry *e; 66 ModuleTypeList *l; 67 68 e = g_malloc0(sizeof(*e)); 69 e->init = fn; 70 e->type = type; 71 72 l = find_type(type); 73 74 QTAILQ_INSERT_TAIL(l, e, node); 75 } 76 77 void register_dso_module_init(void (*fn)(void), module_init_type type) 78 { 79 ModuleEntry *e; 80 81 init_lists(); 82 83 e = g_malloc0(sizeof(*e)); 84 e->init = fn; 85 e->type = type; 86 87 QTAILQ_INSERT_TAIL(&dso_init_list, e, node); 88 } 89 90 static void module_load(module_init_type type); 91 92 void module_call_init(module_init_type type) 93 { 94 ModuleTypeList *l; 95 ModuleEntry *e; 96 97 module_load(type); 98 l = find_type(type); 99 100 QTAILQ_FOREACH(e, l, node) { 101 e->init(); 102 } 103 } 104 105 #ifdef CONFIG_MODULES 106 static int module_load_file(const char *fname) 107 { 108 GModule *g_module; 109 void (*sym)(void); 110 const char *dsosuf = HOST_DSOSUF; 111 int len = strlen(fname); 112 int suf_len = strlen(dsosuf); 113 ModuleEntry *e, *next; 114 int ret; 115 116 if (len <= suf_len || strcmp(&fname[len - suf_len], dsosuf)) { 117 /* wrong suffix */ 118 ret = -EINVAL; 119 goto out; 120 } 121 if (access(fname, F_OK)) { 122 ret = -ENOENT; 123 goto out; 124 } 125 126 assert(QTAILQ_EMPTY(&dso_init_list)); 127 128 g_module = g_module_open(fname, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); 129 if (!g_module) { 130 fprintf(stderr, "Failed to open module: %s\n", 131 g_module_error()); 132 ret = -EINVAL; 133 goto out; 134 } 135 if (!g_module_symbol(g_module, DSO_STAMP_FUN_STR, (gpointer *)&sym)) { 136 fprintf(stderr, "Failed to initialize module: %s\n", 137 fname); 138 /* Print some info if this is a QEMU module (but from different build), 139 * this will make debugging user problems easier. */ 140 if (g_module_symbol(g_module, "qemu_module_dummy", (gpointer *)&sym)) { 141 fprintf(stderr, 142 "Note: only modules from the same build can be loaded.\n"); 143 } 144 g_module_close(g_module); 145 ret = -EINVAL; 146 } else { 147 QTAILQ_FOREACH(e, &dso_init_list, node) { 148 register_module_init(e->init, e->type); 149 } 150 ret = 0; 151 } 152 153 QTAILQ_FOREACH_SAFE(e, &dso_init_list, node, next) { 154 QTAILQ_REMOVE(&dso_init_list, e, node); 155 g_free(e); 156 } 157 out: 158 return ret; 159 } 160 #endif 161 162 static void module_load(module_init_type type) 163 { 164 #ifdef CONFIG_MODULES 165 char *fname = NULL; 166 const char **mp; 167 static const char *block_modules[] = { 168 CONFIG_BLOCK_MODULES 169 }; 170 char *exec_dir; 171 char *dirs[3]; 172 int i = 0; 173 int ret; 174 175 if (!g_module_supported()) { 176 fprintf(stderr, "Module is not supported by system.\n"); 177 return; 178 } 179 180 switch (type) { 181 case MODULE_INIT_BLOCK: 182 mp = block_modules; 183 break; 184 default: 185 /* no other types have dynamic modules for now*/ 186 return; 187 } 188 189 exec_dir = qemu_get_exec_dir(); 190 dirs[i++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR); 191 dirs[i++] = g_strdup_printf("%s/..", exec_dir ? : ""); 192 dirs[i++] = g_strdup_printf("%s", exec_dir ? : ""); 193 assert(i == ARRAY_SIZE(dirs)); 194 g_free(exec_dir); 195 exec_dir = NULL; 196 197 for ( ; *mp; mp++) { 198 for (i = 0; i < ARRAY_SIZE(dirs); i++) { 199 fname = g_strdup_printf("%s/%s%s", dirs[i], *mp, HOST_DSOSUF); 200 ret = module_load_file(fname); 201 g_free(fname); 202 fname = NULL; 203 /* Try loading until loaded a module file */ 204 if (!ret) { 205 break; 206 } 207 } 208 } 209 210 for (i = 0; i < ARRAY_SIZE(dirs); i++) { 211 g_free(dirs[i]); 212 } 213 214 #endif 215 } 216