]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - stand/common/module.c
Add missing break statements in r351004.
[FreeBSD/FreeBSD.git] / stand / common / module.c
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
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 /*
31  * file/module function dispatcher, support, etc.
32  */
33
34 #include <stand.h>
35 #include <string.h>
36 #include <sys/param.h>
37 #include <sys/linker.h>
38 #include <sys/module.h>
39 #include <sys/queue.h>
40 #include <sys/stdint.h>
41
42 #if defined(LOADER_FDT_SUPPORT)
43 #include <fdt_platform.h>
44 #endif
45
46 #include "bootstrap.h"
47
48 #define MDIR_REMOVED    0x0001
49 #define MDIR_NOHINTS    0x0002
50
51 struct moduledir {
52         char    *d_path;        /* path of modules directory */
53         u_char  *d_hints;       /* content of linker.hints file */
54         int     d_hintsz;       /* size of hints data */
55         int     d_flags;
56         STAILQ_ENTRY(moduledir) d_link;
57 };
58
59 static int                      file_load(char *filename, vm_offset_t dest, struct preloaded_file **result);
60 static int                      file_load_dependencies(struct preloaded_file *base_mod);
61 static char *                   file_search(const char *name, char **extlist);
62 static struct kernel_module *   file_findmodule(struct preloaded_file *fp, char *modname, struct mod_depend *verinfo);
63 static int                      file_havepath(const char *name);
64 static char                     *mod_searchmodule(char *name, struct mod_depend *verinfo);
65 static char *                   mod_searchmodule_pnpinfo(const char *bus, const char *pnpinfo);
66 static void                     file_insert_tail(struct preloaded_file *mp);
67 static void                     file_remove(struct preloaded_file *fp);
68 struct file_metadata*           metadata_next(struct file_metadata *base_mp, int type);
69 static void                     moduledir_readhints(struct moduledir *mdp);
70 static void                     moduledir_rebuild(void);
71
72 /* load address should be tweaked by first module loaded (kernel) */
73 static vm_offset_t      loadaddr = 0;
74
75 #if defined(LOADER_FDT_SUPPORT)
76 static const char       *default_searchpath =
77     "/boot/kernel;/boot/modules;/boot/dtb";
78 #else
79 static const char       *default_searchpath = "/boot/kernel;/boot/modules";
80 #endif
81
82 static STAILQ_HEAD(, moduledir) moduledir_list =
83     STAILQ_HEAD_INITIALIZER(moduledir_list);
84
85 struct preloaded_file *preloaded_files = NULL;
86
87 static char *kld_ext_list[] = {
88     ".ko",
89     "",
90     ".debug",
91     NULL
92 };
93
94
95 /*
96  * load an object, either a disk file or code module.
97  *
98  * To load a file, the syntax is:
99  *
100  * load -t <type> <path>
101  *
102  * code modules are loaded as:
103  *
104  * load <path> <options>
105  */
106
107 COMMAND_SET(load, "load", "load a kernel or module", command_load);
108
109 static int
110 command_load(int argc, char *argv[])
111 {
112         struct preloaded_file *fp;
113         char    *typestr;
114         char    *prefix;
115         char    *skip;
116         int             dflag, dofile, dokld, ch, error;
117
118         dflag = dokld = dofile = 0;
119         optind = 1;
120         optreset = 1;
121         typestr = NULL;
122         if (argc == 1) {
123                 command_errmsg = "no filename specified";
124                 return (CMD_CRIT);
125         }
126         prefix = skip = NULL;
127         while ((ch = getopt(argc, argv, "dkp:s:t:")) != -1) {
128                 switch(ch) {
129                 case 'd':
130                         dflag++;
131                         break;
132                 case 'k':
133                         dokld = 1;
134                         break;
135                 case 'p':
136                         prefix = optarg;
137                         break;
138                 case 's':
139                         skip = optarg;
140                         break;
141                 case 't':
142                         typestr = optarg;
143                         dofile = 1;
144                         break;
145                 case '?':
146                 default:
147                         /* getopt has already reported an error */
148                         return (CMD_OK);
149                 }
150         }
151         argv += (optind - 1);
152         argc -= (optind - 1);
153
154         /*
155          * Request to load a raw file?
156          */
157         if (dofile) {
158                 if ((argc != 2) || (typestr == NULL) || (*typestr == 0)) {
159                         command_errmsg = "invalid load type";
160                         return (CMD_CRIT);
161                 }
162
163 #ifdef LOADER_VERIEXEC
164                 if (strncmp(typestr, "manifest", 8) == 0) {
165                         if (dflag > 0)
166                                 ve_debug_set(dflag);
167                         return (load_manifest(argv[1], prefix, skip, NULL));
168                 }
169 #ifdef LOADER_VERIEXEC_PASS_MANIFEST
170                 if (strncmp(typestr, "pass_manifest", 13) == 0) {
171                         if (dflag > 0)
172                                 ve_debug_set(dflag);
173                     return (pass_manifest(argv[1], prefix));
174                 }
175 #endif
176 #endif
177
178                 fp = file_findfile(argv[1], typestr);
179                 if (fp) {
180                         snprintf(command_errbuf, sizeof(command_errbuf),
181                           "warning: file '%s' already loaded", argv[1]);
182                         return (CMD_WARN);
183                 }
184
185                 if (file_loadraw(argv[1], typestr, 1) != NULL)
186                         return (CMD_OK);
187
188                 /* Failing to load mfs_root is never going to end well! */
189                 if (strcmp("mfs_root", typestr) == 0)
190                         return (CMD_FATAL);
191
192                 return (CMD_ERROR);
193         }
194         /*
195          * Do we have explicit KLD load ?
196          */
197         if (dokld || file_havepath(argv[1])) {
198                 error = mod_loadkld(argv[1], argc - 2, argv + 2);
199                 if (error == EEXIST) {
200                         snprintf(command_errbuf, sizeof(command_errbuf),
201                           "warning: KLD '%s' already loaded", argv[1]);
202                         return (CMD_WARN);
203                 }
204         
205                 return (error == 0 ? CMD_OK : CMD_CRIT);
206         }
207         /*
208          * Looks like a request for a module.
209          */
210         error = mod_load(argv[1], NULL, argc - 2, argv + 2);
211         if (error == EEXIST) {
212                 snprintf(command_errbuf, sizeof(command_errbuf),
213                   "warning: module '%s' already loaded", argv[1]);
214                 return (CMD_WARN);
215         }
216
217         return (error == 0 ? CMD_OK : CMD_CRIT);
218 }
219
220 #ifdef LOADER_GELI_SUPPORT
221 COMMAND_SET(load_geli, "load_geli", "load a geli key", command_load_geli);
222
223 static int
224 command_load_geli(int argc, char *argv[])
225 {
226         char    typestr[80];
227         char    *cp;
228         int             ch, num;
229
230         if (argc < 3) {
231                 command_errmsg = "usage is [-n key#] <prov> <file>";
232                 return(CMD_ERROR);
233         }
234
235         num = 0;
236         optind = 1;
237         optreset = 1;
238         while ((ch = getopt(argc, argv, "n:")) != -1) {
239                 switch(ch) {
240                 case 'n':
241                         num = strtol(optarg, &cp, 0);
242                         if (cp == optarg) {
243                                 snprintf(command_errbuf, sizeof(command_errbuf),
244                                   "bad key index '%s'", optarg);
245                                 return(CMD_ERROR);
246                         }
247                         break;
248                 case '?':
249                 default:
250                         /* getopt has already reported an error */
251                         return(CMD_OK);
252                 }
253         }
254         argv += (optind - 1);
255         argc -= (optind - 1);
256         sprintf(typestr, "%s:geli_keyfile%d", argv[1], num);
257         return (file_loadraw(argv[2], typestr, 1) ? CMD_OK : CMD_ERROR);
258 }
259 #endif
260
261 void
262 unload(void)
263 {
264         struct preloaded_file *fp;
265
266         while (preloaded_files != NULL) {
267                 fp = preloaded_files;
268                 preloaded_files = preloaded_files->f_next;
269                 file_discard(fp);
270         }
271         loadaddr = 0;
272         unsetenv("kernelname");
273 }
274
275 COMMAND_SET(unload, "unload", "unload all modules", command_unload);
276
277 static int
278 command_unload(int argc, char *argv[])
279 {
280         unload();
281         return(CMD_OK);
282 }
283
284 COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod);
285
286 static int
287 command_lsmod(int argc, char *argv[])
288 {
289         struct preloaded_file   *fp;
290         struct kernel_module    *mp;
291         struct file_metadata    *md;
292         char                    lbuf[80];
293         int                             ch, verbose, ret = 0;
294
295         verbose = 0;
296         optind = 1;
297         optreset = 1;
298         while ((ch = getopt(argc, argv, "v")) != -1) {
299                 switch(ch) {
300                 case 'v':
301                         verbose = 1;
302                         break;
303                 case '?':
304                 default:
305                         /* getopt has already reported an error */
306                         return(CMD_OK);
307                 }
308         }
309
310         pager_open();
311         for (fp = preloaded_files; fp; fp = fp->f_next) {
312                 snprintf(lbuf, sizeof(lbuf), " %p: ", (void *) fp->f_addr);
313                 pager_output(lbuf);
314                 pager_output(fp->f_name);
315                 snprintf(lbuf, sizeof(lbuf), " (%s, 0x%lx)\n", fp->f_type,
316                   (long)fp->f_size);
317                 if (pager_output(lbuf))
318                         break;
319                 if (fp->f_args != NULL) {
320                         pager_output("    args: ");
321                         pager_output(fp->f_args);
322                         if (pager_output("\n"))
323                                 break;
324                 }
325                 if (fp->f_modules) {
326                         pager_output("  modules: ");
327                         for (mp = fp->f_modules; mp; mp = mp->m_next) {
328                                 snprintf(lbuf, sizeof(lbuf), "%s.%d ", mp->m_name,
329                                   mp->m_version);
330                                 pager_output(lbuf);
331                         }
332                         if (pager_output("\n"))
333                                 break;
334                 }
335                 if (verbose) {
336                         /* XXX could add some formatting smarts here to display some better */
337                         for (md = fp->f_metadata; md != NULL; md = md->md_next) {
338                                 snprintf(lbuf, sizeof(lbuf), "      0x%04x, 0x%lx\n",
339                                   md->md_type, (long) md->md_size);
340                                 if (pager_output(lbuf))
341                                         break;
342                         }
343                 }
344                 if (ret)
345                         break;
346         }
347         pager_close();
348         return(CMD_OK);
349 }
350
351 COMMAND_SET(pnpmatch, "pnpmatch", "list matched modules based on pnpinfo", command_pnpmatch);
352
353 static int pnp_dump_flag = 0;
354 static int pnp_unbound_flag = 0;
355 static int pnp_verbose_flag = 0;
356
357 static int
358 command_pnpmatch(int argc, char *argv[])
359 {
360         char *module;
361         int ch;
362
363         pnp_verbose_flag = 0;
364         pnp_dump_flag = 0;
365         optind = 1;
366         optreset = 1;
367         while ((ch = getopt(argc, argv, "vd")) != -1) {
368                 switch(ch) {
369                 case 'v':
370                         pnp_verbose_flag = 1;
371                         break;
372                 case 'd':
373                         pnp_dump_flag = 1;
374                         break;
375                 case '?':
376                 default:
377                         /* getopt has already reported an error */
378                         return(CMD_OK);
379                 }
380         }
381         argv += (optind - 1);
382         argc -= (optind - 1);
383
384         module = mod_searchmodule_pnpinfo(argv[1], argv[2]);
385         if (module)
386                 printf("Matched module: %s\n", module);
387         else if(argv[1])
388                 printf("No module matches %s\n", argv[1]);
389
390         return (CMD_OK);
391 }
392
393 COMMAND_SET(pnpload, "pnpload", "load matched modules based on pnpinfo", command_pnpload);
394
395 static int
396 command_pnpload(int argc, char *argv[])
397 {
398         char *module;
399         int ch, error;
400
401         pnp_verbose_flag = 0;
402         pnp_dump_flag = 0;
403         optind = 1;
404         optreset = 1;
405         while ((ch = getopt(argc, argv, "vd")) != -1) {
406                 switch(ch) {
407                 case 'v':
408                         pnp_verbose_flag = 1;
409                         break;
410                 case 'd':
411                         pnp_dump_flag = 1;
412                         break;
413                 case '?':
414                 default:
415                         /* getopt has already reported an error */
416                         return(CMD_OK);
417                 }
418         }
419         argv += (optind - 1);
420         argc -= (optind - 1);
421
422         if (argc != 2)
423                 return (CMD_ERROR);
424
425         module = mod_searchmodule_pnpinfo(argv[1], argv[2]);
426
427         error = mod_load(module, NULL, 0, NULL);
428         if (error == EEXIST) {
429                 snprintf(command_errbuf, sizeof(command_errbuf),
430                   "warning: module '%s' already loaded", argv[1]);
431                 return (CMD_WARN);
432         }
433
434         return (error == 0 ? CMD_OK : CMD_CRIT);
435 }
436
437 #if defined(LOADER_FDT_SUPPORT)
438 static void
439 pnpautoload_simplebus(void) {
440         const char *pnpstring;
441         const char *compatstr;
442         char *pnpinfo = NULL;
443         char *module = NULL;
444         int tag = 0, len, pnplen;
445         int error;
446
447         while (1) {
448                 pnpstring = fdt_devmatch_next(&tag, &len);
449                 if (pnpstring == NULL)
450                         return;
451
452                 compatstr = pnpstring;
453                 for (pnplen = 0; pnplen != len; compatstr = pnpstring + pnplen) {
454                         pnplen += strlen(compatstr) + 1;
455                         asprintf(&pnpinfo, "compat=%s", compatstr);
456
457                         module = mod_searchmodule_pnpinfo("simplebus", pnpinfo);
458                         if (module) {
459                                 error = mod_loadkld(module, 0, NULL);
460                                 if (error)
461                                         printf("Cannot load module %s\n", module);
462                                 break;
463                         }
464                 }
465                 free(pnpinfo);
466                 free(module);
467         }
468 }
469 #endif
470
471 struct pnp_bus {
472         const char *name;
473         void (*load)(void);
474 };
475
476 struct pnp_bus pnp_buses[] = {
477 #if defined(LOADER_FDT_SUPPORT)
478         {"simplebus", pnpautoload_simplebus},
479 #endif
480 };
481
482 COMMAND_SET(pnpautoload, "pnpautoload", "auto load modules based on pnpinfo", command_pnpautoload);
483
484 static int
485 command_pnpautoload(int argc, char *argv[])
486 {
487         int i;
488         int verbose;
489         int ch, match;
490
491         pnp_verbose_flag = 0;
492         pnp_dump_flag = 0;
493         verbose = 0;
494         optind = 1;
495         optreset = 1;
496         match = 0;
497         while ((ch = getopt(argc, argv, "v")) != -1) {
498                 switch(ch) {
499                 case 'v':
500                         verbose = 1;
501                         break;
502                 case '?':
503                 default:
504                         /* getopt has already reported an error */
505                         return(CMD_OK);
506                 }
507         }
508         argv += (optind - 1);
509         argc -= (optind - 1);
510
511         if (argc > 2)
512                 return (CMD_ERROR);
513
514         for (i = 0; i < nitems(pnp_buses); i++) {
515                 if (argc == 2 && strcmp(argv[1], pnp_buses[i].name) != 0) {
516                         if (verbose)
517                                 printf("Skipping bus %s\n", pnp_buses[i].name);
518                         continue;
519                 }
520                 if (verbose)
521                         printf("Autoloading modules for simplebus\n");
522                 pnp_buses[i].load();
523                 match = 1;
524         }
525         if (match == 0)
526                 printf("Unsupported bus %s\n", argv[1]);
527
528         return (CMD_OK);
529 }
530
531 /*
532  * File level interface, functions file_*
533  */
534 int
535 file_load(char *filename, vm_offset_t dest, struct preloaded_file **result)
536 {
537         static int last_file_format = 0;
538         struct preloaded_file *fp;
539         int error;
540         int i;
541
542         if (archsw.arch_loadaddr != NULL)
543                 dest = archsw.arch_loadaddr(LOAD_RAW, filename, dest);
544
545         error = EFTYPE;
546         for (i = last_file_format, fp = NULL;
547              file_formats[i] && fp == NULL; i++) {
548                 error = (file_formats[i]->l_load)(filename, dest, &fp);
549                 if (error == 0) {
550                         fp->f_loader = last_file_format = i; /* remember the loader */
551                         *result = fp;
552                         break;
553                 } else if (last_file_format == i && i != 0) {
554                         /* Restart from the beginning */
555                         i = -1;
556                         last_file_format = 0;
557                         fp = NULL;
558                         continue;
559                 }
560                 if (error == EFTYPE)
561                         continue;               /* Unknown to this handler? */
562                 if (error) {
563                         snprintf(command_errbuf, sizeof(command_errbuf),
564                           "can't load file '%s': %s", filename, strerror(error));
565                         break;
566                 }
567         }
568         return (error);
569 }
570
571 static int
572 file_load_dependencies(struct preloaded_file *base_file)
573 {
574         struct file_metadata *md;
575         struct preloaded_file *fp;
576         struct mod_depend *verinfo;
577         struct kernel_module *mp;
578         char *dmodname;
579         int error;
580
581         md = file_findmetadata(base_file, MODINFOMD_DEPLIST);
582         if (md == NULL)
583                 return (0);
584         error = 0;
585         do {
586                 verinfo = (struct mod_depend*)md->md_data;
587                 dmodname = (char *)(verinfo + 1);
588                 if (file_findmodule(NULL, dmodname, verinfo) == NULL) {
589                         printf("loading required module '%s'\n", dmodname);
590                         error = mod_load(dmodname, verinfo, 0, NULL);
591                         if (error)
592                                 break;
593                         /*
594                          * If module loaded via kld name which isn't listed
595                          * in the linker.hints file, we should check if it have
596                          * required version.
597                          */
598                         mp = file_findmodule(NULL, dmodname, verinfo);
599                         if (mp == NULL) {
600                                 snprintf(command_errbuf, sizeof(command_errbuf),
601                                   "module '%s' exists but with wrong version", dmodname);
602                                 error = ENOENT;
603                                 break;
604                         }
605                 }
606                 md = metadata_next(md, MODINFOMD_DEPLIST);
607         } while (md);
608         if (!error)
609                 return (0);
610         /* Load failed; discard everything */
611         while (base_file != NULL) {
612                 fp = base_file;
613                 base_file = base_file->f_next;
614                 file_discard(fp);
615         }
616         return (error);
617 }
618
619 /*
620  * We've been asked to load (fname) as (type), so just suck it in,
621  * no arguments or anything.
622  */
623 struct preloaded_file *
624 file_loadraw(const char *fname, char *type, int insert)
625 {
626         struct preloaded_file   *fp;
627         char                    *name;
628         int                             fd, got;
629         vm_offset_t                     laddr;
630
631         /* We can't load first */
632         if ((file_findfile(NULL, NULL)) == NULL) {
633                 command_errmsg = "can't load file before kernel";
634                 return(NULL);
635         }
636
637         /* locate the file on the load path */
638         name = file_search(fname, NULL);
639         if (name == NULL) {
640                 snprintf(command_errbuf, sizeof(command_errbuf),
641                   "can't find '%s'", fname);
642                 return(NULL);
643         }
644
645         if ((fd = open(name, O_RDONLY)) < 0) {
646                 snprintf(command_errbuf, sizeof(command_errbuf),
647                   "can't open '%s': %s", name, strerror(errno));
648                 free(name);
649                 return(NULL);
650         }
651
652 #ifdef LOADER_VERIEXEC
653         if (verify_file(fd, name, 0, VE_MUST) < 0) {
654                 sprintf(command_errbuf, "can't verify '%s'", name);
655                 free(name);
656                 close(fd);
657                 return(NULL);
658         }
659 #endif
660
661         if (archsw.arch_loadaddr != NULL)
662                 loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr);
663
664         printf("%s ", name);
665
666         laddr = loadaddr;
667         for (;;) {
668                 /* read in 4k chunks; size is not really important */
669                 got = archsw.arch_readin(fd, laddr, 4096);
670                 if (got == 0)                           /* end of file */
671                         break;
672                 if (got < 0) {                          /* error */
673                         snprintf(command_errbuf, sizeof(command_errbuf),
674                           "error reading '%s': %s", name, strerror(errno));
675                         free(name);
676                         close(fd);
677                         return(NULL);
678                 }
679                 laddr += got;
680         }
681
682         printf("size=%#jx\n", (uintmax_t)(laddr - loadaddr));
683
684         /* Looks OK so far; create & populate control structure */
685         fp = file_alloc();
686         if (fp == NULL) {
687                 snprintf(command_errbuf, sizeof (command_errbuf),
688                     "no memory to load %s", name);
689                 free(name);
690                 close(fd);
691                 return (NULL);
692         }
693         fp->f_name = name;
694         fp->f_type = strdup(type);
695         fp->f_args = NULL;
696         fp->f_metadata = NULL;
697         fp->f_loader = -1;
698         fp->f_addr = loadaddr;
699         fp->f_size = laddr - loadaddr;
700
701         if (fp->f_type == NULL) {
702                 snprintf(command_errbuf, sizeof (command_errbuf),
703                     "no memory to load %s", name);
704                 free(name);
705                 close(fd);
706                 return (NULL);
707         }
708         /* recognise space consumption */
709         loadaddr = laddr;
710
711         /* Add to the list of loaded files */
712         if (insert != 0)
713                 file_insert_tail(fp);
714         close(fd);
715         return(fp);
716 }
717
718 /*
719  * Load the module (name), pass it (argc),(argv), add container file
720  * to the list of loaded files.
721  * If module is already loaded just assign new argc/argv.
722  */
723 int
724 mod_load(char *modname, struct mod_depend *verinfo, int argc, char *argv[])
725 {
726         struct kernel_module    *mp;
727         int                             err;
728         char                    *filename;
729
730         if (file_havepath(modname)) {
731                 printf("Warning: mod_load() called instead of mod_loadkld() for module '%s'\n", modname);
732                 return (mod_loadkld(modname, argc, argv));
733         }
734         /* see if module is already loaded */
735         mp = file_findmodule(NULL, modname, verinfo);
736         if (mp) {
737 #ifdef moduleargs
738                 free(mp->m_args);
739                 mp->m_args = unargv(argc, argv);
740 #endif
741                 snprintf(command_errbuf, sizeof(command_errbuf),
742                   "warning: module '%s' already loaded", mp->m_name);
743                 return (0);
744         }
745         /* locate file with the module on the search path */
746         filename = mod_searchmodule(modname, verinfo);
747         if (filename == NULL) {
748                 snprintf(command_errbuf, sizeof(command_errbuf),
749                   "can't find '%s'", modname);
750                 return (ENOENT);
751         }
752         err = mod_loadkld(filename, argc, argv);
753         free(filename);
754         return (err);
755 }
756
757 /*
758  * Load specified KLD. If path is omitted, then try to locate it via
759  * search path.
760  */
761 int
762 mod_loadkld(const char *kldname, int argc, char *argv[])
763 {
764         struct preloaded_file   *fp;
765         int                     err;
766         char                    *filename;
767         vm_offset_t             loadaddr_saved;
768
769         /*
770          * Get fully qualified KLD name
771          */
772         filename = file_search(kldname, kld_ext_list);
773         if (filename == NULL) {
774                 snprintf(command_errbuf, sizeof(command_errbuf),
775                   "can't find '%s'", kldname);
776                 return (ENOENT);
777         }
778         /*
779          * Check if KLD already loaded
780          */
781         fp = file_findfile(filename, NULL);
782         if (fp) {
783                 snprintf(command_errbuf, sizeof(command_errbuf),
784                   "warning: KLD '%s' already loaded", filename);
785                 free(filename);
786                 return (0);
787         }
788
789         do {
790                 err = file_load(filename, loadaddr, &fp);
791                 if (err)
792                         break;
793                 fp->f_args = unargv(argc, argv);
794                 loadaddr_saved = loadaddr;
795                 loadaddr = fp->f_addr + fp->f_size;
796                 file_insert_tail(fp);   /* Add to the list of loaded files */
797                 if (file_load_dependencies(fp) != 0) {
798                         err = ENOENT;
799                         file_remove(fp);
800                         loadaddr = loadaddr_saved;
801                         fp = NULL;
802                         break;
803                 }
804         } while(0);
805         if (err == EFTYPE) {
806                 snprintf(command_errbuf, sizeof(command_errbuf),
807                   "don't know how to load module '%s'", filename);
808         }
809         if (err)
810                 file_discard(fp);
811         free(filename);
812         return (err);
813 }
814
815 /*
816  * Find a file matching (name) and (type).
817  * NULL may be passed as a wildcard to either.
818  */
819 struct preloaded_file *
820 file_findfile(const char *name, const char *type)
821 {
822         struct preloaded_file *fp;
823
824         for (fp = preloaded_files; fp != NULL; fp = fp->f_next) {
825                 if (((name == NULL) || !strcmp(name, fp->f_name)) &&
826                   ((type == NULL) || !strcmp(type, fp->f_type)))
827                         break;
828         }
829         return (fp);
830 }
831
832 /*
833  * Find a module matching (name) inside of given file.
834  * NULL may be passed as a wildcard.
835  */
836 struct kernel_module *
837 file_findmodule(struct preloaded_file *fp, char *modname,
838         struct mod_depend *verinfo)
839 {
840         struct kernel_module *mp, *best;
841         int bestver, mver;
842
843         if (fp == NULL) {
844                 for (fp = preloaded_files; fp; fp = fp->f_next) {
845                         mp = file_findmodule(fp, modname, verinfo);
846                         if (mp)
847                                 return (mp);
848                 }
849                 return (NULL);
850         }
851         best = NULL;
852         bestver = 0;
853         for (mp = fp->f_modules; mp; mp = mp->m_next) {
854                 if (strcmp(modname, mp->m_name) == 0) {
855                         if (verinfo == NULL)
856                                 return (mp);
857                         mver = mp->m_version;
858                         if (mver == verinfo->md_ver_preferred)
859                                 return (mp);
860                         if (mver >= verinfo->md_ver_minimum &&
861                           mver <= verinfo->md_ver_maximum &&
862                           mver > bestver) {
863                                 best = mp;
864                                 bestver = mver;
865                         }
866                 }
867         }
868         return (best);
869 }
870 /*
871  * Make a copy of (size) bytes of data from (p), and associate them as
872  * metadata of (type) to the module (mp).
873  */
874 void
875 file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p)
876 {
877         struct file_metadata    *md;
878
879         md = malloc(sizeof(struct file_metadata) - sizeof(md->md_data) + size);
880         if (md != NULL) {
881                 md->md_size = size;
882                 md->md_type = type;
883                 bcopy(p, md->md_data, size);
884                 md->md_next = fp->f_metadata;
885         }
886         fp->f_metadata = md;
887 }
888
889 /*
890  * Find a metadata object of (type) associated with the file (fp)
891  */
892 struct file_metadata *
893 file_findmetadata(struct preloaded_file *fp, int type)
894 {
895         struct file_metadata *md;
896
897         for (md = fp->f_metadata; md != NULL; md = md->md_next)
898                 if (md->md_type == type)
899                         break;
900         return(md);
901 }
902
903 /*
904  * Remove all metadata from the file.
905  */
906 void
907 file_removemetadata(struct preloaded_file *fp)
908 {
909         struct file_metadata *md, *next;
910
911         for (md = fp->f_metadata; md != NULL; md = next)
912         {
913                 next = md->md_next;
914                 free(md);
915         }
916         fp->f_metadata = NULL;
917 }
918
919 struct file_metadata *
920 metadata_next(struct file_metadata *md, int type)
921 {
922
923         if (md == NULL)
924                 return (NULL);
925         while((md = md->md_next) != NULL)
926                 if (md->md_type == type)
927                         break;
928         return (md);
929 }
930
931 static char *emptyextlist[] = { "", NULL };
932
933 /*
934  * Check if the given file is in place and return full path to it.
935  */
936 static char *
937 file_lookup(const char *path, const char *name, int namelen, char **extlist)
938 {
939         struct stat     st;
940         char    *result, *cp, **cpp;
941         int             pathlen, extlen, len;
942
943         pathlen = strlen(path);
944         extlen = 0;
945         if (extlist == NULL)
946                 extlist = emptyextlist;
947         for (cpp = extlist; *cpp; cpp++) {
948                 len = strlen(*cpp);
949                 if (len > extlen)
950                         extlen = len;
951         }
952         result = malloc(pathlen + namelen + extlen + 2);
953         if (result == NULL)
954                 return (NULL);
955         bcopy(path, result, pathlen);
956         if (pathlen > 0 && result[pathlen - 1] != '/')
957                 result[pathlen++] = '/';
958         cp = result + pathlen;
959         bcopy(name, cp, namelen);
960         cp += namelen;
961         for (cpp = extlist; *cpp; cpp++) {
962                 strcpy(cp, *cpp);
963                 if (stat(result, &st) == 0 && S_ISREG(st.st_mode))
964                         return result;
965         }
966         free(result);
967         return NULL;
968 }
969
970 /*
971  * Check if file name have any qualifiers
972  */
973 static int
974 file_havepath(const char *name)
975 {
976         const char              *cp;
977
978         archsw.arch_getdev(NULL, name, &cp);
979         return (cp != name || strchr(name, '/') != NULL);
980 }
981
982 /*
983  * Attempt to find the file (name) on the module searchpath.
984  * If (name) is qualified in any way, we simply check it and
985  * return it or NULL.  If it is not qualified, then we attempt
986  * to construct a path using entries in the environment variable
987  * module_path.
988  *
989  * The path we return a pointer to need never be freed, as we manage
990  * it internally.
991  */
992 static char *
993 file_search(const char *name, char **extlist)
994 {
995         struct moduledir        *mdp;
996         struct stat             sb;
997         char            *result;
998         int                     namelen;
999
1000         /* Don't look for nothing */
1001         if (name == NULL)
1002                 return(NULL);
1003
1004         if (*name == 0)
1005                 return(strdup(name));
1006
1007         if (file_havepath(name)) {
1008                 /* Qualified, so just see if it exists */
1009                 if (stat(name, &sb) == 0)
1010                         return(strdup(name));
1011                 return(NULL);
1012         }
1013         moduledir_rebuild();
1014         result = NULL;
1015         namelen = strlen(name);
1016         STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
1017                 result = file_lookup(mdp->d_path, name, namelen, extlist);
1018                 if (result)
1019                         break;
1020         }
1021         return(result);
1022 }
1023
1024 #define INT_ALIGN(base, ptr)    ptr = \
1025         (base) + roundup2((ptr) - (base), sizeof(int))
1026
1027 static char *
1028 mod_search_hints(struct moduledir *mdp, const char *modname,
1029         struct mod_depend *verinfo)
1030 {
1031         u_char  *cp, *recptr, *bufend, *best;
1032         char    *result;
1033         int             *intp, bestver, blen, clen, found, ival, modnamelen, reclen;
1034
1035         moduledir_readhints(mdp);
1036         modnamelen = strlen(modname);
1037         found = 0;
1038         result = NULL;
1039         bestver = 0;
1040         if (mdp->d_hints == NULL)
1041                 goto bad;
1042         recptr = mdp->d_hints;
1043         bufend = recptr + mdp->d_hintsz;
1044         clen = blen = 0;
1045         best = cp = NULL;
1046         while (recptr < bufend && !found) {
1047                 intp = (int*)recptr;
1048                 reclen = *intp++;
1049                 ival = *intp++;
1050                 cp = (u_char*)intp;
1051                 switch (ival) {
1052                 case MDT_VERSION:
1053                         clen = *cp++;
1054                         if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
1055                                 break;
1056                         cp += clen;
1057                         INT_ALIGN(mdp->d_hints, cp);
1058                         ival = *(int*)cp;
1059                         cp += sizeof(int);
1060                         clen = *cp++;
1061                         if (verinfo == NULL || ival == verinfo->md_ver_preferred) {
1062                                 found = 1;
1063                                 break;
1064                         }
1065                         if (ival >= verinfo->md_ver_minimum &&
1066                           ival <= verinfo->md_ver_maximum &&
1067                           ival > bestver) {
1068                                 bestver = ival;
1069                                 best = cp;
1070                                 blen = clen;
1071                         }
1072                         break;
1073                 default:
1074                         break;
1075                 }
1076                 recptr += reclen + sizeof(int);
1077         }
1078         /*
1079          * Finally check if KLD is in the place
1080          */
1081         if (found)
1082                 result = file_lookup(mdp->d_path, (const char *)cp, clen, NULL);
1083         else if (best)
1084                 result = file_lookup(mdp->d_path, (const char *)best, blen, NULL);
1085 bad:
1086         /*
1087          * If nothing found or hints is absent - fallback to the old way
1088          * by using "kldname[.ko]" as module name.
1089          */
1090         if (!found && !bestver && result == NULL)
1091                 result = file_lookup(mdp->d_path, modname, modnamelen, kld_ext_list);
1092         return result;
1093 }
1094
1095 static int
1096 getint(void **ptr)
1097 {
1098         int *p = *ptr;
1099         int rv;
1100
1101         p = (int *)roundup2((intptr_t)p, sizeof(int));
1102         rv = *p++;
1103         *ptr = p;
1104         return rv;
1105 }
1106
1107 static void
1108 getstr(void **ptr, char *val)
1109 {
1110         int *p = *ptr;
1111         char *c = (char *)p;
1112         int len = *(uint8_t *)c;
1113
1114         memcpy(val, c + 1, len);
1115         val[len] = 0;
1116         c += len + 1;
1117         *ptr = (void *)c;
1118 }
1119
1120 static int
1121 pnpval_as_int(const char *val, const char *pnpinfo)
1122 {
1123         int rv;
1124         char key[256];
1125         char *cp;
1126
1127         if (pnpinfo == NULL)
1128                 return -1;
1129
1130         cp = strchr(val, ';');
1131         key[0] = ' ';
1132         if (cp == NULL)
1133                 strlcpy(key + 1, val, sizeof(key) - 1);
1134         else {
1135                 memcpy(key + 1, val, cp - val);
1136                 key[cp - val + 1] = '\0';
1137         }
1138         strlcat(key, "=", sizeof(key));
1139         if (strncmp(key + 1, pnpinfo, strlen(key + 1)) == 0)
1140                 rv = strtol(pnpinfo + strlen(key + 1), NULL, 0);
1141         else {
1142                 cp = strstr(pnpinfo, key);
1143                 if (cp == NULL)
1144                         rv = -1;
1145                 else
1146                         rv = strtol(cp + strlen(key), NULL, 0);
1147         }
1148         return rv;
1149 }
1150
1151 static void
1152 quoted_strcpy(char *dst, const char *src)
1153 {
1154         char q = ' ';
1155
1156         if (*src == '\'' || *src == '"')
1157                 q = *src++;
1158         while (*src && *src != q)
1159                 *dst++ = *src++; // XXX backtick quoting
1160         *dst++ = '\0';
1161         // XXX overflow
1162 }
1163
1164 static char *
1165 pnpval_as_str(const char *val, const char *pnpinfo)
1166 {
1167         static char retval[256];
1168         char key[256];
1169         char *cp;
1170
1171         if (pnpinfo == NULL) {
1172                 *retval = '\0';
1173                 return retval;
1174         }
1175
1176         cp = strchr(val, ';');
1177         key[0] = ' ';
1178         if (cp == NULL)
1179                 strlcpy(key + 1, val, sizeof(key) - 1);
1180         else {
1181                 memcpy(key + 1, val, cp - val);
1182                 key[cp - val + 1] = '\0';
1183         }
1184         strlcat(key, "=", sizeof(key));
1185         if (strncmp(key + 1, pnpinfo, strlen(key + 1)) == 0)
1186                 quoted_strcpy(retval, pnpinfo + strlen(key + 1));
1187         else {
1188                 cp = strstr(pnpinfo, key);
1189                 if (cp == NULL)
1190                         strcpy(retval, "MISSING");
1191                 else
1192                         quoted_strcpy(retval, cp + strlen(key));
1193         }
1194         return retval;
1195 }
1196
1197 static char *
1198 devmatch_search_hints(struct moduledir *mdp, const char *bus, const char *dev, const char *pnpinfo)
1199 {
1200         char val1[256], val2[256];
1201         int ival, len, ents, i, notme, mask, bit, v, found;
1202         void *ptr, *walker, *hints_end;
1203         char *lastmod = NULL, *cp, *s;
1204
1205         moduledir_readhints(mdp);
1206         found = 0;
1207         if (mdp->d_hints == NULL)
1208                 goto bad;
1209         walker = mdp->d_hints;
1210         hints_end = walker + mdp->d_hintsz;
1211         while (walker < hints_end && !found) {
1212                 len = getint(&walker);
1213                 ival = getint(&walker);
1214                 ptr = walker;
1215                 switch (ival) {
1216                 case MDT_VERSION:
1217                         getstr(&ptr, val1);
1218                         ival = getint(&ptr);
1219                         getstr(&ptr, val2);
1220                         if (pnp_dump_flag || pnp_verbose_flag)
1221                                 printf("Version: if %s.%d kmod %s\n", val1, ival, val2);
1222                         break;
1223                 case MDT_MODULE:
1224                         getstr(&ptr, val1);
1225                         getstr(&ptr, val2);
1226                         if (lastmod)
1227                                 free(lastmod);
1228                         lastmod = strdup(val2);
1229                         if (pnp_dump_flag || pnp_verbose_flag)
1230                                 printf("module %s in %s\n", val1, val1);
1231                         break;
1232                 case MDT_PNP_INFO:
1233                         if (!pnp_dump_flag && !pnp_unbound_flag && lastmod && strcmp(lastmod, "kernel") == 0)
1234                                 break;
1235                         getstr(&ptr, val1);
1236                         getstr(&ptr, val2);
1237                         ents = getint(&ptr);
1238                         if (pnp_dump_flag || pnp_verbose_flag)
1239                                 printf("PNP info for bus %s format %s %d entries (%s)\n",
1240                                     val1, val2, ents, lastmod);
1241                         if (strcmp(val1, "usb") == 0) {
1242                                 if (pnp_verbose_flag)
1243                                         printf("Treating usb as uhub -- bug in source table still?\n");
1244                                 strcpy(val1, "uhub");
1245                         }
1246                         if (bus && strcmp(val1, bus) != 0) {
1247                                 if (pnp_verbose_flag)
1248                                         printf("Skipped because table for bus %s, looking for %s\n",
1249                                             val1, bus);
1250                                 break;
1251                         }
1252                         for (i = 0; i < ents; i++) {
1253                                 if (pnp_verbose_flag)
1254                                         printf("---------- Entry %d ----------\n", i);
1255                                 if (pnp_dump_flag)
1256                                         printf("   ");
1257                                 cp = val2;
1258                                 notme = 0;
1259                                 mask = -1;
1260                                 bit = -1;
1261                                 do {
1262                                         switch (*cp) {
1263                                                 /* All integer fields */
1264                                         case 'I':
1265                                         case 'J':
1266                                         case 'G':
1267                                         case 'L':
1268                                         case 'M':
1269                                                 ival = getint(&ptr);
1270                                                 if (pnp_dump_flag) {
1271                                                         printf("%#x:", ival);
1272                                                         break;
1273                                                 }
1274                                                 if (bit >= 0 && ((1 << bit) & mask) == 0)
1275                                                         break;
1276                                                 v = pnpval_as_int(cp + 2, pnpinfo);
1277                                                 if (pnp_verbose_flag)
1278                                                         printf("Matching %s (%c) table=%#x tomatch=%#x\n",
1279                                                             cp + 2, *cp, v, ival);
1280                                                 switch (*cp) {
1281                                                 case 'J':
1282                                                         if (ival == -1)
1283                                                                 break;
1284                                                         /*FALLTHROUGH*/
1285                                                 case 'I':
1286                                                         if (v != ival)
1287                                                                 notme++;
1288                                                         break;
1289                                                 case 'G':
1290                                                         if (v < ival)
1291                                                                 notme++;
1292                                                         break;
1293                                                 case 'L':
1294                                                         if (v > ival)
1295                                                                 notme++;
1296                                                         break;
1297                                                 case 'M':
1298                                                         mask = ival;
1299                                                         break;
1300                                                 }
1301                                                 break;
1302                                                 /* String fields */
1303                                         case 'D':
1304                                         case 'Z':
1305                                                 getstr(&ptr, val1);
1306                                                 if (pnp_dump_flag) {
1307                                                         printf("'%s':", val1);
1308                                                         break;
1309                                                 }
1310                                                 if (*cp == 'D')
1311                                                         break;
1312                                                 s = pnpval_as_str(cp + 2, pnpinfo);
1313                                                 if (strcmp(s, val1) != 0)
1314                                                         notme++;
1315                                                 break;
1316                                                 /* Key override fields, required to be last in the string */
1317                                         case 'T':
1318                                                 /*
1319                                                  * This is imperfect and only does one key and will be redone
1320                                                  * to be more general for multiple keys. Currently, nothing
1321                                                  * does that.
1322                                                  */
1323                                                 if (pnp_dump_flag)                              /* No per-row data stored */
1324                                                         break;
1325                                                 if (cp[strlen(cp) - 1] == ';')          /* Skip required ; at end */
1326                                                         cp[strlen(cp) - 1] = '\0';      /* in case it's not there */
1327                                                 if ((s = strstr(pnpinfo, cp + 2)) == NULL)
1328                                                         notme++;
1329                                                 else if (s > pnpinfo && s[-1] != ' ')
1330                                                         notme++;
1331                                                 break;
1332                                         default:
1333                                                 printf("Unknown field type %c\n:", *cp);
1334                                                 break;
1335                                         }
1336                                         bit++;
1337                                         cp = strchr(cp, ';');
1338                                         if (cp)
1339                                                 cp++;
1340                                 } while (cp && *cp);
1341                                 if (pnp_dump_flag)
1342                                         printf("\n");
1343                                 else if (!notme) {
1344                                         if (!pnp_unbound_flag) {
1345                                                 if (pnp_verbose_flag)
1346                                                         printf("Matches --- %s ---\n", lastmod);
1347                                         }
1348                                         found++;
1349                                 }
1350                         }
1351                         break;
1352                 default:
1353                         break;
1354                 }
1355                 walker = (void *)(len - sizeof(int) + (intptr_t)walker);
1356         }
1357         if (pnp_unbound_flag && found == 0 && *pnpinfo) {
1358                 if (pnp_verbose_flag)
1359                         printf("------------------------- ");
1360                 printf("%s on %s pnpinfo %s", *dev ? dev : "unattached", bus, pnpinfo);
1361                 if (pnp_verbose_flag)
1362                         printf(" -------------------------");
1363                 printf("\n");
1364         }
1365         if (found != 0)
1366                 return (lastmod);
1367         free(lastmod);
1368
1369 bad:
1370         return (NULL);
1371 }
1372
1373 /*
1374  * Attempt to locate the file containing the module (name)
1375  */
1376 static char *
1377 mod_searchmodule(char *name, struct mod_depend *verinfo)
1378 {
1379         struct  moduledir *mdp;
1380         char    *result;
1381
1382         moduledir_rebuild();
1383         /*
1384          * Now we ready to lookup module in the given directories
1385          */
1386         result = NULL;
1387         STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
1388                 result = mod_search_hints(mdp, name, verinfo);
1389                 if (result)
1390                         break;
1391         }
1392
1393         return(result);
1394 }
1395
1396 static char *
1397 mod_searchmodule_pnpinfo(const char *bus, const char *pnpinfo)
1398 {
1399         struct  moduledir *mdp;
1400         char    *result;
1401
1402         moduledir_rebuild();
1403         /*
1404          * Now we ready to lookup module in the given directories
1405          */
1406         result = NULL;
1407         STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
1408                 result = devmatch_search_hints(mdp, bus, NULL, pnpinfo);
1409                 if (result)
1410                         break;
1411         }
1412
1413         return(result);
1414 }
1415
1416 int
1417 file_addmodule(struct preloaded_file *fp, char *modname, int version,
1418         struct kernel_module **newmp)
1419 {
1420         struct kernel_module *mp;
1421         struct mod_depend mdepend;
1422
1423         bzero(&mdepend, sizeof(mdepend));
1424         mdepend.md_ver_preferred = version;
1425         mp = file_findmodule(fp, modname, &mdepend);
1426         if (mp)
1427                 return (EEXIST);
1428         mp = calloc(1, sizeof(struct kernel_module));
1429         if (mp == NULL)
1430                 return (ENOMEM);
1431         mp->m_name = strdup(modname);
1432         if (mp->m_name == NULL) {
1433                 free(mp);
1434                 return (ENOMEM);
1435         }
1436         mp->m_version = version;
1437         mp->m_fp = fp;
1438         mp->m_next = fp->f_modules;
1439         fp->f_modules = mp;
1440         if (newmp)
1441                 *newmp = mp;
1442         return (0);
1443 }
1444
1445 /*
1446  * Throw a file away
1447  */
1448 void
1449 file_discard(struct preloaded_file *fp)
1450 {
1451         struct file_metadata    *md, *md1;
1452         struct kernel_module    *mp, *mp1;
1453         if (fp == NULL)
1454                 return;
1455         md = fp->f_metadata;
1456         while (md) {
1457                 md1 = md;
1458                 md = md->md_next;
1459                 free(md1);
1460         }
1461         mp = fp->f_modules;
1462         while (mp) {
1463                 free(mp->m_name);
1464                 mp1 = mp;
1465                 mp = mp->m_next;
1466                 free(mp1);
1467         }
1468         free(fp->f_name);
1469         free(fp->f_type);
1470         free(fp->f_args);
1471         free(fp);
1472 }
1473
1474 /*
1475  * Allocate a new file; must be used instead of malloc()
1476  * to ensure safe initialisation.
1477  */
1478 struct preloaded_file *
1479 file_alloc(void)
1480 {
1481
1482         return (calloc(1, sizeof(struct preloaded_file)));
1483 }
1484
1485 /*
1486  * Add a module to the chain
1487  */
1488 static void
1489 file_insert_tail(struct preloaded_file *fp)
1490 {
1491         struct preloaded_file   *cm;
1492     
1493         /* Append to list of loaded file */
1494         fp->f_next = NULL;
1495         if (preloaded_files == NULL) {
1496                 preloaded_files = fp;
1497         } else {
1498                 for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next)
1499                         ;
1500                 cm->f_next = fp;
1501         }
1502 }
1503
1504 /*
1505  * Remove module from the chain
1506  */
1507 static void
1508 file_remove(struct preloaded_file *fp)
1509 {
1510         struct preloaded_file   *cm;
1511
1512         if (preloaded_files == NULL)
1513                 return;
1514
1515         if (preloaded_files == fp) {
1516                 preloaded_files = fp->f_next;
1517                 return;
1518         }
1519         for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next) {
1520                 if (cm->f_next == fp) {
1521                         cm->f_next = fp->f_next;
1522                         return;
1523                 }
1524         }
1525 }
1526
1527 static char *
1528 moduledir_fullpath(struct moduledir *mdp, const char *fname)
1529 {
1530         char *cp;
1531
1532         cp = malloc(strlen(mdp->d_path) + strlen(fname) + 2);
1533         if (cp == NULL)
1534                 return NULL;
1535         strcpy(cp, mdp->d_path);
1536         strcat(cp, "/");
1537         strcat(cp, fname);
1538         return (cp);
1539 }
1540
1541 /*
1542  * Read linker.hints file into memory performing some sanity checks.
1543  */
1544 static void
1545 moduledir_readhints(struct moduledir *mdp)
1546 {
1547         struct stat     st;
1548         char    *path;
1549         int             fd, size, version;
1550
1551         if (mdp->d_hints != NULL || (mdp->d_flags & MDIR_NOHINTS))
1552                 return;
1553         path = moduledir_fullpath(mdp, "linker.hints");
1554         if (stat(path, &st) != 0 ||
1555           st.st_size < (ssize_t)(sizeof(version) + sizeof(int)) ||
1556           st.st_size > LINKER_HINTS_MAX || (fd = open(path, O_RDONLY)) < 0) {
1557                 free(path);
1558                 mdp->d_flags |= MDIR_NOHINTS;
1559                 return;
1560         }
1561         free(path);
1562         size = read(fd, &version, sizeof(version));
1563         if (size != sizeof(version) || version != LINKER_HINTS_VERSION)
1564                 goto bad;
1565         size = st.st_size - size;
1566         mdp->d_hints = malloc(size);
1567         if (mdp->d_hints == NULL)
1568                 goto bad;
1569         if (read(fd, mdp->d_hints, size) != size)
1570                 goto bad;
1571         mdp->d_hintsz = size;
1572         close(fd);
1573         return;
1574 bad:
1575         close(fd);
1576         free(mdp->d_hints);
1577         mdp->d_hints = NULL;
1578         mdp->d_flags |= MDIR_NOHINTS;
1579         return;
1580 }
1581
1582 /*
1583  * Extract directories from the ';' separated list, remove duplicates.
1584  */
1585 static void
1586 moduledir_rebuild(void)
1587 {
1588         struct  moduledir *mdp, *mtmp;
1589         const char      *path, *cp, *ep;
1590         size_t  cplen;
1591
1592         path = getenv("module_path");
1593         if (path == NULL)
1594                 path = default_searchpath;
1595         /*
1596          * Rebuild list of module directories if it changed
1597          */
1598         STAILQ_FOREACH(mdp, &moduledir_list, d_link)
1599                 mdp->d_flags |= MDIR_REMOVED;
1600
1601         for (ep = path; *ep != 0;  ep++) {
1602                 cp = ep;
1603                 for (; *ep != 0 && *ep != ';'; ep++)
1604                         ;
1605                 /*
1606                  * Ignore trailing slashes
1607                  */
1608                 for (cplen = ep - cp; cplen > 1 && cp[cplen - 1] == '/'; cplen--)
1609                         ;
1610                 STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
1611                         if (strlen(mdp->d_path) != cplen ||     bcmp(cp, mdp->d_path, cplen) != 0)
1612                                 continue;
1613                         mdp->d_flags &= ~MDIR_REMOVED;
1614                         break;
1615                 }
1616                 if (mdp == NULL) {
1617                         mdp = malloc(sizeof(*mdp) + cplen + 1);
1618                         if (mdp == NULL)
1619                                 return;
1620                         mdp->d_path = (char*)(mdp + 1);
1621                         bcopy(cp, mdp->d_path, cplen);
1622                         mdp->d_path[cplen] = 0;
1623                         mdp->d_hints = NULL;
1624                         mdp->d_flags = 0;
1625                         STAILQ_INSERT_TAIL(&moduledir_list, mdp, d_link);
1626                 }
1627                 if (*ep == 0)
1628                         break;
1629         }
1630         /*
1631          * Delete unused directories if any
1632          */
1633         mdp = STAILQ_FIRST(&moduledir_list);
1634         while (mdp) {
1635                 if ((mdp->d_flags & MDIR_REMOVED) == 0) {
1636                         mdp = STAILQ_NEXT(mdp, d_link);
1637                 } else {
1638                         free(mdp->d_hints);
1639                         mtmp = mdp;
1640                         mdp = STAILQ_NEXT(mdp, d_link);
1641                         STAILQ_REMOVE(&moduledir_list, mtmp, moduledir, d_link);
1642                         free(mtmp);
1643                 }
1644         }
1645         return;
1646 }