Deleted Added
full compact
module.c (38764) module.c (39178)
1/*-
2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: module.c,v 1.2 1998/08/31 21:10:42 msmith Exp $
26 * $Id: module.c,v 1.3 1998/09/03 02:10:08 msmith Exp $
27 */
28
29/*
30 * module function dispatcher, support, etc.
27 */
28
29/*
30 * module function dispatcher, support, etc.
31 *
32 * XXX need a 'searchmodule' function that takes a name and
33 * traverses a search path.
34 */
35
36#include <stand.h>
37#include <string.h>
38
39#include "bootstrap.h"
40
41static struct loaded_module *mod_loadmodule(char *name, int argc, char *argv[]);
42static char *mod_searchdep(struct loaded_module *mp);
31 */
32
33#include <stand.h>
34#include <string.h>
35
36#include "bootstrap.h"
37
38static struct loaded_module *mod_loadmodule(char *name, int argc, char *argv[]);
39static char *mod_searchdep(struct loaded_module *mp);
40static char *mod_searchfile(char *name);
43static char *mod_searchmodule(char *name);
44static void mod_append(struct loaded_module *mp);
45
41static char *mod_searchmodule(char *name);
42static void mod_append(struct loaded_module *mp);
43
46/* XXX load address should be tweaked by first module loaded (kernel) */
44/* load address should be tweaked by first module loaded (kernel) */
47static vm_offset_t loadaddr = 0;
48
45static vm_offset_t loadaddr = 0;
46
47static char *default_searchpath ="/;/boot";
48
49struct loaded_module *loaded_modules = NULL;
50
51/*
52 * load an object, either a disk file or code module.
53 *
54 * To load a file, the syntax is:
55 *
56 * load -t <type> <path>
57 *
58 * code modules are loaded as:
59 *
60 * load <path> <options>
61 */
62
63COMMAND_SET(load, "load", "load a kernel or module", command_load);
64
65static int
66command_load(int argc, char *argv[])
67{
68 char *typestr;
69 int dofile, ch;
70
71 dofile = 0;
72 optind = 1;
73 typestr = NULL;
74 while ((ch = getopt(argc, argv, "t:")) != -1) {
75 switch(ch) {
76 case 't':
77 typestr = optarg;
78 dofile = 1;
79 break;
80 case '?':
81 default:
82 /* getopt has already reported an error */
83 return(CMD_OK);
84 }
85 }
86 argv += (optind - 1);
87 argc -= (optind - 1);
88
89 /*
90 * Request to load a raw file?
91 */
92 if (dofile) {
93 if ((typestr == NULL) || (*typestr == 0)) {
94 command_errmsg = "invalid load type";
95 return(CMD_ERROR);
96 }
97 return(mod_loadobj(typestr, argv[1]));
98 }
99
100 /*
101 * Looks like a request for a module.
102 */
103 return(mod_load(argv[1], argc - 2, argv + 2));
104}
105
106COMMAND_SET(unload, "unload", "unload all modules", command_unload);
107
108static int
109command_unload(int argc, char *argv[])
110{
111 struct loaded_module *mp;
112
113 while (loaded_modules != NULL) {
114 mp = loaded_modules;
115 loaded_modules = loaded_modules->m_next;
116 mod_discard(mp);
117 }
118 loadaddr = 0;
119 return(CMD_OK);
120}
121
122COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod);
123
124static int
125command_lsmod(int argc, char *argv[])
126{
127 struct loaded_module *am;
128 struct module_metadata *md;
129 char lbuf[80];
130 int ch, verbose;
131
132 verbose = 0;
133 optind = 1;
134 while ((ch = getopt(argc, argv, "v")) != -1) {
135 switch(ch) {
136 case 'v':
137 verbose = 1;
138 break;
139 case '?':
140 default:
141 /* getopt has already reported an error */
142 return(CMD_OK);
143 }
144 }
145
146 pager_open();
147 for (am = loaded_modules; (am != NULL); am = am->m_next) {
148 sprintf(lbuf, " %x: %s (%s, 0x%x)\n",
149 am->m_addr, am->m_name, am->m_type, am->m_size);
150 pager_output(lbuf);
151 if (am->m_args != NULL) {
152 pager_output(" args: ");
153 pager_output(am->m_args);
154 pager_output("\n");
155 }
156 if (verbose)
157 /* XXX could add some formatting smarts here to display some better */
158 for (md = am->m_metadata; md != NULL; md = md->md_next) {
159 sprintf(lbuf, " 0x%04x, 0x%x\n", md->md_type, md->md_size);
160 pager_output(lbuf);
161 }
162 }
163 pager_close();
164 return(CMD_OK);
165}
166
167/*
168 * We've been asked to load (name) and give it (argc),(argv).
169 * Start by trying to load it, and then attempt to load all of its
170 * dependancies. If we fail at any point, throw them all away and
171 * fail the entire load.
172 *
173 * XXX if a depended-on module requires arguments, it must be loaded
174 * explicitly first.
175 */
176int
177mod_load(char *name, int argc, char *argv[])
178{
179 struct loaded_module *last_mod, *base_mod, *mp;
180 char *dep_name;
181
182 /* remember previous last module on chain */
183 for (last_mod = loaded_modules;
184 (last_mod != NULL) && (last_mod->m_next != NULL);
185 last_mod = last_mod->m_next)
186 ;
187
188 /*
189 * Load the first module; note that it's the only one that gets
190 * arguments explicitly.
191 */
192 if ((base_mod = mod_loadmodule(name, argc, argv)) == NULL)
193 return(CMD_ERROR);
194
195 /*
196 * Look for dependancies.
197 */
198 while ((dep_name = mod_searchdep(base_mod)) != NULL) {
199 printf("loading required module '%s'\n", dep_name);
200 if ((mp = mod_loadmodule(dep_name, 0, NULL)) == NULL) {
201 /* Load failed; discard everything */
202 while (base_mod != NULL) {
203 mp = base_mod;
204 base_mod = base_mod->m_next;
205 mod_discard(mp);
206 }
207 last_mod->m_next = NULL;
208 loadaddr = last_mod->m_addr + last_mod->m_size;
209 /* error message already set by mod_loadmodule */
210 return(CMD_ERROR);
211 }
212 }
213 return(CMD_OK);
214}
215
216/*
217 * We've been asked to load (name) as (type), so just suck it in,
218 * no arguments or anything.
219 */
220int
221mod_loadobj(char *type, char *name)
222{
223 struct loaded_module *mp;
224 char *cp;
225 int fd, got;
226 vm_offset_t laddr;
227
228 /* We can't load first */
229 if ((mod_findmodule(NULL, NULL)) == NULL) {
230 command_errmsg = "can't load file before kernel";
231 return(CMD_ERROR);
232 }
233
49struct loaded_module *loaded_modules = NULL;
50
51/*
52 * load an object, either a disk file or code module.
53 *
54 * To load a file, the syntax is:
55 *
56 * load -t <type> <path>
57 *
58 * code modules are loaded as:
59 *
60 * load <path> <options>
61 */
62
63COMMAND_SET(load, "load", "load a kernel or module", command_load);
64
65static int
66command_load(int argc, char *argv[])
67{
68 char *typestr;
69 int dofile, ch;
70
71 dofile = 0;
72 optind = 1;
73 typestr = NULL;
74 while ((ch = getopt(argc, argv, "t:")) != -1) {
75 switch(ch) {
76 case 't':
77 typestr = optarg;
78 dofile = 1;
79 break;
80 case '?':
81 default:
82 /* getopt has already reported an error */
83 return(CMD_OK);
84 }
85 }
86 argv += (optind - 1);
87 argc -= (optind - 1);
88
89 /*
90 * Request to load a raw file?
91 */
92 if (dofile) {
93 if ((typestr == NULL) || (*typestr == 0)) {
94 command_errmsg = "invalid load type";
95 return(CMD_ERROR);
96 }
97 return(mod_loadobj(typestr, argv[1]));
98 }
99
100 /*
101 * Looks like a request for a module.
102 */
103 return(mod_load(argv[1], argc - 2, argv + 2));
104}
105
106COMMAND_SET(unload, "unload", "unload all modules", command_unload);
107
108static int
109command_unload(int argc, char *argv[])
110{
111 struct loaded_module *mp;
112
113 while (loaded_modules != NULL) {
114 mp = loaded_modules;
115 loaded_modules = loaded_modules->m_next;
116 mod_discard(mp);
117 }
118 loadaddr = 0;
119 return(CMD_OK);
120}
121
122COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod);
123
124static int
125command_lsmod(int argc, char *argv[])
126{
127 struct loaded_module *am;
128 struct module_metadata *md;
129 char lbuf[80];
130 int ch, verbose;
131
132 verbose = 0;
133 optind = 1;
134 while ((ch = getopt(argc, argv, "v")) != -1) {
135 switch(ch) {
136 case 'v':
137 verbose = 1;
138 break;
139 case '?':
140 default:
141 /* getopt has already reported an error */
142 return(CMD_OK);
143 }
144 }
145
146 pager_open();
147 for (am = loaded_modules; (am != NULL); am = am->m_next) {
148 sprintf(lbuf, " %x: %s (%s, 0x%x)\n",
149 am->m_addr, am->m_name, am->m_type, am->m_size);
150 pager_output(lbuf);
151 if (am->m_args != NULL) {
152 pager_output(" args: ");
153 pager_output(am->m_args);
154 pager_output("\n");
155 }
156 if (verbose)
157 /* XXX could add some formatting smarts here to display some better */
158 for (md = am->m_metadata; md != NULL; md = md->md_next) {
159 sprintf(lbuf, " 0x%04x, 0x%x\n", md->md_type, md->md_size);
160 pager_output(lbuf);
161 }
162 }
163 pager_close();
164 return(CMD_OK);
165}
166
167/*
168 * We've been asked to load (name) and give it (argc),(argv).
169 * Start by trying to load it, and then attempt to load all of its
170 * dependancies. If we fail at any point, throw them all away and
171 * fail the entire load.
172 *
173 * XXX if a depended-on module requires arguments, it must be loaded
174 * explicitly first.
175 */
176int
177mod_load(char *name, int argc, char *argv[])
178{
179 struct loaded_module *last_mod, *base_mod, *mp;
180 char *dep_name;
181
182 /* remember previous last module on chain */
183 for (last_mod = loaded_modules;
184 (last_mod != NULL) && (last_mod->m_next != NULL);
185 last_mod = last_mod->m_next)
186 ;
187
188 /*
189 * Load the first module; note that it's the only one that gets
190 * arguments explicitly.
191 */
192 if ((base_mod = mod_loadmodule(name, argc, argv)) == NULL)
193 return(CMD_ERROR);
194
195 /*
196 * Look for dependancies.
197 */
198 while ((dep_name = mod_searchdep(base_mod)) != NULL) {
199 printf("loading required module '%s'\n", dep_name);
200 if ((mp = mod_loadmodule(dep_name, 0, NULL)) == NULL) {
201 /* Load failed; discard everything */
202 while (base_mod != NULL) {
203 mp = base_mod;
204 base_mod = base_mod->m_next;
205 mod_discard(mp);
206 }
207 last_mod->m_next = NULL;
208 loadaddr = last_mod->m_addr + last_mod->m_size;
209 /* error message already set by mod_loadmodule */
210 return(CMD_ERROR);
211 }
212 }
213 return(CMD_OK);
214}
215
216/*
217 * We've been asked to load (name) as (type), so just suck it in,
218 * no arguments or anything.
219 */
220int
221mod_loadobj(char *type, char *name)
222{
223 struct loaded_module *mp;
224 char *cp;
225 int fd, got;
226 vm_offset_t laddr;
227
228 /* We can't load first */
229 if ((mod_findmodule(NULL, NULL)) == NULL) {
230 command_errmsg = "can't load file before kernel";
231 return(CMD_ERROR);
232 }
233
234 /* Try to come up with a fully-qualified name if we don't have one */
235 if ((cp = mod_searchmodule(name)) != NULL)
236 name = cp;
234 /* locate the file on the load path */
235 cp = mod_searchfile(name);
236 if (cp == NULL) {
237 sprintf(command_errbuf, "can't find '%s'", name);
238 return(CMD_ERROR);
239 }
240 name = cp;
237
238 if ((fd = open(name, O_RDONLY)) < 0) {
239 sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno));
240 return(CMD_ERROR);
241 }
242
243 laddr = loadaddr;
244 for (;;) {
245 /* read in 4k chunks; size is not really important */
246 got = archsw.arch_readin(fd, laddr, 4096);
247 if (got == 0) /* end of file */
248 break;
249 if (got < 0) { /* error */
250 sprintf(command_errbuf, "error reading '%s': %s", name, strerror(errno));
251 return(CMD_ERROR);
252 }
253 laddr += got;
254 }
255
256 /* Looks OK so far; create & populate control structure */
257 mp = malloc(sizeof(struct loaded_module));
258 mp->m_name = strdup(name);
259 mp->m_type = strdup(type);
260 mp->m_args = NULL;
261 mp->m_metadata = NULL;
262 mp->m_loader = -1;
263 mp->m_addr = loadaddr;
264 mp->m_size = laddr - loadaddr;
265
266 /* recognise space consumption */
267 loadaddr = laddr;
268
269 /* Add to the list of loaded modules */
270 mod_append(mp);
271 return(CMD_OK);
272}
273
274/*
275 * Load the module (name), pass it (argc),(argv).
276 * Don't do any dependancy checking.
277 */
278static struct loaded_module *
279mod_loadmodule(char *name, int argc, char *argv[])
280{
281 struct loaded_module *mp;
282 int i, err;
283 char *cp;
284
241
242 if ((fd = open(name, O_RDONLY)) < 0) {
243 sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno));
244 return(CMD_ERROR);
245 }
246
247 laddr = loadaddr;
248 for (;;) {
249 /* read in 4k chunks; size is not really important */
250 got = archsw.arch_readin(fd, laddr, 4096);
251 if (got == 0) /* end of file */
252 break;
253 if (got < 0) { /* error */
254 sprintf(command_errbuf, "error reading '%s': %s", name, strerror(errno));
255 return(CMD_ERROR);
256 }
257 laddr += got;
258 }
259
260 /* Looks OK so far; create & populate control structure */
261 mp = malloc(sizeof(struct loaded_module));
262 mp->m_name = strdup(name);
263 mp->m_type = strdup(type);
264 mp->m_args = NULL;
265 mp->m_metadata = NULL;
266 mp->m_loader = -1;
267 mp->m_addr = loadaddr;
268 mp->m_size = laddr - loadaddr;
269
270 /* recognise space consumption */
271 loadaddr = laddr;
272
273 /* Add to the list of loaded modules */
274 mod_append(mp);
275 return(CMD_OK);
276}
277
278/*
279 * Load the module (name), pass it (argc),(argv).
280 * Don't do any dependancy checking.
281 */
282static struct loaded_module *
283mod_loadmodule(char *name, int argc, char *argv[])
284{
285 struct loaded_module *mp;
286 int i, err;
287 char *cp;
288
285 /* Try to come up with a fully-qualified name if we don't have one */
286 if ((cp = mod_searchmodule(name)) != NULL)
287 name = cp;
289 /* locate the module on the search path */
290 cp = mod_searchmodule(name);
291 if (cp == NULL) {
292 sprintf(command_errbuf, "can't find '%s'", name);
293 return(NULL);
294 }
295 name = cp;
296
288 err = 0;
289 for (i = 0, mp = NULL; (module_formats[i] != NULL) && (mp == NULL); i++) {
290 if ((err = (module_formats[i]->l_load)(name, loadaddr, &mp)) != 0) {
291
292 /* Unknown to this handler? */
293 if (err == EFTYPE)
294 continue;
295
296 /* Fatal error */
297 sprintf(command_errbuf, "can't load module '%s': %s", name, strerror(err));
298 return(NULL);
299 } else {
300
301 /* Load was OK, set args */
302 mp->m_args = unargv(argc, argv);
303
304 /* where can we put the next one? */
305 loadaddr = mp->m_addr + mp->m_size;
306
307 /* remember the loader */
308 mp->m_loader = i;
309
310 /* Add to the list of loaded modules */
311 mod_append(mp);
312
313 break;
314 }
315 }
316 if (err == EFTYPE)
317 sprintf(command_errbuf, "don't know how to load module '%s'", name);
318 return(mp);
319}
320
321/*
322 * Search the modules from (mp) onwards, and return the name of the
323 * first unresolved dependancy, or NULL if none were found.
324 */
325static char *
326mod_searchdep(struct loaded_module *mp)
327{
328 struct kld_module_identifier *ident, *dident;
329 struct kld_module_dependancy *deps, *dp;
330 struct module_metadata *md;
331 struct loaded_module *dmp;
332 int dindex;
333
334 for (; mp != NULL; mp = mp->m_next) {
335
336 /*
337 * Get KLD module data
338 */
339 ident = NULL;
340 deps = NULL;
341 if ((md = mod_findmetadata(mp, MODINFOMD_KLDIDENT)) != NULL)
342 ident = (struct kld_module_identifier *)md->md_data;
343 if ((md = mod_findmetadata(mp, MODINFOMD_KLDDEP)) != NULL)
344 deps = (struct kld_module_dependancy *)md->md_data;
345
346 /*
347 * Both must exist for this module to depend on anything
348 */
349 if ((ident != NULL) && (deps != NULL)) {
350
351 /* Iterate over dependancies */
352 for (dindex = 0; dindex < ident->ki_ndeps; dindex++) {
353 dp = KLD_GETDEP(ident, deps, dindex);
354
355 /*
356 * Look for a module matching the dependancy; if we don't have it,
357 * we need it.
358 */
359 if ((dmp = mod_findmodule(dp->kd_name, NULL)) == NULL)
360 return(dp->kd_name);
361
362 /* Version check */
363 if ((md = mod_findmetadata(dmp, MODINFOMD_KLDIDENT)) != NULL) {
364 dident = (struct kld_module_identifier *)md->md_data;
365 if (dp->kd_version != dident->ki_version)
366 printf("module '%s' requires '%s' version %d, but version %d is loaded\n",
367 mp->m_name, dp->kd_name, dp->kd_version, dident->ki_version);
368 }
369 }
370 }
371 }
372 return(NULL);
373}
374
375/*
376 * Find a module matching (name) and (type).
377 * NULL may be passed as a wildcard to either.
378 */
379struct loaded_module *
380mod_findmodule(char *name, char *type)
381{
382 struct loaded_module *mp;
383
384 for (mp = loaded_modules; mp != NULL; mp = mp->m_next) {
385 if (((name == NULL) || !strcmp(name, mp->m_name)) &&
386 ((type == NULL) || !strcmp(type, mp->m_type)))
387 break;
388 }
389 return(mp);
390}
391
392/*
393 * Make a copy of (size) bytes of data from (p), and associate them as
394 * metadata of (type) to the module (mp).
395 */
396void
397mod_addmetadata(struct loaded_module *mp, int type, size_t size, void *p)
398{
399 struct module_metadata *md;
400
401 md = malloc(sizeof(struct module_metadata) + size);
402 md->md_size = size;
403 md->md_type = type;
404 bcopy(p, md->md_data, size);
405 md->md_next = mp->m_metadata;
406 mp->m_metadata = md;
407}
408
409/*
410 * Find a metadata object of (type) associated with the module
411 * (mp)
412 */
413struct module_metadata *
414mod_findmetadata(struct loaded_module *mp, int type)
415{
416 struct module_metadata *md;
417
418 for (md = mp->m_metadata; md != NULL; md = md->md_next)
419 if (md->md_type == type)
420 break;
421 return(md);
422}
423
424/*
297 err = 0;
298 for (i = 0, mp = NULL; (module_formats[i] != NULL) && (mp == NULL); i++) {
299 if ((err = (module_formats[i]->l_load)(name, loadaddr, &mp)) != 0) {
300
301 /* Unknown to this handler? */
302 if (err == EFTYPE)
303 continue;
304
305 /* Fatal error */
306 sprintf(command_errbuf, "can't load module '%s': %s", name, strerror(err));
307 return(NULL);
308 } else {
309
310 /* Load was OK, set args */
311 mp->m_args = unargv(argc, argv);
312
313 /* where can we put the next one? */
314 loadaddr = mp->m_addr + mp->m_size;
315
316 /* remember the loader */
317 mp->m_loader = i;
318
319 /* Add to the list of loaded modules */
320 mod_append(mp);
321
322 break;
323 }
324 }
325 if (err == EFTYPE)
326 sprintf(command_errbuf, "don't know how to load module '%s'", name);
327 return(mp);
328}
329
330/*
331 * Search the modules from (mp) onwards, and return the name of the
332 * first unresolved dependancy, or NULL if none were found.
333 */
334static char *
335mod_searchdep(struct loaded_module *mp)
336{
337 struct kld_module_identifier *ident, *dident;
338 struct kld_module_dependancy *deps, *dp;
339 struct module_metadata *md;
340 struct loaded_module *dmp;
341 int dindex;
342
343 for (; mp != NULL; mp = mp->m_next) {
344
345 /*
346 * Get KLD module data
347 */
348 ident = NULL;
349 deps = NULL;
350 if ((md = mod_findmetadata(mp, MODINFOMD_KLDIDENT)) != NULL)
351 ident = (struct kld_module_identifier *)md->md_data;
352 if ((md = mod_findmetadata(mp, MODINFOMD_KLDDEP)) != NULL)
353 deps = (struct kld_module_dependancy *)md->md_data;
354
355 /*
356 * Both must exist for this module to depend on anything
357 */
358 if ((ident != NULL) && (deps != NULL)) {
359
360 /* Iterate over dependancies */
361 for (dindex = 0; dindex < ident->ki_ndeps; dindex++) {
362 dp = KLD_GETDEP(ident, deps, dindex);
363
364 /*
365 * Look for a module matching the dependancy; if we don't have it,
366 * we need it.
367 */
368 if ((dmp = mod_findmodule(dp->kd_name, NULL)) == NULL)
369 return(dp->kd_name);
370
371 /* Version check */
372 if ((md = mod_findmetadata(dmp, MODINFOMD_KLDIDENT)) != NULL) {
373 dident = (struct kld_module_identifier *)md->md_data;
374 if (dp->kd_version != dident->ki_version)
375 printf("module '%s' requires '%s' version %d, but version %d is loaded\n",
376 mp->m_name, dp->kd_name, dp->kd_version, dident->ki_version);
377 }
378 }
379 }
380 }
381 return(NULL);
382}
383
384/*
385 * Find a module matching (name) and (type).
386 * NULL may be passed as a wildcard to either.
387 */
388struct loaded_module *
389mod_findmodule(char *name, char *type)
390{
391 struct loaded_module *mp;
392
393 for (mp = loaded_modules; mp != NULL; mp = mp->m_next) {
394 if (((name == NULL) || !strcmp(name, mp->m_name)) &&
395 ((type == NULL) || !strcmp(type, mp->m_type)))
396 break;
397 }
398 return(mp);
399}
400
401/*
402 * Make a copy of (size) bytes of data from (p), and associate them as
403 * metadata of (type) to the module (mp).
404 */
405void
406mod_addmetadata(struct loaded_module *mp, int type, size_t size, void *p)
407{
408 struct module_metadata *md;
409
410 md = malloc(sizeof(struct module_metadata) + size);
411 md->md_size = size;
412 md->md_type = type;
413 bcopy(p, md->md_data, size);
414 md->md_next = mp->m_metadata;
415 mp->m_metadata = md;
416}
417
418/*
419 * Find a metadata object of (type) associated with the module
420 * (mp)
421 */
422struct module_metadata *
423mod_findmetadata(struct loaded_module *mp, int type)
424{
425 struct module_metadata *md;
426
427 for (md = mp->m_metadata; md != NULL; md = md->md_next)
428 if (md->md_type == type)
429 break;
430 return(md);
431}
432
433/*
425 * Attempt to locate a kernel module file for the module (name).
434 * Attempt to find the file (name) on the module searchpath.
426 * If (name) is qualified in any way, we simply check it and
427 * return it or NULL. If it is not qualified, then we attempt
428 * to construct a path using entries in the environment variable
429 * module_path.
430 *
431 * The path we return a pointer to need never be freed, as we manage
432 * it internally.
433 */
434static char *
435 * If (name) is qualified in any way, we simply check it and
436 * return it or NULL. If it is not qualified, then we attempt
437 * to construct a path using entries in the environment variable
438 * module_path.
439 *
440 * The path we return a pointer to need never be freed, as we manage
441 * it internally.
442 */
443static char *
435mod_searchmodule(char *name)
444mod_searchfile(char *name)
436{
437 static char *result = NULL;
445{
446 static char *result = NULL;
438 static char *defpath = "/boot", *path;
447 char *path;
439 char *cp, *sp;
440 struct stat sb;
441
442 /* Don't look for nothing */
443 if ((name == NULL) || (*name == 0))
444 return(name);
445
446 /*
447 * See if there's a device on the front, or a directory name.
448 */
449 archsw.arch_getdev(NULL, name, &cp);
450 if ((cp != name) || (strchr(name, '/') != NULL)) {
451 /* Qualified, so just see if it exists */
452 if (stat(name, &sb) == 0)
453 return(name);
454 return(NULL);
455 }
456
457 /*
458 * Get the module path
459 */
460 if ((cp = getenv("module_path")) == NULL)
448 char *cp, *sp;
449 struct stat sb;
450
451 /* Don't look for nothing */
452 if ((name == NULL) || (*name == 0))
453 return(name);
454
455 /*
456 * See if there's a device on the front, or a directory name.
457 */
458 archsw.arch_getdev(NULL, name, &cp);
459 if ((cp != name) || (strchr(name, '/') != NULL)) {
460 /* Qualified, so just see if it exists */
461 if (stat(name, &sb) == 0)
462 return(name);
463 return(NULL);
464 }
465
466 /*
467 * Get the module path
468 */
469 if ((cp = getenv("module_path")) == NULL)
461 cp = defpath;
470 cp = default_searchpath;
462 sp = path = strdup(cp);
463
464 /*
465 * Traverse the path, splitting off ';'-delimited components.
466 */
467 if (result != NULL)
468 free(result);
469 while((cp = strsep(&path, ";")) != NULL) {
471 sp = path = strdup(cp);
472
473 /*
474 * Traverse the path, splitting off ';'-delimited components.
475 */
476 if (result != NULL)
477 free(result);
478 while((cp = strsep(&path, ";")) != NULL) {
470 result = malloc(strlen(cp) + strlen(name) + 2);
471 sprintf(result, "%s/%s", cp, name);
472 if (stat(result, &sb) == 0)
479 result = malloc(strlen(cp) + strlen(name) + 5);
480 strcpy(result, cp);
481 if (cp[strlen(cp) - 1] != '/')
482 strcat(result, "/");
483 strcat(result, name);
484/* printf("search '%s'\n", result); */
485 if ((stat(result, &sb) == 0) &&
486 S_ISREG(sb.st_mode))
473 break;
474 free(result);
475 result = NULL;
476 }
477 free(sp);
478 return(result);
479}
480
481/*
487 break;
488 free(result);
489 result = NULL;
490 }
491 free(sp);
492 return(result);
493}
494
495/*
496 * Attempt to locate the file containing the module (name)
497 */
498static char *
499mod_searchmodule(char *name)
500{
501 char *tn, *result;
502
503 /* Look for (name).ko */
504 tn = malloc(strlen(name) + 3);
505 strcpy(tn, name);
506 strcat(tn, ".ko");
507 result = mod_searchfile(tn);
508 free(tn);
509 /* Look for just (name) (useful for finding kernels) */
510 if (result == NULL)
511 result = mod_searchfile(name);
512
513 return(result);
514}
515
516
517/*
482 * Throw a module away
483 */
484void
485mod_discard(struct loaded_module *mp)
486{
487 struct module_metadata *md;
488
518 * Throw a module away
519 */
520void
521mod_discard(struct loaded_module *mp)
522{
523 struct module_metadata *md;
524
489 while (mp->m_metadata != NULL) {
490 md = mp->m_metadata;
491 mp->m_metadata = mp->m_metadata->md_next;
492 free(md);
493 }
494 if (mp->m_name != NULL)
495 free(mp->m_name);
496 if (mp->m_type != NULL)
497 free(mp->m_type);
498 if (mp->m_args != NULL)
499 free(mp->m_args);
500 free(mp);
525 if (mp != NULL) {
526 while (mp->m_metadata != NULL) {
527 md = mp->m_metadata;
528 mp->m_metadata = mp->m_metadata->md_next;
529 free(md);
530 }
531 if (mp->m_name != NULL)
532 free(mp->m_name);
533 if (mp->m_type != NULL)
534 free(mp->m_type);
535 if (mp->m_args != NULL)
536 free(mp->m_args);
537 free(mp);
538 }
501}
502
503/*
539}
540
541/*
542 * Allocate a new module; must be used instead of malloc()
543 * to ensure safe initialisation.
544 */
545struct loaded_module *
546mod_allocmodule(void)
547{
548 struct loaded_module *mp;
549
550 if ((mp = malloc(sizeof(struct loaded_module))) != NULL) {
551 bzero(mp, sizeof(struct loaded_module));
552 }
553 return(mp);
554}
555
556
557/*
504 * Add a module to the chain
505 */
506static void
507mod_append(struct loaded_module *mp)
508{
509 struct loaded_module *cm;
510
511 /* Append to list of loaded modules */
512 mp->m_next = NULL;
513 if (loaded_modules == NULL) {
514 loaded_modules = mp;
515 } else {
516 for (cm = loaded_modules; cm->m_next != NULL; cm = cm->m_next)
517 ;
518 cm->m_next = mp;
519 }
520}
558 * Add a module to the chain
559 */
560static void
561mod_append(struct loaded_module *mp)
562{
563 struct loaded_module *cm;
564
565 /* Append to list of loaded modules */
566 mp->m_next = NULL;
567 if (loaded_modules == NULL) {
568 loaded_modules = mp;
569 } else {
570 for (cm = loaded_modules; cm->m_next != NULL; cm = cm->m_next)
571 ;
572 cm->m_next = mp;
573 }
574}