1 /* $NetBSD: module.h,v 1.40 2016/01/18 16:46:08 pooka Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifndef _SYS_MODULE_H_ 30 #define _SYS_MODULE_H_ 31 32 #include <sys/types.h> 33 #include <sys/param.h> 34 #include <sys/cdefs.h> 35 #include <sys/queue.h> 36 #include <sys/uio.h> 37 38 #define MAXMODNAME 32 39 #define MAXMODDEPS 10 40 41 /* Module classes, provided only for system boot and cosmetic purposes. */ 42 typedef enum modclass { 43 MODULE_CLASS_ANY, 44 MODULE_CLASS_MISC, 45 MODULE_CLASS_VFS, 46 MODULE_CLASS_DRIVER, 47 MODULE_CLASS_EXEC, 48 MODULE_CLASS_SECMODEL 49 } modclass_t; 50 51 /* Module sources: where did it come from? */ 52 typedef enum modsrc { 53 MODULE_SOURCE_KERNEL, 54 MODULE_SOURCE_BOOT, 55 MODULE_SOURCE_FILESYS 56 } modsrc_t; 57 58 /* Commands passed to module control routine. */ 59 typedef enum modcmd { 60 MODULE_CMD_INIT, /* mandatory */ 61 MODULE_CMD_FINI, /* mandatory */ 62 MODULE_CMD_STAT, /* optional */ 63 MODULE_CMD_AUTOUNLOAD, /* optional */ 64 } modcmd_t; 65 66 #ifdef _KERNEL 67 68 #include <sys/kernel.h> 69 #include <sys/mutex.h> 70 71 #include <prop/proplib.h> 72 73 /* Module header structure. */ 74 typedef struct modinfo { 75 u_int mi_version; 76 modclass_t mi_class; 77 int (*mi_modcmd)(modcmd_t, void *); 78 const char *mi_name; 79 const char *mi_required; 80 } const modinfo_t; 81 82 /* Per module information, maintained by kern_module.c */ 83 typedef struct module { 84 u_int mod_refcnt; 85 const modinfo_t *mod_info; 86 struct kobj *mod_kobj; 87 TAILQ_ENTRY(module) mod_chain; 88 struct module *mod_required[MAXMODDEPS]; 89 u_int mod_nrequired; 90 modsrc_t mod_source; 91 time_t mod_autotime; 92 void *mod_ctf; 93 u_int mod_fbtentries; /* DTrace FBT entry count */ 94 int mod_flags; 95 #define MODFLG_MUST_FORCE 0x01 96 #define MODFLG_AUTO_LOADED 0x02 97 98 } module_t; 99 100 /* 101 * Per-module linkage. Loadable modules have a `link_set_modules' section 102 * containing only one entry, pointing to the module's modinfo_t record. 103 * For the kernel, `link_set_modules' can contain multiple entries and 104 * records all modules built into the kernel at link time. 105 * 106 * Alternatively, in some environments rump kernels use 107 * __attribute__((constructor)) due to link sets being 108 * difficult (impossible?) to implement (e.g. GNU gold, OS X, etc.) 109 * If we're cold (read: rump_init() has not been called), we lob the 110 * module onto the list to be handled when rump_init() runs. 111 * nb. it's not possible to use in-kernel locking mechanisms here since 112 * the code runs before rump_init(). We solve the problem by decreeing 113 * that thou shalt not call dlopen()/dlclose() for rump kernel components 114 * from multiple threads before calling rump_init(). 115 */ 116 117 #ifdef RUMP_USE_CTOR 118 struct modinfo_chain { 119 const struct modinfo *mc_info; 120 LIST_ENTRY(modinfo_chain) mc_entries; 121 }; 122 LIST_HEAD(modinfo_boot_chain, modinfo_chain); 123 #define _MODULE_REGISTER(name) \ 124 static struct modinfo_chain __CONCAT(mc,name) = { \ 125 .mc_info = &__CONCAT(name,_modinfo), \ 126 }; \ 127 static void __CONCAT(modctor_,name)(void) __attribute__((__constructor__));\ 128 static void __CONCAT(modctor_,name)(void) \ 129 { \ 130 extern struct modinfo_boot_chain modinfo_boot_chain; \ 131 if (cold) { \ 132 struct modinfo_chain *mc = &__CONCAT(mc,name); \ 133 LIST_INSERT_HEAD(&modinfo_boot_chain, mc, mc_entries); \ 134 } \ 135 } \ 136 \ 137 static void __CONCAT(moddtor_,name)(void) __attribute__((__destructor__));\ 138 static void __CONCAT(moddtor_,name)(void) \ 139 { \ 140 struct modinfo_chain *mc = &__CONCAT(mc,name); \ 141 if (cold) { \ 142 LIST_REMOVE(mc, mc_entries); \ 143 } \ 144 } 145 146 #else /* RUMP_USE_CTOR */ 147 148 #define _MODULE_REGISTER(name) __link_set_add_rodata(modules, __CONCAT(name,_modinfo)); 149 150 #endif /* RUMP_USE_CTOR */ 151 152 #define MODULE(class, name, required) \ 153 static int __CONCAT(name,_modcmd)(modcmd_t, void *); \ 154 static const modinfo_t __CONCAT(name,_modinfo) = { \ 155 .mi_version = __NetBSD_Version__, \ 156 .mi_class = (class), \ 157 .mi_modcmd = __CONCAT(name,_modcmd), \ 158 .mi_name = __STRING(name), \ 159 .mi_required = (required) \ 160 }; \ 161 _MODULE_REGISTER(name) 162 163 TAILQ_HEAD(modlist, module); 164 165 extern struct vm_map *module_map; 166 extern u_int module_count; 167 extern u_int module_builtinlist; 168 extern struct modlist module_list; 169 extern struct modlist module_builtins; 170 extern u_int module_gen; 171 172 void module_init(void); 173 void module_start_unload_thread(void); 174 void module_builtin_require_force(void); 175 void module_init_md(void); 176 void module_init_class(modclass_t); 177 int module_prime(const char *, void *, size_t); 178 179 bool module_compatible(int, int); 180 int module_load(const char *, int, prop_dictionary_t, modclass_t); 181 int module_builtin_add(modinfo_t * const *, size_t, bool); 182 int module_builtin_remove(modinfo_t *, bool); 183 int module_autoload(const char *, modclass_t); 184 int module_unload(const char *); 185 int module_hold(const char *); 186 void module_rele(const char *); 187 int module_find_section(const char *, void **, size_t *); 188 void module_thread_kick(void); 189 void module_load_vfs_init(void); 190 191 void module_whatis(uintptr_t, void (*)(const char *, ...) 192 __printflike(1, 2)); 193 void module_print_list(void (*)(const char *, ...) __printflike(1, 2)); 194 195 #ifdef _MODULE_INTERNAL 196 extern 197 int (*module_load_vfs_vec)(const char *, int, bool, module_t *, 198 prop_dictionary_t *); 199 int module_load_vfs(const char *, int, bool, module_t *, 200 prop_dictionary_t *); 201 void module_error(const char *, ...) __printflike(1, 2); 202 void module_print(const char *, ...) __printflike(1, 2); 203 #endif /* _MODULE_INTERNAL */ 204 205 #define MODULE_BASE_SIZE 64 206 extern char module_base[MODULE_BASE_SIZE]; 207 extern const char *module_machine; 208 209 #else /* _KERNEL */ 210 211 #include <stdint.h> 212 213 #endif /* _KERNEL */ 214 215 typedef struct modctl_load { 216 const char *ml_filename; 217 218 #define MODCTL_NO_PROP 0x2 219 #define MODCTL_LOAD_FORCE 0x1 220 int ml_flags; 221 222 const char *ml_props; 223 size_t ml_propslen; 224 } modctl_load_t; 225 226 typedef enum modctl { 227 MODCTL_LOAD, /* modctl_load_t *ml */ 228 MODCTL_UNLOAD, /* char *name */ 229 MODCTL_STAT, /* struct iovec *buffer */ 230 MODCTL_EXISTS /* enum: 0: load, 1: autoload */ 231 } modctl_t; 232 233 /* 234 * This structure intentionally has the same layout for 32 and 64 235 * bit builds. 236 */ 237 typedef struct modstat { 238 char ms_name[MAXMODNAME]; 239 char ms_required[MAXMODNAME * MAXMODDEPS]; 240 uint64_t ms_addr; 241 modsrc_t ms_source; 242 modclass_t ms_class; 243 u_int ms_size; 244 u_int ms_refcnt; 245 u_int ms_flags; 246 u_int ms_reserved[3]; 247 } modstat_t; 248 249 int modctl(int, void *); 250 251 #ifdef _KERNEL 252 /* attention: pointers passed are userland pointers!, 253 see modctl_load_t */ 254 int handle_modctl_load(const char *, int, const char *, size_t); 255 #endif 256 257 #endif /* !_SYS_MODULE_H_ */ 258