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