2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * $FreeBSD: src/sys/boot/common/module.c,v 1.13.2.4 2002/12/19 12:41:10 thomas Exp $
27 * $DragonFly: src/sys/boot/common/module.c,v 1.2 2003/06/17 04:28:17 dillon Exp $
31 * module function dispatcher, support, etc.
36 #include <sys/param.h>
37 #include <sys/linker.h>
39 #include "bootstrap.h"
41 static int mod_loadmodule(char *name, int argc, char *argv[], struct loaded_module **mpp);
42 static int file_load_dependancies(struct loaded_module *base_file);
43 static char *mod_searchfile(char *name);
44 static char *mod_searchmodule(char *name);
45 static void mod_append(struct loaded_module *mp);
46 static struct module_metadata *metadata_next(struct module_metadata *md, int type);
48 /* load address should be tweaked by first module loaded (kernel) */
49 static vm_offset_t loadaddr = 0;
51 static const char *default_searchpath ="/;/boot;/modules";
53 struct loaded_module *loaded_modules = NULL;
56 * load an object, either a disk file or code module.
58 * To load a file, the syntax is:
60 * load -t <type> <path>
62 * code modules are loaded as:
64 * load <path> <options>
67 COMMAND_SET(load, "load", "load a kernel or module", command_load);
70 command_load(int argc, char *argv[])
73 int dofile, ch, error;
80 command_errmsg = "no filename specified";
83 while ((ch = getopt(argc, argv, "t:")) != -1) {
91 /* getopt has already reported an error */
99 * Request to load a raw file?
102 if ((argc != 2) || (typestr == NULL) || (*typestr == 0)) {
103 command_errmsg = "invalid load type";
106 return(mod_loadobj(typestr, argv[1]));
110 * Looks like a request for a module.
112 error = mod_load(argv[1], argc - 2, argv + 2);
114 sprintf(command_errbuf, "warning: module '%s' already loaded", argv[1]);
115 return (error == 0 ? CMD_OK : CMD_ERROR);
118 COMMAND_SET(unload, "unload", "unload all modules", command_unload);
121 command_unload(int argc, char *argv[])
123 struct loaded_module *mp;
125 while (loaded_modules != NULL) {
127 loaded_modules = loaded_modules->m_next;
134 COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod);
137 command_lsmod(int argc, char *argv[])
139 struct loaded_module *am;
140 struct module_metadata *md;
147 while ((ch = getopt(argc, argv, "v")) != -1) {
154 /* getopt has already reported an error */
160 for (am = loaded_modules; (am != NULL); am = am->m_next) {
161 sprintf(lbuf, " %p: %s (%s, 0x%lx)\n",
162 (void *) am->m_addr, am->m_name, am->m_type, (long) am->m_size);
164 if (am->m_args != NULL) {
165 pager_output(" args: ");
166 pager_output(am->m_args);
170 /* XXX could add some formatting smarts here to display some better */
171 for (md = am->m_metadata; md != NULL; md = md->md_next) {
172 sprintf(lbuf, " 0x%04x, 0x%lx\n", md->md_type, (long) md->md_size);
181 * We've been asked to load (name) and give it (argc),(argv).
182 * Start by trying to load it, and then attempt to load all of its
183 * dependancies. If we fail at any point, throw them all away and
184 * fail the entire load.
186 * XXX if a depended-on module requires arguments, it must be loaded
190 mod_load(char *name, int argc, char *argv[])
192 struct loaded_module *last_mod, *base_mod, *mp;
195 /* remember previous last module on chain */
196 for (last_mod = loaded_modules;
197 (last_mod != NULL) && (last_mod->m_next != NULL);
198 last_mod = last_mod->m_next)
202 * Load the first module; note that it's the only one that gets
203 * arguments explicitly.
205 error = mod_loadmodule(name, argc, argv, &base_mod);
209 error = file_load_dependancies(base_mod);
213 /* Load failed; discard everything */
214 last_mod->m_next = NULL;
215 loadaddr = last_mod->m_addr + last_mod->m_size;
216 while (base_mod != NULL) {
218 base_mod = base_mod->m_next;
225 * We've been asked to load (name) as (type), so just suck it in,
226 * no arguments or anything.
229 mod_loadobj(char *type, char *name)
231 struct loaded_module *mp;
236 /* We can't load first */
237 if ((mod_findmodule(NULL, NULL)) == NULL) {
238 command_errmsg = "can't load file before kernel";
242 /* locate the file on the load path */
243 cp = mod_searchfile(name);
245 sprintf(command_errbuf, "can't find '%s'", name);
250 if ((fd = open(name, O_RDONLY)) < 0) {
251 sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno));
258 /* read in 4k chunks; size is not really important */
259 got = archsw.arch_readin(fd, laddr, 4096);
260 if (got == 0) /* end of file */
262 if (got < 0) { /* error */
263 sprintf(command_errbuf, "error reading '%s': %s", name, strerror(errno));
271 /* Looks OK so far; create & populate control structure */
272 mp = malloc(sizeof(struct loaded_module));
274 mp->m_type = strdup(type);
276 mp->m_metadata = NULL;
278 mp->m_addr = loadaddr;
279 mp->m_size = laddr - loadaddr;
281 /* recognise space consumption */
284 /* Add to the list of loaded modules */
291 * Load the module (name), pass it (argc),(argv).
292 * Don't do any dependancy checking.
295 mod_loadmodule(char *name, int argc, char *argv[], struct loaded_module **mpp)
297 struct loaded_module *mp;
301 /* locate the module on the search path */
302 cp = mod_searchmodule(name);
304 sprintf(command_errbuf, "can't find '%s'", name);
309 cp = strrchr(name, '/');
314 /* see if module is already loaded */
315 mp = mod_findmodule(cp, NULL);
322 for (i = 0, mp = NULL; (module_formats[i] != NULL) && (mp == NULL); i++) {
323 if ((err = (module_formats[i]->l_load)(name, loadaddr, &mp)) != 0) {
325 /* Unknown to this handler? */
330 sprintf(command_errbuf, "can't load module '%s': %s", name, strerror(err));
335 /* Load was OK, set args */
336 mp->m_args = unargv(argc, argv);
338 /* where can we put the next one? */
339 loadaddr = mp->m_addr + mp->m_size;
341 /* remember the loader */
344 /* Add to the list of loaded modules */
352 sprintf(command_errbuf, "don't know how to load module '%s'", name);
358 file_load_dependancies(struct loaded_module *base_file)
360 struct module_metadata *md;
364 md = mod_findmetadata(base_file, MODINFOMD_DEPLIST);
369 dmodname = (char *)md->md_data;
370 if (mod_findmodule(NULL, dmodname) == NULL) {
371 printf("loading required module '%s'\n", dmodname);
372 error = mod_load(dmodname, 0, NULL);
378 md = metadata_next(md, MODINFOMD_DEPLIST);
384 * Find a module matching (name) and (type).
385 * NULL may be passed as a wildcard to either.
387 struct loaded_module *
388 mod_findmodule(char *name, char *type)
390 struct loaded_module *mp;
392 for (mp = loaded_modules; mp != NULL; mp = mp->m_next) {
393 if (((name == NULL) || !strcmp(name, mp->m_name)) &&
394 ((type == NULL) || !strcmp(type, mp->m_type)))
401 * Make a copy of (size) bytes of data from (p), and associate them as
402 * metadata of (type) to the module (mp).
405 mod_addmetadata(struct loaded_module *mp, int type, size_t size, void *p)
407 struct module_metadata *md;
409 md = malloc(sizeof(struct module_metadata) + size);
412 bcopy(p, md->md_data, size);
413 md->md_next = mp->m_metadata;
418 * Find a metadata object of (type) associated with the module
421 struct module_metadata *
422 mod_findmetadata(struct loaded_module *mp, int type)
424 struct module_metadata *md;
426 for (md = mp->m_metadata; md != NULL; md = md->md_next)
427 if (md->md_type == type)
432 struct module_metadata *
433 metadata_next(struct module_metadata *md, int type)
437 while((md = md->md_next) != NULL)
438 if (md->md_type == type)
444 * Attempt to find the file (name) on the module searchpath.
445 * If (name) is qualified in any way, we simply check it and
446 * return it or NULL. If it is not qualified, then we attempt
447 * to construct a path using entries in the environment variable
450 * The path we return a pointer to need never be freed, as we manage
454 mod_searchfile(char *name)
461 /* Don't look for nothing */
466 return(strdup(name));
469 * See if there's a device on the front, or a directory name.
471 archsw.arch_getdev(NULL, name, &cp);
472 if ((cp != name) || (strchr(name, '/') != NULL)) {
473 /* Qualified, so just see if it exists */
474 if (stat(name, &sb) == 0)
475 return(strdup(name));
480 * Get the module path
482 if ((cp = getenv("module_path")) == NULL)
483 cp = default_searchpath;
484 sp = path = strdup(cp);
487 * Traverse the path, splitting off ';'-delimited components.
490 while((cp = strsep(&path, ";")) != NULL) {
491 result = malloc(strlen(cp) + strlen(name) + 5);
493 if (cp[strlen(cp) - 1] != '/')
495 strcat(result, name);
496 /* printf("search '%s'\n", result); */
497 if ((stat(result, &sb) == 0) &&
508 * Attempt to locate the file containing the module (name)
511 mod_searchmodule(char *name)
515 /* Look for (name).ko */
516 tn = malloc(strlen(name) + 3 + 1);
519 result = mod_searchfile(tn);
521 /* Look for just (name) (useful for finding kernels) */
523 result = mod_searchfile(name);
530 * Throw a module away
533 mod_discard(struct loaded_module *mp)
535 struct module_metadata *md;
538 while (mp->m_metadata != NULL) {
540 mp->m_metadata = mp->m_metadata->md_next;
543 if (mp->m_name != NULL)
545 if (mp->m_type != NULL)
547 if (mp->m_args != NULL)
554 * Allocate a new module; must be used instead of malloc()
555 * to ensure safe initialisation.
557 struct loaded_module *
558 mod_allocmodule(void)
560 struct loaded_module *mp;
562 if ((mp = malloc(sizeof(struct loaded_module))) != NULL) {
563 bzero(mp, sizeof(struct loaded_module));
570 * Add a module to the chain
573 mod_append(struct loaded_module *mp)
575 struct loaded_module *cm;
577 /* Append to list of loaded modules */
579 if (loaded_modules == NULL) {
582 for (cm = loaded_modules; cm->m_next != NULL; cm = cm->m_next)