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