1 /* $NetBSD: module.h,v 1.48 2021/10/24 06:52:26 skrll 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/uio.h> 36 37 #define MAXMODNAME 32 38 #define MAXMODDEPS 10 39 40 /* Module classes, provided only for system boot and module validation. */ 41 typedef enum modclass { 42 MODULE_CLASS_ANY, 43 MODULE_CLASS_MISC, 44 MODULE_CLASS_VFS, 45 MODULE_CLASS_DRIVER, 46 MODULE_CLASS_EXEC, 47 MODULE_CLASS_SECMODEL, 48 MODULE_CLASS_BUFQ, 49 MODULE_CLASS_MAX 50 } modclass_t; 51 52 /* Module sources: where did it come from? */ 53 typedef enum modsrc { 54 MODULE_SOURCE_KERNEL, 55 MODULE_SOURCE_BOOT, 56 MODULE_SOURCE_FILESYS 57 } modsrc_t; 58 59 /* Commands passed to module control routine. */ 60 typedef enum modcmd { 61 MODULE_CMD_INIT, /* mandatory */ 62 MODULE_CMD_FINI, /* mandatory */ 63 MODULE_CMD_STAT, /* optional */ 64 MODULE_CMD_AUTOUNLOAD, /* optional */ 65 } modcmd_t; 66 67 #ifdef _KERNEL 68 69 #include <sys/kernel.h> 70 #include <sys/mutex.h> 71 #include <sys/queue.h> 72 #include <sys/specificdata.h> 73 74 #include <prop/proplib.h> 75 76 /* Module header structure. */ 77 typedef struct modinfo { 78 u_int mi_version; 79 modclass_t mi_class; 80 int (*mi_modcmd)(modcmd_t, void *); 81 const char *mi_name; 82 const char *mi_required; 83 } const modinfo_t; 84 85 /* Per module information, maintained by kern_module.c */ 86 87 struct sysctllog; 88 89 typedef struct module { 90 u_int mod_refcnt; 91 int mod_flags; 92 #define MODFLG_MUST_FORCE 0x01 93 #define MODFLG_AUTO_LOADED 0x02 94 const modinfo_t *mod_info; 95 struct kobj *mod_kobj; 96 TAILQ_ENTRY(module) mod_chain; 97 struct module *(*mod_required)[MAXMODDEPS]; 98 u_int mod_nrequired; 99 u_int mod_arequired; 100 modsrc_t mod_source; 101 time_t mod_autotime; 102 specificdata_reference mod_sdref; 103 struct sysctllog *mod_sysctllog; 104 } module_t; 105 106 /* 107 * Per-module linkage. Loadable modules have a `link_set_modules' section 108 * containing only one entry, pointing to the module's modinfo_t record. 109 * For the kernel, `link_set_modules' can contain multiple entries and 110 * records all modules built into the kernel at link time. 111 * 112 * Alternatively, in some environments rump kernels use 113 * __attribute__((constructor)) due to link sets being 114 * difficult (impossible?) to implement (e.g. GNU gold, OS X, etc.) 115 * If we're cold (read: rump_init() has not been called), we lob the 116 * module onto the list to be handled when rump_init() runs. 117 * nb. it's not possible to use in-kernel locking mechanisms here since 118 * the code runs before rump_init(). We solve the problem by decreeing 119 * that thou shalt not call dlopen()/dlclose() for rump kernel components 120 * from multiple threads before calling rump_init(). 121 */ 122 123 #ifdef RUMP_USE_CTOR 124 struct modinfo_chain { 125 const struct modinfo *mc_info; 126 LIST_ENTRY(modinfo_chain) mc_entries; 127 }; 128 LIST_HEAD(modinfo_boot_chain, modinfo_chain); 129 #define _MODULE_REGISTER(name) \ 130 static struct modinfo_chain __CONCAT(mc,name) = { \ 131 .mc_info = &__CONCAT(name,_modinfo), \ 132 }; \ 133 static void __CONCAT(modctor_,name)(void) __attribute__((__constructor__));\ 134 static void __CONCAT(modctor_,name)(void) \ 135 { \ 136 extern struct modinfo_boot_chain modinfo_boot_chain; \ 137 if (cold) { \ 138 struct modinfo_chain *mc = &__CONCAT(mc,name); \ 139 LIST_INSERT_HEAD(&modinfo_boot_chain, mc, mc_entries); \ 140 } \ 141 } \ 142 \ 143 static void __CONCAT(moddtor_,name)(void) __attribute__((__destructor__));\ 144 static void __CONCAT(moddtor_,name)(void) \ 145 { \ 146 struct modinfo_chain *mc = &__CONCAT(mc,name); \ 147 if (cold) { \ 148 LIST_REMOVE(mc, mc_entries); \ 149 } \ 150 } 151 152 #else /* RUMP_USE_CTOR */ 153 154 #define _MODULE_REGISTER(name) __link_set_add_rodata(modules, __CONCAT(name,_modinfo)); 155 156 #endif /* RUMP_USE_CTOR */ 157 158 #define MODULE(class, name, required) \ 159 static int __CONCAT(name,_modcmd)(modcmd_t, void *); \ 160 static const modinfo_t __CONCAT(name,_modinfo) = { \ 161 .mi_version = __NetBSD_Version__, \ 162 .mi_class = (class), \ 163 .mi_modcmd = __CONCAT(name,_modcmd), \ 164 .mi_name = __STRING(name), \ 165 .mi_required = (required) \ 166 }; \ 167 _MODULE_REGISTER(name) 168 169 TAILQ_HEAD(modlist, module); 170 171 extern struct vm_map *module_map; 172 extern u_int module_count; 173 extern u_int module_builtinlist; 174 extern struct modlist module_list; 175 extern struct modlist module_builtins; 176 extern u_int module_gen; 177 178 void module_init(void); 179 void module_start_unload_thread(void); 180 void module_builtin_require_force(void); 181 void module_init_md(void); 182 void module_init_class(modclass_t); 183 int module_prime(const char *, void *, size_t); 184 185 module_t *module_kernel(void); 186 const char *module_name(struct module *); 187 modsrc_t module_source(struct module *); 188 bool module_compatible(int, int); 189 int module_load(const char *, int, prop_dictionary_t, modclass_t); 190 int module_builtin_add(modinfo_t * const *, size_t, bool); 191 int module_builtin_remove(modinfo_t *, bool); 192 int module_autoload(const char *, modclass_t); 193 int module_unload(const char *); 194 void module_hold(module_t *); 195 void module_rele(module_t *); 196 int module_find_section(const char *, void **, size_t *); 197 void module_thread_kick(void); 198 void module_load_vfs_init(void); 199 200 specificdata_key_t module_specific_key_create(specificdata_key_t *, specificdata_dtor_t); 201 void module_specific_key_delete(specificdata_key_t); 202 void *module_getspecific(module_t *, specificdata_key_t); 203 void module_setspecific(module_t *, specificdata_key_t, void *); 204 void *module_register_callbacks(void (*)(struct module *), 205 void (*)(struct module *)); 206 void module_unregister_callbacks(void *); 207 208 void module_whatis(uintptr_t, void (*)(const char *, ...) 209 __printflike(1, 2)); 210 void module_print_list(void (*)(const char *, ...) __printflike(1, 2)); 211 212 #ifdef _MODULE_INTERNAL 213 extern 214 int (*module_load_vfs_vec)(const char *, int, bool, module_t *, 215 prop_dictionary_t *); 216 int module_load_vfs(const char *, int, bool, module_t *, 217 prop_dictionary_t *); 218 void module_error(const char *, ...) __printflike(1, 2); 219 void module_print(const char *, ...) __printflike(1, 2); 220 #endif /* _MODULE_INTERNAL */ 221 222 #define MODULE_BASE_SIZE 64 223 extern char module_base[MODULE_BASE_SIZE]; 224 extern const char *module_machine; 225 226 struct netbsd32_modctl_args; 227 extern int compat32_80_modctl_compat_stub(struct lwp *, 228 const struct netbsd32_modctl_args *, register_t *); 229 230 #else /* _KERNEL */ 231 232 #include <stdint.h> 233 234 #endif /* _KERNEL */ 235 236 typedef struct modctl_load { 237 const char *ml_filename; 238 239 #define MODCTL_NO_PROP 0x2 240 #define MODCTL_LOAD_FORCE 0x1 241 int ml_flags; 242 243 const char *ml_props; 244 size_t ml_propslen; 245 } modctl_load_t; 246 247 enum modctl { 248 MODCTL_LOAD, /* modctl_load_t *ml */ 249 MODCTL_UNLOAD, /* char *name */ 250 MODCTL_OSTAT, /* struct iovec *buffer */ 251 MODCTL_EXISTS, /* enum: 0: load, 1: autoload */ 252 MODCTL_STAT /* struct iovec *buffer */ 253 }; 254 255 /* 256 * This structure is used with the newer version of MODCTL_STAT, which 257 * exports strings of arbitrary length for the list of required modules. 258 */ 259 typedef struct modstat { 260 char ms_name[MAXMODNAME]; 261 uint64_t ms_addr; 262 modsrc_t ms_source; 263 modclass_t ms_class; 264 u_int ms_size; 265 u_int ms_refcnt; 266 u_int ms_flags; 267 u_int ms_reqoffset; /* offset to module's required list 268 from beginning of iovec buffer! */ 269 } modstat_t; 270 271 int modctl(int, void *); 272 273 #ifdef _KERNEL 274 /* attention: pointers passed are userland pointers!, 275 see modctl_load_t */ 276 int handle_modctl_load(const char *, int, const char *, size_t); 277 #endif 278 279 #endif /* !_SYS_MODULE_H_ */ 280