]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - stand/common/module.c
Optionally bind ktls threads to NUMA domains
[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 #ifdef LOADER_VERIEXEC_VECTX
621 #define VECTX_HANDLE(fd) vctx
622 #else
623 #define VECTX_HANDLE(fd) fd
624 #endif
625
626
627 /*
628  * We've been asked to load (fname) as (type), so just suck it in,
629  * no arguments or anything.
630  */
631 struct preloaded_file *
632 file_loadraw(const char *fname, char *type, int insert)
633 {
634         struct preloaded_file   *fp;
635         char                    *name;
636         int                             fd, got;
637         vm_offset_t                     laddr;
638 #ifdef LOADER_VERIEXEC_VECTX
639         struct vectx            *vctx;
640         int                     verror;
641 #endif
642
643         /* We can't load first */
644         if ((file_findfile(NULL, NULL)) == NULL) {
645                 command_errmsg = "can't load file before kernel";
646                 return(NULL);
647         }
648
649         /* locate the file on the load path */
650         name = file_search(fname, NULL);
651         if (name == NULL) {
652                 snprintf(command_errbuf, sizeof(command_errbuf),
653                   "can't find '%s'", fname);
654                 return(NULL);
655         }
656
657         if ((fd = open(name, O_RDONLY)) < 0) {
658                 snprintf(command_errbuf, sizeof(command_errbuf),
659                   "can't open '%s': %s", name, strerror(errno));
660                 free(name);
661                 return(NULL);
662         }
663
664 #ifdef LOADER_VERIEXEC_VECTX
665         vctx = vectx_open(fd, name, 0L, NULL, &verror, __func__);
666         if (verror) {
667                 sprintf(command_errbuf, "can't verify '%s': %s",
668                     name, ve_error_get());
669                 free(name);
670                 free(vctx);
671                 close(fd);
672                 return(NULL);
673         }
674 #else
675 #ifdef LOADER_VERIEXEC
676         if (verify_file(fd, name, 0, VE_MUST, __func__) < 0) {
677                 sprintf(command_errbuf, "can't verify '%s': %s",
678                     name, ve_error_get());
679                 free(name);
680                 close(fd);
681                 return(NULL);
682         }
683 #endif
684 #endif
685
686         if (archsw.arch_loadaddr != NULL)
687                 loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr);
688
689         printf("%s ", name);
690
691         laddr = loadaddr;
692         for (;;) {
693                 /* read in 4k chunks; size is not really important */
694                 got = archsw.arch_readin(VECTX_HANDLE(fd), laddr, 4096);
695                 if (got == 0)                           /* end of file */
696                         break;
697                 if (got < 0) {                          /* error */
698                         snprintf(command_errbuf, sizeof(command_errbuf),
699                           "error reading '%s': %s", name, strerror(errno));
700                         free(name);
701                         close(fd);
702 #ifdef LOADER_VERIEXEC_VECTX
703                         free(vctx);
704 #endif
705                         return(NULL);
706                 }
707                 laddr += got;
708         }
709
710         printf("size=%#jx\n", (uintmax_t)(laddr - loadaddr));
711 #ifdef LOADER_VERIEXEC_VECTX
712         verror = vectx_close(vctx, VE_MUST, __func__);
713         if (verror) {
714                 free(name);
715                 close(fd);
716                 free(vctx);
717                 return(NULL);
718         }
719 #endif
720
721         /* Looks OK so far; create & populate control structure */
722         fp = file_alloc();
723         if (fp == NULL) {
724                 snprintf(command_errbuf, sizeof (command_errbuf),
725                     "no memory to load %s", name);
726                 free(name);
727                 close(fd);
728                 return (NULL);
729         }
730         fp->f_name = name;
731         fp->f_type = strdup(type);
732         fp->f_args = NULL;
733         fp->f_metadata = NULL;
734         fp->f_loader = -1;
735         fp->f_addr = loadaddr;
736         fp->f_size = laddr - loadaddr;
737
738         if (fp->f_type == NULL) {
739                 snprintf(command_errbuf, sizeof (command_errbuf),
740                     "no memory to load %s", name);
741                 free(name);
742                 close(fd);
743                 return (NULL);
744         }
745         /* recognise space consumption */
746         loadaddr = laddr;
747
748         /* Add to the list of loaded files */
749         if (insert != 0)
750                 file_insert_tail(fp);
751         close(fd);
752         return(fp);
753 }
754
755 /*
756  * Load the module (name), pass it (argc),(argv), add container file
757  * to the list of loaded files.
758  * If module is already loaded just assign new argc/argv.
759  */
760 int
761 mod_load(char *modname, struct mod_depend *verinfo, int argc, char *argv[])
762 {
763         struct kernel_module    *mp;
764         int                             err;
765         char                    *filename;
766
767         if (file_havepath(modname)) {
768                 printf("Warning: mod_load() called instead of mod_loadkld() for module '%s'\n", modname);
769                 return (mod_loadkld(modname, argc, argv));
770         }
771         /* see if module is already loaded */
772         mp = file_findmodule(NULL, modname, verinfo);
773         if (mp) {
774 #ifdef moduleargs
775                 free(mp->m_args);
776                 mp->m_args = unargv(argc, argv);
777 #endif
778                 snprintf(command_errbuf, sizeof(command_errbuf),
779                   "warning: module '%s' already loaded", mp->m_name);
780                 return (0);
781         }
782         /* locate file with the module on the search path */
783         filename = mod_searchmodule(modname, verinfo);
784         if (filename == NULL) {
785                 snprintf(command_errbuf, sizeof(command_errbuf),
786                   "can't find '%s'", modname);
787                 return (ENOENT);
788         }
789         err = mod_loadkld(filename, argc, argv);
790         free(filename);
791         return (err);
792 }
793
794 /*
795  * Load specified KLD. If path is omitted, then try to locate it via
796  * search path.
797  */
798 int
799 mod_loadkld(const char *kldname, int argc, char *argv[])
800 {
801         struct preloaded_file   *fp;
802         int                     err;
803         char                    *filename;
804         vm_offset_t             loadaddr_saved;
805
806         /*
807          * Get fully qualified KLD name
808          */
809         filename = file_search(kldname, kld_ext_list);
810         if (filename == NULL) {
811                 snprintf(command_errbuf, sizeof(command_errbuf),
812                   "can't find '%s'", kldname);
813                 return (ENOENT);
814         }
815         /*
816          * Check if KLD already loaded
817          */
818         fp = file_findfile(filename, NULL);
819         if (fp) {
820                 snprintf(command_errbuf, sizeof(command_errbuf),
821                   "warning: KLD '%s' already loaded", filename);
822                 free(filename);
823                 return (0);
824         }
825
826         do {
827                 err = file_load(filename, loadaddr, &fp);
828                 if (err)
829                         break;
830                 fp->f_args = unargv(argc, argv);
831                 loadaddr_saved = loadaddr;
832                 loadaddr = fp->f_addr + fp->f_size;
833                 file_insert_tail(fp);   /* Add to the list of loaded files */
834                 if (file_load_dependencies(fp) != 0) {
835                         err = ENOENT;
836                         file_remove(fp);
837                         loadaddr = loadaddr_saved;
838                         fp = NULL;
839                         break;
840                 }
841         } while(0);
842         if (err == EFTYPE) {
843                 snprintf(command_errbuf, sizeof(command_errbuf),
844                   "don't know how to load module '%s'", filename);
845         }
846         if (err)
847                 file_discard(fp);
848         free(filename);
849         return (err);
850 }
851
852 /*
853  * Find a file matching (name) and (type).
854  * NULL may be passed as a wildcard to either.
855  */
856 struct preloaded_file *
857 file_findfile(const char *name, const char *type)
858 {
859         struct preloaded_file *fp;
860
861         for (fp = preloaded_files; fp != NULL; fp = fp->f_next) {
862                 if (((name == NULL) || !strcmp(name, fp->f_name)) &&
863                   ((type == NULL) || !strcmp(type, fp->f_type)))
864                         break;
865         }
866         return (fp);
867 }
868
869 /*
870  * Find a module matching (name) inside of given file.
871  * NULL may be passed as a wildcard.
872  */
873 struct kernel_module *
874 file_findmodule(struct preloaded_file *fp, char *modname,
875         struct mod_depend *verinfo)
876 {
877         struct kernel_module *mp, *best;
878         int bestver, mver;
879
880         if (fp == NULL) {
881                 for (fp = preloaded_files; fp; fp = fp->f_next) {
882                         mp = file_findmodule(fp, modname, verinfo);
883                         if (mp)
884                                 return (mp);
885                 }
886                 return (NULL);
887         }
888         best = NULL;
889         bestver = 0;
890         for (mp = fp->f_modules; mp; mp = mp->m_next) {
891                 if (strcmp(modname, mp->m_name) == 0) {
892                         if (verinfo == NULL)
893                                 return (mp);
894                         mver = mp->m_version;
895                         if (mver == verinfo->md_ver_preferred)
896                                 return (mp);
897                         if (mver >= verinfo->md_ver_minimum &&
898                           mver <= verinfo->md_ver_maximum &&
899                           mver > bestver) {
900                                 best = mp;
901                                 bestver = mver;
902                         }
903                 }
904         }
905         return (best);
906 }
907 /*
908  * Make a copy of (size) bytes of data from (p), and associate them as
909  * metadata of (type) to the module (mp).
910  */
911 void
912 file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p)
913 {
914         struct file_metadata    *md;
915
916         md = malloc(sizeof(struct file_metadata) - sizeof(md->md_data) + size);
917         if (md != NULL) {
918                 md->md_size = size;
919                 md->md_type = type;
920                 bcopy(p, md->md_data, size);
921                 md->md_next = fp->f_metadata;
922         }
923         fp->f_metadata = md;
924 }
925
926 /*
927  * Find a metadata object of (type) associated with the file (fp)
928  */
929 struct file_metadata *
930 file_findmetadata(struct preloaded_file *fp, int type)
931 {
932         struct file_metadata *md;
933
934         for (md = fp->f_metadata; md != NULL; md = md->md_next)
935                 if (md->md_type == type)
936                         break;
937         return(md);
938 }
939
940 /*
941  * Remove all metadata from the file.
942  */
943 void
944 file_removemetadata(struct preloaded_file *fp)
945 {
946         struct file_metadata *md, *next;
947
948         for (md = fp->f_metadata; md != NULL; md = next)
949         {
950                 next = md->md_next;
951                 free(md);
952         }
953         fp->f_metadata = NULL;
954 }
955
956 struct file_metadata *
957 metadata_next(struct file_metadata *md, int type)
958 {
959
960         if (md == NULL)
961                 return (NULL);
962         while((md = md->md_next) != NULL)
963                 if (md->md_type == type)
964                         break;
965         return (md);
966 }
967
968 static char *emptyextlist[] = { "", NULL };
969
970 /*
971  * Check if the given file is in place and return full path to it.
972  */
973 static char *
974 file_lookup(const char *path, const char *name, int namelen, char **extlist)
975 {
976         struct stat     st;
977         char    *result, *cp, **cpp;
978         int             pathlen, extlen, len;
979
980         pathlen = strlen(path);
981         extlen = 0;
982         if (extlist == NULL)
983                 extlist = emptyextlist;
984         for (cpp = extlist; *cpp; cpp++) {
985                 len = strlen(*cpp);
986                 if (len > extlen)
987                         extlen = len;
988         }
989         result = malloc(pathlen + namelen + extlen + 2);
990         if (result == NULL)
991                 return (NULL);
992         bcopy(path, result, pathlen);
993         if (pathlen > 0 && result[pathlen - 1] != '/')
994                 result[pathlen++] = '/';
995         cp = result + pathlen;
996         bcopy(name, cp, namelen);
997         cp += namelen;
998         for (cpp = extlist; *cpp; cpp++) {
999                 strcpy(cp, *cpp);
1000                 if (stat(result, &st) == 0 && S_ISREG(st.st_mode))
1001                         return result;
1002         }
1003         free(result);
1004         return NULL;
1005 }
1006
1007 /*
1008  * Check if file name have any qualifiers
1009  */
1010 static int
1011 file_havepath(const char *name)
1012 {
1013         const char              *cp;
1014
1015         archsw.arch_getdev(NULL, name, &cp);
1016         return (cp != name || strchr(name, '/') != NULL);
1017 }
1018
1019 /*
1020  * Attempt to find the file (name) on the module searchpath.
1021  * If (name) is qualified in any way, we simply check it and
1022  * return it or NULL.  If it is not qualified, then we attempt
1023  * to construct a path using entries in the environment variable
1024  * module_path.
1025  *
1026  * The path we return a pointer to need never be freed, as we manage
1027  * it internally.
1028  */
1029 static char *
1030 file_search(const char *name, char **extlist)
1031 {
1032         struct moduledir        *mdp;
1033         struct stat             sb;
1034         char            *result;
1035         int                     namelen;
1036
1037         /* Don't look for nothing */
1038         if (name == NULL)
1039                 return(NULL);
1040
1041         if (*name == 0)
1042                 return(strdup(name));
1043
1044         if (file_havepath(name)) {
1045                 /* Qualified, so just see if it exists */
1046                 if (stat(name, &sb) == 0)
1047                         return(strdup(name));
1048                 return(NULL);
1049         }
1050         moduledir_rebuild();
1051         result = NULL;
1052         namelen = strlen(name);
1053         STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
1054                 result = file_lookup(mdp->d_path, name, namelen, extlist);
1055                 if (result)
1056                         break;
1057         }
1058         return(result);
1059 }
1060
1061 #define INT_ALIGN(base, ptr)    ptr = \
1062         (base) + roundup2((ptr) - (base), sizeof(int))
1063
1064 static char *
1065 mod_search_hints(struct moduledir *mdp, const char *modname,
1066         struct mod_depend *verinfo)
1067 {
1068         u_char  *cp, *recptr, *bufend, *best;
1069         char    *result;
1070         int             *intp, bestver, blen, clen, found, ival, modnamelen, reclen;
1071
1072         moduledir_readhints(mdp);
1073         modnamelen = strlen(modname);
1074         found = 0;
1075         result = NULL;
1076         bestver = 0;
1077         if (mdp->d_hints == NULL)
1078                 goto bad;
1079         recptr = mdp->d_hints;
1080         bufend = recptr + mdp->d_hintsz;
1081         clen = blen = 0;
1082         best = cp = NULL;
1083         while (recptr < bufend && !found) {
1084                 intp = (int*)recptr;
1085                 reclen = *intp++;
1086                 ival = *intp++;
1087                 cp = (u_char*)intp;
1088                 switch (ival) {
1089                 case MDT_VERSION:
1090                         clen = *cp++;
1091                         if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
1092                                 break;
1093                         cp += clen;
1094                         INT_ALIGN(mdp->d_hints, cp);
1095                         ival = *(int*)cp;
1096                         cp += sizeof(int);
1097                         clen = *cp++;
1098                         if (verinfo == NULL || ival == verinfo->md_ver_preferred) {
1099                                 found = 1;
1100                                 break;
1101                         }
1102                         if (ival >= verinfo->md_ver_minimum &&
1103                           ival <= verinfo->md_ver_maximum &&
1104                           ival > bestver) {
1105                                 bestver = ival;
1106                                 best = cp;
1107                                 blen = clen;
1108                         }
1109                         break;
1110                 default:
1111                         break;
1112                 }
1113                 recptr += reclen + sizeof(int);
1114         }
1115         /*
1116          * Finally check if KLD is in the place
1117          */
1118         if (found)
1119                 result = file_lookup(mdp->d_path, (const char *)cp, clen, NULL);
1120         else if (best)
1121                 result = file_lookup(mdp->d_path, (const char *)best, blen, NULL);
1122 bad:
1123         /*
1124          * If nothing found or hints is absent - fallback to the old way
1125          * by using "kldname[.ko]" as module name.
1126          */
1127         if (!found && !bestver && result == NULL)
1128                 result = file_lookup(mdp->d_path, modname, modnamelen, kld_ext_list);
1129         return result;
1130 }
1131
1132 static int
1133 getint(void **ptr)
1134 {
1135         int *p = *ptr;
1136         int rv;
1137
1138         p = (int *)roundup2((intptr_t)p, sizeof(int));
1139         rv = *p++;
1140         *ptr = p;
1141         return rv;
1142 }
1143
1144 static void
1145 getstr(void **ptr, char *val)
1146 {
1147         int *p = *ptr;
1148         char *c = (char *)p;
1149         int len = *(uint8_t *)c;
1150
1151         memcpy(val, c + 1, len);
1152         val[len] = 0;
1153         c += len + 1;
1154         *ptr = (void *)c;
1155 }
1156
1157 static int
1158 pnpval_as_int(const char *val, const char *pnpinfo)
1159 {
1160         int rv;
1161         char key[256];
1162         char *cp;
1163
1164         if (pnpinfo == NULL)
1165                 return -1;
1166
1167         cp = strchr(val, ';');
1168         key[0] = ' ';
1169         if (cp == NULL)
1170                 strlcpy(key + 1, val, sizeof(key) - 1);
1171         else {
1172                 memcpy(key + 1, val, cp - val);
1173                 key[cp - val + 1] = '\0';
1174         }
1175         strlcat(key, "=", sizeof(key));
1176         if (strncmp(key + 1, pnpinfo, strlen(key + 1)) == 0)
1177                 rv = strtol(pnpinfo + strlen(key + 1), NULL, 0);
1178         else {
1179                 cp = strstr(pnpinfo, key);
1180                 if (cp == NULL)
1181                         rv = -1;
1182                 else
1183                         rv = strtol(cp + strlen(key), NULL, 0);
1184         }
1185         return rv;
1186 }
1187
1188 static void
1189 quoted_strcpy(char *dst, const char *src)
1190 {
1191         char q = ' ';
1192
1193         if (*src == '\'' || *src == '"')
1194                 q = *src++;
1195         while (*src && *src != q)
1196                 *dst++ = *src++; // XXX backtick quoting
1197         *dst++ = '\0';
1198         // XXX overflow
1199 }
1200
1201 static char *
1202 pnpval_as_str(const char *val, const char *pnpinfo)
1203 {
1204         static char retval[256];
1205         char key[256];
1206         char *cp;
1207
1208         if (pnpinfo == NULL) {
1209                 *retval = '\0';
1210                 return retval;
1211         }
1212
1213         cp = strchr(val, ';');
1214         key[0] = ' ';
1215         if (cp == NULL)
1216                 strlcpy(key + 1, val, sizeof(key) - 1);
1217         else {
1218                 memcpy(key + 1, val, cp - val);
1219                 key[cp - val + 1] = '\0';
1220         }
1221         strlcat(key, "=", sizeof(key));
1222         if (strncmp(key + 1, pnpinfo, strlen(key + 1)) == 0)
1223                 quoted_strcpy(retval, pnpinfo + strlen(key + 1));
1224         else {
1225                 cp = strstr(pnpinfo, key);
1226                 if (cp == NULL)
1227                         strcpy(retval, "MISSING");
1228                 else
1229                         quoted_strcpy(retval, cp + strlen(key));
1230         }
1231         return retval;
1232 }
1233
1234 static char *
1235 devmatch_search_hints(struct moduledir *mdp, const char *bus, const char *dev, const char *pnpinfo)
1236 {
1237         char val1[256], val2[256];
1238         int ival, len, ents, i, notme, mask, bit, v, found;
1239         void *ptr, *walker, *hints_end;
1240         char *lastmod = NULL, *cp, *s;
1241
1242         moduledir_readhints(mdp);
1243         found = 0;
1244         if (mdp->d_hints == NULL)
1245                 goto bad;
1246         walker = mdp->d_hints;
1247         hints_end = walker + mdp->d_hintsz;
1248         while (walker < hints_end && !found) {
1249                 len = getint(&walker);
1250                 ival = getint(&walker);
1251                 ptr = walker;
1252                 switch (ival) {
1253                 case MDT_VERSION:
1254                         getstr(&ptr, val1);
1255                         ival = getint(&ptr);
1256                         getstr(&ptr, val2);
1257                         if (pnp_dump_flag || pnp_verbose_flag)
1258                                 printf("Version: if %s.%d kmod %s\n", val1, ival, val2);
1259                         break;
1260                 case MDT_MODULE:
1261                         getstr(&ptr, val1);
1262                         getstr(&ptr, val2);
1263                         if (lastmod)
1264                                 free(lastmod);
1265                         lastmod = strdup(val2);
1266                         if (pnp_dump_flag || pnp_verbose_flag)
1267                                 printf("module %s in %s\n", val1, val1);
1268                         break;
1269                 case MDT_PNP_INFO:
1270                         if (!pnp_dump_flag && !pnp_unbound_flag && lastmod && strcmp(lastmod, "kernel") == 0)
1271                                 break;
1272                         getstr(&ptr, val1);
1273                         getstr(&ptr, val2);
1274                         ents = getint(&ptr);
1275                         if (pnp_dump_flag || pnp_verbose_flag)
1276                                 printf("PNP info for bus %s format %s %d entries (%s)\n",
1277                                     val1, val2, ents, lastmod);
1278                         if (strcmp(val1, "usb") == 0) {
1279                                 if (pnp_verbose_flag)
1280                                         printf("Treating usb as uhub -- bug in source table still?\n");
1281                                 strcpy(val1, "uhub");
1282                         }
1283                         if (bus && strcmp(val1, bus) != 0) {
1284                                 if (pnp_verbose_flag)
1285                                         printf("Skipped because table for bus %s, looking for %s\n",
1286                                             val1, bus);
1287                                 break;
1288                         }
1289                         for (i = 0; i < ents; i++) {
1290                                 if (pnp_verbose_flag)
1291                                         printf("---------- Entry %d ----------\n", i);
1292                                 if (pnp_dump_flag)
1293                                         printf("   ");
1294                                 cp = val2;
1295                                 notme = 0;
1296                                 mask = -1;
1297                                 bit = -1;
1298                                 do {
1299                                         switch (*cp) {
1300                                                 /* All integer fields */
1301                                         case 'I':
1302                                         case 'J':
1303                                         case 'G':
1304                                         case 'L':
1305                                         case 'M':
1306                                                 ival = getint(&ptr);
1307                                                 if (pnp_dump_flag) {
1308                                                         printf("%#x:", ival);
1309                                                         break;
1310                                                 }
1311                                                 if (bit >= 0 && ((1 << bit) & mask) == 0)
1312                                                         break;
1313                                                 v = pnpval_as_int(cp + 2, pnpinfo);
1314                                                 if (pnp_verbose_flag)
1315                                                         printf("Matching %s (%c) table=%#x tomatch=%#x\n",
1316                                                             cp + 2, *cp, v, ival);
1317                                                 switch (*cp) {
1318                                                 case 'J':
1319                                                         if (ival == -1)
1320                                                                 break;
1321                                                         /*FALLTHROUGH*/
1322                                                 case 'I':
1323                                                         if (v != ival)
1324                                                                 notme++;
1325                                                         break;
1326                                                 case 'G':
1327                                                         if (v < ival)
1328                                                                 notme++;
1329                                                         break;
1330                                                 case 'L':
1331                                                         if (v > ival)
1332                                                                 notme++;
1333                                                         break;
1334                                                 case 'M':
1335                                                         mask = ival;
1336                                                         break;
1337                                                 }
1338                                                 break;
1339                                                 /* String fields */
1340                                         case 'D':
1341                                         case 'Z':
1342                                                 getstr(&ptr, val1);
1343                                                 if (pnp_dump_flag) {
1344                                                         printf("'%s':", val1);
1345                                                         break;
1346                                                 }
1347                                                 if (*cp == 'D')
1348                                                         break;
1349                                                 s = pnpval_as_str(cp + 2, pnpinfo);
1350                                                 if (strcmp(s, val1) != 0)
1351                                                         notme++;
1352                                                 break;
1353                                                 /* Key override fields, required to be last in the string */
1354                                         case 'T':
1355                                                 /*
1356                                                  * This is imperfect and only does one key and will be redone
1357                                                  * to be more general for multiple keys. Currently, nothing
1358                                                  * does that.
1359                                                  */
1360                                                 if (pnp_dump_flag)                              /* No per-row data stored */
1361                                                         break;
1362                                                 if (cp[strlen(cp) - 1] == ';')          /* Skip required ; at end */
1363                                                         cp[strlen(cp) - 1] = '\0';      /* in case it's not there */
1364                                                 if ((s = strstr(pnpinfo, cp + 2)) == NULL)
1365                                                         notme++;
1366                                                 else if (s > pnpinfo && s[-1] != ' ')
1367                                                         notme++;
1368                                                 break;
1369                                         default:
1370                                                 printf("Unknown field type %c\n:", *cp);
1371                                                 break;
1372                                         }
1373                                         bit++;
1374                                         cp = strchr(cp, ';');
1375                                         if (cp)
1376                                                 cp++;
1377                                 } while (cp && *cp);
1378                                 if (pnp_dump_flag)
1379                                         printf("\n");
1380                                 else if (!notme) {
1381                                         if (!pnp_unbound_flag) {
1382                                                 if (pnp_verbose_flag)
1383                                                         printf("Matches --- %s ---\n", lastmod);
1384                                         }
1385                                         found++;
1386                                 }
1387                         }
1388                         break;
1389                 default:
1390                         break;
1391                 }
1392                 walker = (void *)(len - sizeof(int) + (intptr_t)walker);
1393         }
1394         if (pnp_unbound_flag && found == 0 && *pnpinfo) {
1395                 if (pnp_verbose_flag)
1396                         printf("------------------------- ");
1397                 printf("%s on %s pnpinfo %s", *dev ? dev : "unattached", bus, pnpinfo);
1398                 if (pnp_verbose_flag)
1399                         printf(" -------------------------");
1400                 printf("\n");
1401         }
1402         if (found != 0)
1403                 return (lastmod);
1404         free(lastmod);
1405
1406 bad:
1407         return (NULL);
1408 }
1409
1410 /*
1411  * Attempt to locate the file containing the module (name)
1412  */
1413 static char *
1414 mod_searchmodule(char *name, struct mod_depend *verinfo)
1415 {
1416         struct  moduledir *mdp;
1417         char    *result;
1418
1419         moduledir_rebuild();
1420         /*
1421          * Now we ready to lookup module in the given directories
1422          */
1423         result = NULL;
1424         STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
1425                 result = mod_search_hints(mdp, name, verinfo);
1426                 if (result)
1427                         break;
1428         }
1429
1430         return(result);
1431 }
1432
1433 static char *
1434 mod_searchmodule_pnpinfo(const char *bus, const char *pnpinfo)
1435 {
1436         struct  moduledir *mdp;
1437         char    *result;
1438
1439         moduledir_rebuild();
1440         /*
1441          * Now we ready to lookup module in the given directories
1442          */
1443         result = NULL;
1444         STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
1445                 result = devmatch_search_hints(mdp, bus, NULL, pnpinfo);
1446                 if (result)
1447                         break;
1448         }
1449
1450         return(result);
1451 }
1452
1453 int
1454 file_addmodule(struct preloaded_file *fp, char *modname, int version,
1455         struct kernel_module **newmp)
1456 {
1457         struct kernel_module *mp;
1458         struct mod_depend mdepend;
1459
1460         bzero(&mdepend, sizeof(mdepend));
1461         mdepend.md_ver_preferred = version;
1462         mp = file_findmodule(fp, modname, &mdepend);
1463         if (mp)
1464                 return (EEXIST);
1465         mp = calloc(1, sizeof(struct kernel_module));
1466         if (mp == NULL)
1467                 return (ENOMEM);
1468         mp->m_name = strdup(modname);
1469         if (mp->m_name == NULL) {
1470                 free(mp);
1471                 return (ENOMEM);
1472         }
1473         mp->m_version = version;
1474         mp->m_fp = fp;
1475         mp->m_next = fp->f_modules;
1476         fp->f_modules = mp;
1477         if (newmp)
1478                 *newmp = mp;
1479         return (0);
1480 }
1481
1482 /*
1483  * Throw a file away
1484  */
1485 void
1486 file_discard(struct preloaded_file *fp)
1487 {
1488         struct file_metadata    *md, *md1;
1489         struct kernel_module    *mp, *mp1;
1490         if (fp == NULL)
1491                 return;
1492         md = fp->f_metadata;
1493         while (md) {
1494                 md1 = md;
1495                 md = md->md_next;
1496                 free(md1);
1497         }
1498         mp = fp->f_modules;
1499         while (mp) {
1500                 free(mp->m_name);
1501                 mp1 = mp;
1502                 mp = mp->m_next;
1503                 free(mp1);
1504         }
1505         free(fp->f_name);
1506         free(fp->f_type);
1507         free(fp->f_args);
1508         free(fp);
1509 }
1510
1511 /*
1512  * Allocate a new file; must be used instead of malloc()
1513  * to ensure safe initialisation.
1514  */
1515 struct preloaded_file *
1516 file_alloc(void)
1517 {
1518
1519         return (calloc(1, sizeof(struct preloaded_file)));
1520 }
1521
1522 /*
1523  * Add a module to the chain
1524  */
1525 static void
1526 file_insert_tail(struct preloaded_file *fp)
1527 {
1528         struct preloaded_file   *cm;
1529     
1530         /* Append to list of loaded file */
1531         fp->f_next = NULL;
1532         if (preloaded_files == NULL) {
1533                 preloaded_files = fp;
1534         } else {
1535                 for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next)
1536                         ;
1537                 cm->f_next = fp;
1538         }
1539 }
1540
1541 /*
1542  * Remove module from the chain
1543  */
1544 static void
1545 file_remove(struct preloaded_file *fp)
1546 {
1547         struct preloaded_file   *cm;
1548
1549         if (preloaded_files == NULL)
1550                 return;
1551
1552         if (preloaded_files == fp) {
1553                 preloaded_files = fp->f_next;
1554                 return;
1555         }
1556         for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next) {
1557                 if (cm->f_next == fp) {
1558                         cm->f_next = fp->f_next;
1559                         return;
1560                 }
1561         }
1562 }
1563
1564 static char *
1565 moduledir_fullpath(struct moduledir *mdp, const char *fname)
1566 {
1567         char *cp;
1568
1569         cp = malloc(strlen(mdp->d_path) + strlen(fname) + 2);
1570         if (cp == NULL)
1571                 return NULL;
1572         strcpy(cp, mdp->d_path);
1573         strcat(cp, "/");
1574         strcat(cp, fname);
1575         return (cp);
1576 }
1577
1578 /*
1579  * Read linker.hints file into memory performing some sanity checks.
1580  */
1581 static void
1582 moduledir_readhints(struct moduledir *mdp)
1583 {
1584         struct stat     st;
1585         char    *path;
1586         int             fd, size, version;
1587
1588         if (mdp->d_hints != NULL || (mdp->d_flags & MDIR_NOHINTS))
1589                 return;
1590         path = moduledir_fullpath(mdp, "linker.hints");
1591         if (stat(path, &st) != 0 ||
1592           st.st_size < (ssize_t)(sizeof(version) + sizeof(int)) ||
1593           st.st_size > LINKER_HINTS_MAX || (fd = open(path, O_RDONLY)) < 0) {
1594                 free(path);
1595                 mdp->d_flags |= MDIR_NOHINTS;
1596                 return;
1597         }
1598         free(path);
1599         size = read(fd, &version, sizeof(version));
1600         if (size != sizeof(version) || version != LINKER_HINTS_VERSION)
1601                 goto bad;
1602         size = st.st_size - size;
1603         mdp->d_hints = malloc(size);
1604         if (mdp->d_hints == NULL)
1605                 goto bad;
1606         if (read(fd, mdp->d_hints, size) != size)
1607                 goto bad;
1608         mdp->d_hintsz = size;
1609         close(fd);
1610         return;
1611 bad:
1612         close(fd);
1613         free(mdp->d_hints);
1614         mdp->d_hints = NULL;
1615         mdp->d_flags |= MDIR_NOHINTS;
1616         return;
1617 }
1618
1619 /*
1620  * Extract directories from the ';' separated list, remove duplicates.
1621  */
1622 static void
1623 moduledir_rebuild(void)
1624 {
1625         struct  moduledir *mdp, *mtmp;
1626         const char      *path, *cp, *ep;
1627         size_t  cplen;
1628
1629         path = getenv("module_path");
1630         if (path == NULL)
1631                 path = default_searchpath;
1632         /*
1633          * Rebuild list of module directories if it changed
1634          */
1635         STAILQ_FOREACH(mdp, &moduledir_list, d_link)
1636                 mdp->d_flags |= MDIR_REMOVED;
1637
1638         for (ep = path; *ep != 0;  ep++) {
1639                 cp = ep;
1640                 for (; *ep != 0 && *ep != ';'; ep++)
1641                         ;
1642                 /*
1643                  * Ignore trailing slashes
1644                  */
1645                 for (cplen = ep - cp; cplen > 1 && cp[cplen - 1] == '/'; cplen--)
1646                         ;
1647                 STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
1648                         if (strlen(mdp->d_path) != cplen ||     bcmp(cp, mdp->d_path, cplen) != 0)
1649                                 continue;
1650                         mdp->d_flags &= ~MDIR_REMOVED;
1651                         break;
1652                 }
1653                 if (mdp == NULL) {
1654                         mdp = malloc(sizeof(*mdp) + cplen + 1);
1655                         if (mdp == NULL)
1656                                 return;
1657                         mdp->d_path = (char*)(mdp + 1);
1658                         bcopy(cp, mdp->d_path, cplen);
1659                         mdp->d_path[cplen] = 0;
1660                         mdp->d_hints = NULL;
1661                         mdp->d_flags = 0;
1662                         STAILQ_INSERT_TAIL(&moduledir_list, mdp, d_link);
1663                 }
1664                 if (*ep == 0)
1665                         break;
1666         }
1667         /*
1668          * Delete unused directories if any
1669          */
1670         mdp = STAILQ_FIRST(&moduledir_list);
1671         while (mdp) {
1672                 if ((mdp->d_flags & MDIR_REMOVED) == 0) {
1673                         mdp = STAILQ_NEXT(mdp, d_link);
1674                 } else {
1675                         free(mdp->d_hints);
1676                         mtmp = mdp;
1677                         mdp = STAILQ_NEXT(mdp, d_link);
1678                         STAILQ_REMOVE(&moduledir_list, mtmp, moduledir, d_link);
1679                         free(mtmp);
1680                 }
1681         }
1682         return;
1683 }