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