1 /* $NetBSD: main.c,v 1.100 2020/04/03 19:53:41 joerg Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratories.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * from: @(#)main.c 8.1 (Berkeley) 6/6/93
41 */
42
43 #if HAVE_NBTOOL_CONFIG_H
44 #include "nbtool_config.h"
45 #endif
46
47 #include <sys/cdefs.h>
48 __RCSID("$NetBSD: main.c,v 1.100 2020/04/03 19:53:41 joerg Exp $");
49
50 #ifndef MAKE_BOOTSTRAP
51 #include <sys/cdefs.h>
52 #define COPYRIGHT(x) __COPYRIGHT(x)
53 #else
54 #define COPYRIGHT(x) static const char copyright[] = x
55 #endif
56
57 #ifndef lint
58 COPYRIGHT("@(#) Copyright (c) 1992, 1993\
59 The Regents of the University of California. All rights reserved.");
60 #endif /* not lint */
61
62 #include <sys/types.h>
63 #include <sys/stat.h>
64 #include <sys/param.h>
65 #include <sys/mman.h>
66 #if !HAVE_NBTOOL_CONFIG_H
67 #include <sys/sysctl.h>
68 #endif
69 #include <paths.h>
70 #include <ctype.h>
71 #include <err.h>
72 #include <errno.h>
73 #include <fcntl.h>
74 #include <limits.h>
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <string.h>
78 #include <unistd.h>
79 #include <vis.h>
80 #include <util.h>
81
82 #include "defs.h"
83 #include "sem.h"
84
85 #ifndef LINE_MAX
86 #define LINE_MAX 1024
87 #endif
88
89 struct devbasetq allbases;
90 struct devatq alldevas;
91 struct conftq allcf;
92 struct devitq alldevi, allpseudo;
93 struct devmtq alldevms;
94 struct pspectq allpspecs;
95
96 struct devi **packed;
97 size_t npacked;
98
99 struct locators locators;
100
101 int lkmmode;
102 const char *conffile; /* source file, e.g., "GENERIC.sparc" */
103 const char *machine; /* machine type, e.g., "sparc" or "sun3" */
104 const char *machinearch; /* machine arch, e.g., "sparc" or "m68k" */
105 struct nvlist *machinesubarches;
106 /* machine subarches, e.g., "sun68k" or "hpc" */
107 const char *ioconfname; /* ioconf name, mutually exclusive to machine */
108 const char *srcdir; /* path to source directory (rel. to build) */
109 const char *builddir; /* path to build directory */
110 const char *defbuilddir; /* default build directory */
111 const char *ident; /* kernel "ident"ification string */
112 int errors; /* counts calls to error() */
113 int minmaxusers; /* minimum "maxusers" parameter */
114 int defmaxusers; /* default "maxusers" parameter */
115 int maxmaxusers; /* default "maxusers" parameter */
116 int maxusers; /* configuration's "maxusers" parameter */
117 int maxpartitions; /* configuration's "maxpartitions" parameter */
118 int version; /* version of the configuration file */
119 struct nvlist *options; /* options */
120 struct nvlist *fsoptions; /* filesystems */
121 struct nvlist *mkoptions; /* makeoptions */
122 struct nvlist *appmkoptions; /* appending mkoptions */
123 struct nvlist *condmkoptions; /* conditional makeoption table */
124 struct hashtab *devbasetab; /* devbase lookup */
125 struct hashtab *devroottab; /* attach at root lookup */
126 struct hashtab *devatab; /* devbase attachment lookup */
127 struct hashtab *deaddevitab; /* removed instances lookup */
128 struct hashtab *selecttab; /* selects things that are "optional foo" */
129 struct hashtab *needcnttab; /* retains names marked "needs-count" */
130 struct hashtab *opttab; /* table of configured options */
131 struct hashtab *fsopttab; /* table of configured file systems */
132 struct dlhash *defopttab; /* options that have been "defopt"'d */
133 struct dlhash *defflagtab; /* options that have been "defflag"'d */
134 struct dlhash *defparamtab; /* options that have been "defparam"'d */
135 struct dlhash *defoptlint; /* lint values for options */
136 struct nvhash *deffstab; /* defined file systems */
137 struct dlhash *optfiletab; /* "defopt"'d option .h files */
138 struct hashtab *attrtab; /* attributes (locators, etc.) */
139 struct hashtab *attrdeptab; /* attribute dependencies */
140 struct hashtab *bdevmtab; /* block devm lookup */
141 struct hashtab *cdevmtab; /* character devm lookup */
142
143 int ndevi; /* number of devi's (before packing) */
144 int npspecs; /* number of parent specs */
145 devmajor_t maxbdevm; /* max number of block major */
146 devmajor_t maxcdevm; /* max number of character major */
147 int do_devsw; /* 0 if pre-devsw config */
148 int oktopackage; /* 0 before setmachine() */
149 int devilevel; /* used for devi->i_level */
150
151 struct filelist allfiles; /* list of all kernel source files */
152 struct filelist allcfiles; /* list of all .c files */
153 struct filelist allsfiles; /* list of all .S files */
154 struct filelist allofiles; /* list of all .o files */
155
156 struct prefixlist prefixes, /* prefix stack */
157 allprefixes; /* all prefixes used (after popped) */
158 struct prefixlist buildprefixes, /* build prefix stack */
159 allbuildprefixes;/* all build prefixes used (after popped) */
160
161 int vflag; /* verbose output */
162 int Pflag; /* pack locators */
163 int Lflag; /* lint config generation */
164 int Mflag; /* modular build */
165 int Sflag; /* suffix rules & subdirectory */
166 int handling_cmdlineopts; /* currently processing -D/-U options */
167
168 int yyparse(void);
169
170 #if !defined(MAKE_BOOTSTRAP) && defined(YYDEBUG)
171 extern int yydebug;
172 #endif
173 int dflag;
174
175 static struct dlhash *obsopttab;
176 static struct hashtab *mkopttab;
177 static struct nvlist **nextopt;
178 static struct nvlist **nextmkopt;
179 static struct nvlist **nextappmkopt;
180 static struct nvlist **nextcndmkopt;
181 static struct nvlist **nextfsopt;
182 static struct nvlist *cmdlinedefs, *cmdlineundefs;
183
184 static void usage(void) __dead;
185 static void dependopts(void);
186 static void dependopts_one(const char *);
187 static void do_depends(struct nvlist *);
188 static void do_depend(struct nvlist *);
189 static void stop(void);
190 static int do_option(struct hashtab *, struct nvlist **,
191 struct nvlist ***, const char *, const char *,
192 const char *, struct hashtab *);
193 static int undo_option(struct hashtab *, struct nvlist **,
194 struct nvlist ***, const char *, const char *, int);
195 static int crosscheck(void);
196 static int badstar(void);
197 static int mkallsubdirs(void);
198 static int mksymlinks(void);
199 static int mkident(void);
200 static int devbase_has_dead_instances(const char *, void *, void *);
201 static int devbase_has_any_instance(struct devbase *, int, int, int);
202 static int check_dead_devi(const char *, void *, void *);
203 static void add_makeopt(const char *);
204 static void remove_makeopt(const char *);
205 static void handle_cmdline_makeoptions(void);
206 static void kill_orphans(void);
207 static void do_kill_orphans(struct devbase *, struct attr *,
208 struct devbase *, int);
209 static int kill_orphans_cb(const char *, void *, void *);
210 static int cfcrosscheck(struct config *, const char *, struct nvlist *);
211 static void defopt(struct dlhash *ht, const char *fname,
212 struct defoptlist *opts, struct nvlist *deps, int obs);
213 static struct defoptlist *find_declared_option_option(const char *name);
214 static struct nvlist *find_declared_fs_option(const char *name);
215
216 #define LOGCONFIG_LARGE "INCLUDE_CONFIG_FILE"
217 #define LOGCONFIG_SMALL "INCLUDE_JUST_CONFIG"
218
219 static void logconfig_start(void);
220 static void logconfig_end(void);
221 static FILE *cfg;
222 static time_t cfgtime;
223
224 static int is_elf(const char *);
225 static int extract_config(const char *, const char *, int);
226
227 int badfilename(const char *fname);
228
229 const char *progname;
230 extern const char *yyfile;
231
232 int
main(int argc,char ** argv)233 main(int argc, char **argv)
234 {
235 char *p, cname[PATH_MAX];
236 const char *last_component;
237 int pflag, xflag, ch, removeit;
238
239 setprogname(argv[0]);
240
241 pflag = 0;
242 xflag = 0;
243 while ((ch = getopt(argc, argv, "D:LMPSU:dgpvb:s:x")) != -1) {
244 switch (ch) {
245
246 case 'd':
247 #if !defined(MAKE_BOOTSTRAP) && defined(YYDEBUG)
248 yydebug = 1;
249 #endif
250 dflag++;
251 break;
252
253 case 'M':
254 Mflag = 1;
255 break;
256
257 case 'L':
258 Lflag = 1;
259 break;
260
261 case 'P':
262 Pflag = 1;
263 break;
264
265 case 'g':
266 /*
267 * In addition to DEBUG, you probably wanted to
268 * set "options KGDB" and maybe others. We could
269 * do that for you, but you really should just
270 * put them in the config file.
271 */
272 warnx("-g is obsolete (use -D DEBUG=\"-g\")");
273 usage();
274 /*NOTREACHED*/
275
276 case 'p':
277 /*
278 * Essentially the same as makeoptions PROF="-pg",
279 * but also changes the path from ../../compile/FOO
280 * to ../../compile/FOO.PROF; i.e., compile a
281 * profiling kernel based on a typical "regular"
282 * kernel.
283 *
284 * Note that if you always want profiling, you
285 * can (and should) use a "makeoptions" line.
286 */
287 pflag = 1;
288 break;
289
290 case 'v':
291 vflag = 1;
292 break;
293
294 case 'b':
295 builddir = optarg;
296 break;
297
298 case 's':
299 srcdir = optarg;
300 break;
301
302 case 'S':
303 Sflag = 1;
304 break;
305
306 case 'x':
307 xflag = 1;
308 break;
309
310 case 'D':
311 add_makeopt(optarg);
312 break;
313
314 case 'U':
315 remove_makeopt(optarg);
316 break;
317
318 case '?':
319 default:
320 usage();
321 }
322 }
323
324 if (xflag && optind != 2) {
325 errx(EXIT_FAILURE, "-x must be used alone");
326 }
327
328 argc -= optind;
329 argv += optind;
330 if (argc > 1) {
331 usage();
332 }
333
334 if (Lflag && (builddir != NULL || Pflag || pflag))
335 errx(EXIT_FAILURE, "-L can only be used with -s and -v");
336
337 if (xflag) {
338 if (argc == 0) {
339 #if !HAVE_NBTOOL_CONFIG_H
340 char path_unix[MAXPATHLEN];
341 size_t len = sizeof(path_unix) - 1;
342 path_unix[0] = '/';
343
344 conffile = sysctlbyname("machdep.booted_kernel",
345 &path_unix[1], &len, NULL, 0) == -1 ? _PATH_UNIX :
346 path_unix;
347 #else
348 errx(EXIT_FAILURE, "no kernel supplied");
349 #endif
350 } else
351 conffile = argv[0];
352 if (!is_elf(conffile))
353 errx(EXIT_FAILURE, "%s: not a binary kernel",
354 conffile);
355 if (!extract_config(conffile, "stdout", STDOUT_FILENO))
356 errx(EXIT_FAILURE, "%s does not contain embedded "
357 "configuration data", conffile);
358 exit(0);
359 }
360
361 conffile = (argc == 1) ? argv[0] : "CONFIG";
362 if (firstfile(conffile)) {
363 err(EXIT_FAILURE, "Cannot read `%s'", conffile);
364 exit(2);
365 }
366
367 /*
368 * Init variables.
369 */
370 minmaxusers = 1;
371 maxmaxusers = 10000;
372 initintern();
373 ident = NULL;
374 devbasetab = ht_new();
375 devroottab = ht_new();
376 devatab = ht_new();
377 devitab = ht_new();
378 deaddevitab = ht_new();
379 selecttab = ht_new();
380 needcnttab = ht_new();
381 opttab = ht_new();
382 mkopttab = ht_new();
383 fsopttab = ht_new();
384 deffstab = nvhash_create();
385 defopttab = dlhash_create();
386 defparamtab = dlhash_create();
387 defoptlint = dlhash_create();
388 defflagtab = dlhash_create();
389 optfiletab = dlhash_create();
390 obsopttab = dlhash_create();
391 bdevmtab = ht_new();
392 maxbdevm = 0;
393 cdevmtab = ht_new();
394 maxcdevm = 0;
395 nextopt = &options;
396 nextmkopt = &mkoptions;
397 nextappmkopt = &appmkoptions;
398 nextcndmkopt = &condmkoptions;
399 nextfsopt = &fsoptions;
400 initfiles();
401 initsem();
402
403 /*
404 * Handle profiling (must do this before we try to create any
405 * files).
406 */
407 last_component = strrchr(conffile, '/');
408 last_component = (last_component) ? last_component + 1 : conffile;
409 if (pflag) {
410 p = emalloc(strlen(last_component) + 17);
411 (void)sprintf(p, "../compile/%s.PROF", last_component);
412 (void)addmkoption(intern("PROF"), "-pg");
413 (void)addoption(intern("GPROF"), NULL);
414 } else {
415 p = emalloc(strlen(last_component) + 13);
416 (void)sprintf(p, "../compile/%s", last_component);
417 }
418 defbuilddir = (argc == 0) ? "." : p;
419
420 if (Lflag) {
421 char resolvedname[MAXPATHLEN];
422
423 if (realpath(conffile, resolvedname) == NULL)
424 err(EXIT_FAILURE, "realpath(%s)", conffile);
425
426 if (yyparse())
427 stop();
428
429 printf("include \"%s\"\n", resolvedname);
430
431 emit_params();
432 emit_options();
433 emit_instances();
434
435 exit(EXIT_SUCCESS);
436 }
437
438 removeit = 0;
439 if (is_elf(conffile)) {
440 const char *tmpdir;
441 int cfd;
442
443 if (builddir == NULL)
444 errx(EXIT_FAILURE, "Build directory must be specified "
445 "with binary kernels");
446
447 /* Open temporary configuration file */
448 tmpdir = getenv("TMPDIR");
449 if (tmpdir == NULL)
450 tmpdir = _PATH_TMP;
451 snprintf(cname, sizeof(cname), "%s/config.tmp.XXXXXX", tmpdir);
452 cfd = mkstemp(cname);
453 if (cfd == -1)
454 err(EXIT_FAILURE, "Cannot create `%s'", cname);
455
456 printf("Using configuration data embedded in kernel...\n");
457 if (!extract_config(conffile, cname, cfd)) {
458 unlink(cname);
459 errx(EXIT_FAILURE, "%s does not contain embedded "
460 "configuration data", conffile);
461 }
462
463 removeit = 1;
464 close(cfd);
465 firstfile(cname);
466 }
467
468 /*
469 * Log config file. We don't know until yyparse() if we're
470 * going to need config_file.h (i.e. if we're doing ioconf-only
471 * or not). Just start creating the file, and when we know
472 * later, we'll just keep or discard our work here.
473 */
474 logconfig_start();
475
476 /*
477 * Parse config file (including machine definitions).
478 */
479 if (yyparse())
480 stop();
481
482 if (ioconfname && cfg)
483 fclose(cfg);
484 else
485 logconfig_end();
486
487 if (removeit)
488 unlink(cname);
489
490 /*
491 * Handle command line overrides
492 */
493 yyfile = "handle_cmdline_makeoptions";
494 handle_cmdline_makeoptions();
495
496 /*
497 * Detect and properly ignore orphaned devices
498 */
499 yyfile = "kill_orphans";
500 kill_orphans();
501
502 /*
503 * Select devices and pseudo devices and their attributes
504 */
505 yyfile = "fixdevis";
506 if (fixdevis())
507 stop();
508
509 /*
510 * Copy maxusers to param.
511 */
512 yyfile = "fixmaxusers";
513 fixmaxusers();
514
515 /*
516 * Copy makeoptions to params
517 */
518 yyfile = "fixmkoption";
519 fixmkoption();
520
521 /*
522 * If working on an ioconf-only config, process here and exit
523 */
524 if (ioconfname) {
525 yyfile = "pack";
526 pack();
527 yyfile = "mkioconf";
528 mkioconf();
529 yyfile = "emitlocs";
530 emitlocs();
531 yyfile = "emitioconfh";
532 emitioconfh();
533 return 0;
534 }
535
536 yyfile = "dependattrs";
537 dependattrs();
538
539 /*
540 * Deal with option dependencies.
541 */
542 yyfile = "dependopts";
543 dependopts();
544
545 /*
546 * Fix (as in `set firmly in place') files.
547 */
548 yyfile = "fixfiles";
549 if (fixfiles())
550 stop();
551
552 /*
553 * Fix device-majors.
554 */
555 yyfile = "fixdevsw";
556 if (fixdevsw())
557 stop();
558
559 /*
560 * Perform cross-checking.
561 */
562 if (maxusers == 0) {
563 if (defmaxusers) {
564 (void)printf("maxusers not specified; %d assumed\n",
565 defmaxusers);
566 maxusers = defmaxusers;
567 } else {
568 warnx("need \"maxusers\" line");
569 errors++;
570 }
571 }
572 if (crosscheck() || errors)
573 stop();
574
575 /*
576 * Squeeze things down and finish cross-checks (STAR checks must
577 * run after packing).
578 */
579 yyfile = "pack";
580 pack();
581 yyfile = "badstar";
582 if (badstar())
583 stop();
584
585 yyfile = NULL;
586 /*
587 * Ready to go. Build all the various files.
588 */
589 if ((Sflag && mkallsubdirs()) || mksymlinks() || mkmakefile() || mkheaders() || mkswap() ||
590 mkioconf() || (do_devsw ? mkdevsw() : 0) || mkident() || errors)
591 stop();
592 (void)printf("Build directory is %s\n", builddir);
593 (void)printf("Don't forget to run \"make depend\"\n");
594
595 return 0;
596 }
597
598 static void
usage(void)599 usage(void)
600 {
601 (void)fprintf(stderr, "Usage: %s [-Ppv] [-b builddir] [-D var=value] "
602 "[-s srcdir] [-U var] "
603 "[config-file]\n\t%s -x [kernel-file]\n"
604 "\t%s -L [-v] [-s srcdir] [config-file]\n",
605 getprogname(), getprogname(), getprogname());
606 exit(1);
607 }
608
609 /*
610 * Set any options that are implied by other options.
611 */
612 static void
dependopts(void)613 dependopts(void)
614 {
615 struct nvlist *nv;
616
617 for (nv = options; nv != NULL; nv = nv->nv_next) {
618 dependopts_one(nv->nv_name);
619 }
620
621 for (nv = fsoptions; nv != NULL; nv = nv->nv_next) {
622 dependopts_one(nv->nv_name);
623 }
624 }
625
626 static void
dependopts_one(const char * name)627 dependopts_one(const char *name)
628 {
629 struct defoptlist *dl;
630 struct nvlist *fs;
631
632 dl = find_declared_option_option(name);
633 if (dl != NULL) {
634 do_depends(dl->dl_depends);
635 }
636 fs = find_declared_fs_option(name);
637 if (fs != NULL) {
638 do_depends(fs->nv_ptr);
639 }
640
641 CFGDBG(3, "depend `%s' searched", name);
642 }
643
644 static void
do_depends(struct nvlist * nv)645 do_depends(struct nvlist *nv)
646 {
647 struct nvlist *opt;
648
649 for (opt = nv; opt != NULL; opt = opt->nv_next) {
650 do_depend(opt);
651 }
652 }
653
654 static void
do_depend(struct nvlist * nv)655 do_depend(struct nvlist *nv)
656 {
657 struct attr *a;
658
659 if (nv != NULL && (nv->nv_flags & NV_DEPENDED) == 0) {
660 nv->nv_flags |= NV_DEPENDED;
661 /*
662 * If the dependency is an attribute, then just add
663 * it to the selecttab.
664 */
665 CFGDBG(3, "depend attr `%s'", nv->nv_name);
666 if ((a = ht_lookup(attrtab, nv->nv_name)) != NULL) {
667 if (a->a_iattr)
668 panic("do_depend(%s): dep `%s' is an iattr",
669 nv->nv_name, a->a_name);
670 expandattr(a, selectattr);
671 } else {
672 if (ht_lookup(opttab, nv->nv_name) == NULL)
673 addoption(nv->nv_name, NULL);
674 dependopts_one(nv->nv_name);
675 }
676 }
677 }
678
679 static int
recreate(const char * p,const char * q)680 recreate(const char *p, const char *q)
681 {
682 int ret;
683
684 if ((ret = unlink(q)) == -1 && errno != ENOENT)
685 warn("unlink(%s)", q);
686 if ((ret = symlink(p, q)) == -1)
687 warn("symlink(%s -> %s)", q, p);
688 return ret;
689 }
690
691 static void
mksubdir(char * buf)692 mksubdir(char *buf)
693 {
694 char *p;
695 struct stat st;
696
697 p = strrchr(buf, '/');
698 if (p != NULL && *p == '/') {
699 *p = '\0';
700 mksubdir(buf);
701 *p = '/';
702 }
703 if (stat(buf, &st) == 0) {
704 if (!S_ISDIR(st.st_mode))
705 errx(EXIT_FAILURE, "not directory %s", buf);
706 } else
707 if (mkdir(buf, 0777) == -1)
708 errx(EXIT_FAILURE, "cannot create %s", buf);
709 }
710
711 static int
mksubdirs(struct filelist * fl)712 mksubdirs(struct filelist *fl)
713 {
714 struct files *fi;
715 const char *prologue, *prefix, *sep;
716 char buf[MAXPATHLEN];
717
718 TAILQ_FOREACH(fi, fl, fi_next) {
719 if ((fi->fi_flags & FI_SEL) == 0)
720 continue;
721 prefix = sep = "";
722 if (fi->fi_buildprefix != NULL) {
723 prefix = fi->fi_buildprefix;
724 sep = "/";
725 } else {
726 if (fi->fi_prefix != NULL) {
727 prefix = fi->fi_prefix;
728 sep = "/";
729 }
730 }
731 snprintf(buf, sizeof(buf), "%s%s%s", prefix, sep, fi->fi_dir);
732 if (buf[0] == '\0')
733 continue;
734 mksubdir(buf);
735 if (fi->fi_prefix != NULL && fi->fi_buildprefix != NULL) {
736 char org[MAXPATHLEN];
737
738 if (fi->fi_prefix[0] == '/') {
739 prologue = "";
740 sep = "";
741 } else {
742 prologue = srcdir;
743 sep = "/";
744 }
745 snprintf(buf, sizeof(buf), "%s%s%s",
746 fi->fi_buildprefix, "/", fi->fi_path);
747 snprintf(org, sizeof(org), "%s%s%s%s%s",
748 prologue, sep, fi->fi_prefix, "/", fi->fi_path);
749 recreate(org, buf);
750 fi->fi_prefix = fi->fi_buildprefix;
751 fi->fi_buildprefix = NULL;
752 }
753 }
754
755 return 0;
756 }
757
758 static int
mkallsubdirs(void)759 mkallsubdirs(void)
760 {
761
762 mksubdirs(&allfiles);
763 mksubdirs(&allofiles);
764 return 0;
765 }
766
767 /*
768 * Make a symlink for "machine" so that "#include <machine/foo.h>" works,
769 * and for the machine's CPU architecture, so that works as well.
770 */
771 static int
mksymlinks(void)772 mksymlinks(void)
773 {
774 int ret;
775 char *p, buf[MAXPATHLEN];
776 const char *q;
777 struct nvlist *nv;
778
779 p = buf;
780
781 snprintf(buf, sizeof(buf), "%s/arch/%s/include", srcdir, machine);
782 ret = recreate(p, "machine");
783 ret = recreate(p, machine);
784
785 if (machinearch != NULL) {
786 snprintf(buf, sizeof(buf), "%s/arch/%s/include", srcdir, machinearch);
787 q = machinearch;
788 } else {
789 snprintf(buf, sizeof(buf), "machine");
790 q = machine;
791 }
792
793 ret = recreate(p, q);
794
795 for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) {
796 q = nv->nv_name;
797 snprintf(buf, sizeof(buf), "%s/arch/%s/include", srcdir, q);
798 ret = recreate(p, q);
799 }
800
801 return (ret);
802 }
803
804 static __dead void
stop(void)805 stop(void)
806 {
807 (void)fprintf(stderr, "*** Stop.\n");
808 exit(1);
809 }
810
811 static void
check_dependencies(const char * thing,struct nvlist * deps)812 check_dependencies(const char *thing, struct nvlist *deps)
813 {
814 struct nvlist *dep;
815 struct attr *a;
816
817 for (dep = deps; dep != NULL; dep = dep->nv_next) {
818 /*
819 * If the dependency is an attribute, it must not
820 * be an interface attribute. Otherwise, it must
821 * be a previously declared option.
822 */
823 if ((a = ht_lookup(attrtab, dep->nv_name)) != NULL) {
824 if (a->a_iattr)
825 cfgerror("option `%s' dependency `%s' "
826 "is an interface attribute",
827 thing, a->a_name);
828 } else if (OPT_OBSOLETE(dep->nv_name)) {
829 cfgerror("option `%s' dependency `%s' "
830 "is obsolete", thing, dep->nv_name);
831 } else if (!find_declared_option(dep->nv_name)) {
832 cfgerror("option `%s' dependency `%s' "
833 "is an unknown option",
834 thing, dep->nv_name);
835 }
836 }
837 }
838
839 static void
add_fs_dependencies(struct nvlist * nv,struct nvlist * deps)840 add_fs_dependencies(struct nvlist *nv, struct nvlist *deps)
841 {
842 /* Use nv_ptr to link any other options that are implied. */
843 nv->nv_ptr = deps;
844 check_dependencies(nv->nv_name, deps);
845 }
846
847 static void
add_opt_dependencies(struct defoptlist * dl,struct nvlist * deps)848 add_opt_dependencies(struct defoptlist *dl, struct nvlist *deps)
849 {
850 dl->dl_depends = deps;
851 check_dependencies(dl->dl_name, deps);
852 }
853
854 /*
855 * Define one or more file systems.
856 */
857 void
deffilesystem(struct nvlist * fses,struct nvlist * deps)858 deffilesystem(struct nvlist *fses, struct nvlist *deps)
859 {
860 struct nvlist *nv;
861 struct where *w;
862
863 /*
864 * Mark these options as ones to skip when creating the Makefile.
865 */
866 for (nv = fses; nv != NULL; nv = nv->nv_next) {
867 if ((w = DEFINED_OPTION(nv->nv_name)) != NULL) {
868 cfgerror("file system or option `%s' already defined"
869 " at %s:%hu", nv->nv_name, w->w_srcfile,
870 w->w_srcline);
871 return;
872 }
873
874 /*
875 * Also mark it as a valid file system, which may be
876 * used in "file-system" directives in the config
877 * file.
878 */
879 if (nvhash_insert(deffstab, nv->nv_name, nv))
880 panic("file system `%s' already in table?!",
881 nv->nv_name);
882
883 add_fs_dependencies(nv, deps);
884
885 /*
886 * Implicit attribute definition for filesystem.
887 */
888 const char *n;
889 n = strtolower(nv->nv_name);
890 refattr(n);
891 }
892 }
893
894 /*
895 * Sanity check a file name.
896 */
897 int
badfilename(const char * fname)898 badfilename(const char *fname)
899 {
900 const char *n;
901
902 /*
903 * We're putting multiple options into one file. Sanity
904 * check the file name.
905 */
906 if (strchr(fname, '/') != NULL) {
907 cfgerror("option file name contains a `/'");
908 return 1;
909 }
910 if ((n = strrchr(fname, '.')) == NULL || strcmp(n, ".h") != 0) {
911 cfgerror("option file name does not end in `.h'");
912 return 1;
913 }
914 return 0;
915 }
916
917
918 /*
919 * Search for a defined option (defopt, filesystem, etc), and if found,
920 * return the option's struct nvlist.
921 *
922 * This used to be one function (find_declared_option) before options
923 * and filesystems became different types.
924 */
925 static struct defoptlist *
find_declared_option_option(const char * name)926 find_declared_option_option(const char *name)
927 {
928 struct defoptlist *option;
929
930 if ((option = dlhash_lookup(defopttab, name)) != NULL ||
931 (option = dlhash_lookup(defparamtab, name)) != NULL ||
932 (option = dlhash_lookup(defflagtab, name)) != NULL) {
933 return (option);
934 }
935
936 return (NULL);
937 }
938
939 static struct nvlist *
find_declared_fs_option(const char * name)940 find_declared_fs_option(const char *name)
941 {
942 struct nvlist *fs;
943
944 if ((fs = nvhash_lookup(deffstab, name)) != NULL) {
945 return fs;
946 }
947
948 return (NULL);
949 }
950
951 /*
952 * Like find_declared_option but doesn't return what it finds, so it
953 * can search both the various kinds of options and also filesystems.
954 */
955 struct where *
find_declared_option(const char * name)956 find_declared_option(const char *name)
957 {
958 struct defoptlist *option = NULL;
959 struct nvlist *fs;
960
961 if ((option = dlhash_lookup(defopttab, name)) != NULL ||
962 (option = dlhash_lookup(defparamtab, name)) != NULL ||
963 (option = dlhash_lookup(defflagtab, name)) != NULL) {
964 return &option->dl_where;
965 }
966 if ((fs = nvhash_lookup(deffstab, name)) != NULL) {
967 return &fs->nv_where;
968 }
969
970 return NULL;
971 }
972
973 /*
974 * Define one or more standard options. If an option file name is specified,
975 * place all options in one file with the specified name. Otherwise, create
976 * an option file for each option.
977 * record the option information in the specified table.
978 */
979 void
defopt(struct dlhash * ht,const char * fname,struct defoptlist * opts,struct nvlist * deps,int obs)980 defopt(struct dlhash *ht, const char *fname, struct defoptlist *opts,
981 struct nvlist *deps, int obs)
982 {
983 struct defoptlist *dl, *nextdl, *olddl;
984 const char *name;
985 struct where *w;
986 char buf[500];
987
988 if (fname != NULL && badfilename(fname)) {
989 return;
990 }
991
992 /*
993 * Mark these options as ones to skip when creating the Makefile.
994 */
995 for (dl = opts; dl != NULL; dl = nextdl) {
996 nextdl = dl->dl_next;
997
998 if (dl->dl_lintvalue != NULL) {
999 /*
1000 * If an entry already exists, then we are about to
1001 * complain, so no worry.
1002 */
1003 (void) dlhash_insert(defoptlint, dl->dl_name,
1004 dl);
1005 }
1006
1007 /* An option name can be declared at most once. */
1008 if ((w = DEFINED_OPTION(dl->dl_name)) != NULL) {
1009 cfgerror("file system or option `%s' already defined"
1010 " at %s:%hu", dl->dl_name, w->w_srcfile,
1011 w->w_srcline);
1012 return;
1013 }
1014
1015 if (dlhash_insert(ht, dl->dl_name, dl)) {
1016 cfgerror("file system or option `%s' already defined"
1017 " at %s:%hu", dl->dl_name, dl->dl_where.w_srcfile,
1018 dl->dl_where.w_srcline);
1019 return;
1020 }
1021
1022 if (fname == NULL) {
1023 /*
1024 * Each option will be going into its own file.
1025 * Convert the option name to lower case. This
1026 * lower case name will be used as the option
1027 * file name.
1028 */
1029 (void) snprintf(buf, sizeof(buf), "opt_%s.h",
1030 strtolower(dl->dl_name));
1031 name = intern(buf);
1032 } else {
1033 name = fname;
1034 }
1035
1036 add_opt_dependencies(dl, deps);
1037
1038 /*
1039 * Remove this option from the parameter list before adding
1040 * it to the list associated with this option file.
1041 */
1042 dl->dl_next = NULL;
1043
1044 /*
1045 * Flag as obsolete, if requested.
1046 */
1047 if (obs) {
1048 dl->dl_obsolete = 1;
1049 (void)dlhash_insert(obsopttab, dl->dl_name, dl);
1050 }
1051
1052 /*
1053 * Add this option file if we haven't seen it yet.
1054 * Otherwise, append to the list of options already
1055 * associated with this file.
1056 */
1057 if ((olddl = dlhash_lookup(optfiletab, name)) == NULL) {
1058 (void)dlhash_insert(optfiletab, name, dl);
1059 } else {
1060 while (olddl->dl_next != NULL)
1061 olddl = olddl->dl_next;
1062 olddl->dl_next = dl;
1063 }
1064 }
1065 }
1066
1067 /*
1068 * Define one or more standard options. If an option file name is specified,
1069 * place all options in one file with the specified name. Otherwise, create
1070 * an option file for each option.
1071 */
1072 void
defoption(const char * fname,struct defoptlist * opts,struct nvlist * deps)1073 defoption(const char *fname, struct defoptlist *opts, struct nvlist *deps)
1074 {
1075
1076 cfgwarn("The use of `defopt' is deprecated");
1077 defopt(defopttab, fname, opts, deps, 0);
1078 }
1079
1080
1081 /*
1082 * Define an option for which a value is required.
1083 */
1084 void
defparam(const char * fname,struct defoptlist * opts,struct nvlist * deps,int obs)1085 defparam(const char *fname, struct defoptlist *opts, struct nvlist *deps, int obs)
1086 {
1087
1088 defopt(defparamtab, fname, opts, deps, obs);
1089 }
1090
1091 /*
1092 * Define an option which must not have a value, and which
1093 * emits a "needs-flag" style output.
1094 */
1095 void
defflag(const char * fname,struct defoptlist * opts,struct nvlist * deps,int obs)1096 defflag(const char *fname, struct defoptlist *opts, struct nvlist *deps, int obs)
1097 {
1098
1099 defopt(defflagtab, fname, opts, deps, obs);
1100 }
1101
1102
1103 /*
1104 * Add an option from "options FOO". Note that this selects things that
1105 * are "optional foo".
1106 */
1107 void
addoption(const char * name,const char * value)1108 addoption(const char *name, const char *value)
1109 {
1110 const char *n;
1111 int is_fs, is_param, is_flag, is_undecl, is_obs;
1112
1113 /*
1114 * Figure out how this option was declared (if at all.)
1115 * XXX should use "params" and "flags" in config.
1116 * XXX crying out for a type field in a unified hashtab.
1117 */
1118 is_fs = OPT_FSOPT(name);
1119 is_param = OPT_DEFPARAM(name);
1120 is_flag = OPT_DEFFLAG(name);
1121 is_obs = OPT_OBSOLETE(name);
1122 is_undecl = !DEFINED_OPTION(name);
1123
1124 /* Warn and pretend the user had not selected the option */
1125 if (is_obs) {
1126 cfgwarn("obsolete option `%s' will be ignored", name);
1127 return;
1128 }
1129
1130 /* Make sure this is not a defined file system. */
1131 if (is_fs) {
1132 cfgerror("`%s' is a defined file system", name);
1133 return;
1134 }
1135 /* A defparam must have a value */
1136 if (is_param && value == NULL) {
1137 cfgerror("option `%s' must have a value", name);
1138 return;
1139 }
1140 /* A defflag must not have a value */
1141 if (is_flag && value != NULL) {
1142 cfgerror("option `%s' must not have a value", name);
1143 return;
1144 }
1145
1146 if (is_undecl && vflag) {
1147 cfgwarn("undeclared option `%s' added to IDENT", name);
1148 }
1149
1150 if (do_option(opttab, &options, &nextopt, name, value, "options",
1151 selecttab))
1152 return;
1153
1154 /* make lowercase, then add to select table */
1155 n = strtolower(name);
1156 (void)ht_insert(selecttab, n, (void *)__UNCONST(n));
1157 CFGDBG(3, "option selected `%s'", n);
1158 }
1159
1160 void
deloption(const char * name,int nowarn)1161 deloption(const char *name, int nowarn)
1162 {
1163
1164 CFGDBG(4, "deselecting opt `%s'", name);
1165 if (undo_option(opttab, &options, &nextopt, name, "options", nowarn))
1166 return;
1167 if (undo_option(selecttab, NULL, NULL, strtolower(name), "options", nowarn))
1168 return;
1169 }
1170
1171 /*
1172 * Add a file system option. This routine simply inserts the name into
1173 * a list of valid file systems, which is used to validate the root
1174 * file system type. The name is then treated like a standard option.
1175 */
1176 void
addfsoption(const char * name)1177 addfsoption(const char *name)
1178 {
1179 const char *n;
1180
1181 /* Make sure this is a defined file system. */
1182 if (!OPT_FSOPT(name)) {
1183 cfgerror("`%s' is not a defined file system", name);
1184 return;
1185 }
1186
1187 /*
1188 * Convert to lower case. This will be used in the select
1189 * table, to verify root file systems.
1190 */
1191 n = strtolower(name);
1192
1193 if (do_option(fsopttab, &fsoptions, &nextfsopt, name, n, "file-system",
1194 selecttab))
1195 return;
1196
1197 /* Add to select table. */
1198 (void)ht_insert(selecttab, n, __UNCONST(n));
1199 CFGDBG(3, "fs selected `%s'", name);
1200
1201 /*
1202 * Select attribute if one exists.
1203 */
1204 struct attr *a;
1205 if ((a = ht_lookup(attrtab, n)) != NULL)
1206 selectattr(a);
1207 }
1208
1209 void
delfsoption(const char * name,int nowarn)1210 delfsoption(const char *name, int nowarn)
1211 {
1212 const char *n;
1213
1214 CFGDBG(4, "deselecting fs `%s'", name);
1215 n = strtolower(name);
1216 if (undo_option(fsopttab, &fsoptions, &nextfsopt, name, "file-system", nowarn))
1217 return;
1218 if (undo_option(selecttab, NULL, NULL, n, "file-system", nowarn))
1219 return;
1220 }
1221
1222 /*
1223 * Add a "make" option.
1224 */
1225 void
addmkoption(const char * name,const char * value)1226 addmkoption(const char *name, const char *value)
1227 {
1228
1229 (void)do_option(mkopttab, &mkoptions, &nextmkopt, name, value,
1230 "makeoptions", NULL);
1231 }
1232
1233 void
delmkoption(const char * name,int nowarn)1234 delmkoption(const char *name, int nowarn)
1235 {
1236
1237 CFGDBG(4, "deselecting mkopt `%s'", name);
1238 (void)undo_option(mkopttab, &mkoptions, &nextmkopt, name,
1239 "makeoptions", nowarn);
1240 }
1241
1242 /*
1243 * Add an appending "make" option.
1244 */
1245 void
appendmkoption(const char * name,const char * value)1246 appendmkoption(const char *name, const char *value)
1247 {
1248 struct nvlist *nv;
1249
1250 nv = newnv(name, value, NULL, 0, NULL);
1251 *nextappmkopt = nv;
1252 nextappmkopt = &nv->nv_next;
1253 }
1254
1255 /*
1256 * Add a conditional appending "make" option.
1257 */
1258 void
appendcondmkoption(struct condexpr * cond,const char * name,const char * value)1259 appendcondmkoption(struct condexpr *cond, const char *name, const char *value)
1260 {
1261 struct nvlist *nv;
1262
1263 nv = newnv(name, value, cond, 0, NULL);
1264 *nextcndmkopt = nv;
1265 nextcndmkopt = &nv->nv_next;
1266 }
1267
1268 /*
1269 * Copy maxusers to param "MAXUSERS".
1270 */
1271 void
fixmaxusers(void)1272 fixmaxusers(void)
1273 {
1274 char str[32];
1275
1276 snprintf(str, sizeof(str), "%d", maxusers);
1277 addoption(intern("MAXUSERS"), intern(str));
1278 }
1279
1280 /*
1281 * Copy makeoptions to params with "makeoptions_" prefix.
1282 */
1283 void
fixmkoption(void)1284 fixmkoption(void)
1285 {
1286 struct nvlist *nv;
1287 char buf[100];
1288 const char *name;
1289
1290 for (nv = mkoptions; nv != NULL; nv = nv->nv_next) {
1291 snprintf(buf, sizeof(buf), "makeoptions_%s", nv->nv_name);
1292 name = intern(buf);
1293 if (!DEFINED_OPTION(name) || !OPT_DEFPARAM(name))
1294 continue;
1295 addoption(name, intern(nv->nv_str));
1296 }
1297 }
1298
1299 /*
1300 * Add a name=value pair to an option list. The value may be NULL.
1301 */
1302 static int
do_option(struct hashtab * ht,struct nvlist ** npp,struct nvlist *** next,const char * name,const char * value,const char * type,struct hashtab * stab)1303 do_option(struct hashtab *ht, struct nvlist **npp, struct nvlist ***next,
1304 const char *name, const char *value, const char *type,
1305 struct hashtab *stab)
1306 {
1307 struct nvlist *nv, *onv;
1308
1309 /* assume it will work */
1310 nv = newnv(name, value, NULL, 0, NULL);
1311 if (ht_insert(ht, name, nv) != 0) {
1312
1313 /* oops, already got that option - remove it first */
1314 if ((onv = ht_lookup(ht, name)) == NULL)
1315 panic("do_option 1");
1316 if (onv->nv_str != NULL && !OPT_FSOPT(name))
1317 cfgwarn("already have %s `%s=%s'", type, name,
1318 onv->nv_str);
1319 else
1320 cfgwarn("already have %s `%s'", type, name);
1321
1322 if (undo_option(ht, npp, next, name, type, 0))
1323 panic("do_option 2");
1324 if (stab != NULL &&
1325 undo_option(stab, NULL, NULL, strtolower(name), type, 0))
1326 panic("do_option 3");
1327
1328 /* now try adding it again */
1329 if (ht_insert(ht, name, nv) != 0)
1330 panic("do_option 4");
1331
1332 CFGDBG(2, "opt `%s' replaced", name);
1333 }
1334 **next = nv;
1335 *next = &nv->nv_next;
1336
1337 return (0);
1338 }
1339
1340 /*
1341 * Remove a name from a hash table,
1342 * and optionally, a name=value pair from an option list.
1343 */
1344 static int
undo_option(struct hashtab * ht,struct nvlist ** npp,struct nvlist *** next,const char * name,const char * type,int nowarn)1345 undo_option(struct hashtab *ht, struct nvlist **npp,
1346 struct nvlist ***next, const char *name, const char *type, int nowarn)
1347 {
1348 struct nvlist *nv;
1349
1350 if (ht_remove(ht, name)) {
1351 /*
1352 * -U command line option removals are always silent
1353 */
1354 if (!handling_cmdlineopts && !nowarn)
1355 cfgwarn("%s `%s' is not defined", type, name);
1356 return (1);
1357 }
1358 if (npp == NULL) {
1359 CFGDBG(2, "opt `%s' deselected", name);
1360 return (0);
1361 }
1362
1363 for ( ; *npp != NULL; npp = &(*npp)->nv_next) {
1364 if ((*npp)->nv_name != name)
1365 continue;
1366 if (next != NULL && *next == &(*npp)->nv_next)
1367 *next = npp;
1368 nv = (*npp)->nv_next;
1369 CFGDBG(2, "opt `%s' deselected", (*npp)->nv_name);
1370 nvfree(*npp);
1371 *npp = nv;
1372 return (0);
1373 }
1374 panic("%s `%s' is not defined in nvlist", type, name);
1375 return (1);
1376 }
1377
1378 /*
1379 * Return true if there is at least one instance of the given unit
1380 * on the given device attachment (or any units, if unit == WILD).
1381 */
1382 int
deva_has_instances(struct deva * deva,int unit)1383 deva_has_instances(struct deva *deva, int unit)
1384 {
1385 struct devi *i;
1386
1387 /*
1388 * EHAMMERTOOBIG: we shouldn't check i_pseudoroot here.
1389 * What we want by this check is them to appear non-present
1390 * except for purposes of other devices being able to attach
1391 * to them.
1392 */
1393 for (i = deva->d_ihead; i != NULL; i = i->i_asame)
1394 if (i->i_active == DEVI_ACTIVE && i->i_pseudoroot == 0 &&
1395 (unit == WILD || unit == i->i_unit || i->i_unit == STAR))
1396 return (1);
1397 return (0);
1398 }
1399
1400 /*
1401 * Return true if there is at least one instance of the given unit
1402 * on the given base (or any units, if unit == WILD).
1403 */
1404 int
devbase_has_instances(struct devbase * dev,int unit)1405 devbase_has_instances(struct devbase *dev, int unit)
1406 {
1407 struct deva *da;
1408
1409 /*
1410 * Pseudo-devices are a little special. We consider them
1411 * to have instances only if they are both:
1412 *
1413 * 1. Included in this kernel configuration.
1414 *
1415 * 2. Be declared "defpseudodev".
1416 */
1417 if (dev->d_ispseudo) {
1418 return ((ht_lookup(devitab, dev->d_name) != NULL)
1419 && (dev->d_ispseudo > 1));
1420 }
1421
1422 for (da = dev->d_ahead; da != NULL; da = da->d_bsame)
1423 if (deva_has_instances(da, unit))
1424 return (1);
1425 return (0);
1426 }
1427
1428 static int
cfcrosscheck(struct config * cf,const char * what,struct nvlist * nv)1429 cfcrosscheck(struct config *cf, const char *what, struct nvlist *nv)
1430 {
1431 struct devbase *dev;
1432 struct devi *pd;
1433 int errs, devunit;
1434
1435 if (maxpartitions <= 0)
1436 panic("cfcrosscheck");
1437
1438 for (errs = 0; nv != NULL; nv = nv->nv_next) {
1439 if (nv->nv_name == NULL)
1440 continue;
1441 dev = ht_lookup(devbasetab, nv->nv_name);
1442 if (dev == NULL)
1443 panic("cfcrosscheck(%s)", nv->nv_name);
1444 if (has_attr(dev->d_attrs, s_ifnet))
1445 devunit = nv->nv_ifunit; /* XXX XXX XXX */
1446 else
1447 devunit = (int)(minor(nv->nv_num) / maxpartitions);
1448 if (devbase_has_instances(dev, devunit))
1449 continue;
1450 if (devbase_has_instances(dev, STAR) &&
1451 devunit >= dev->d_umax)
1452 continue;
1453 TAILQ_FOREACH(pd, &allpseudo, i_next) {
1454 if (pd->i_base == dev && devunit < dev->d_umax &&
1455 devunit >= 0)
1456 goto loop;
1457 }
1458 (void)fprintf(stderr,
1459 "%s:%hu: %s says %s on %s, but there's no %s\n",
1460 conffile, cf->cf_where.w_srcline,
1461 cf->cf_name, what, nv->nv_str, nv->nv_str);
1462 errs++;
1463 loop:
1464 ;
1465 }
1466 return (errs);
1467 }
1468
1469 /*
1470 * Cross-check the configuration: make sure that each target device
1471 * or attribute (`at foo[0*?]') names at least one real device. Also
1472 * see that the root and dump devices for all configurations are there.
1473 */
1474 int
crosscheck(void)1475 crosscheck(void)
1476 {
1477 struct config *cf;
1478 int errs;
1479
1480 errs = 0;
1481 if (TAILQ_EMPTY(&allcf)) {
1482 warnx("%s has no configurations!", conffile);
1483 errs++;
1484 }
1485 TAILQ_FOREACH(cf, &allcf, cf_next) {
1486 if (cf->cf_root != NULL) { /* i.e., not root on ? */
1487 errs += cfcrosscheck(cf, "root", cf->cf_root);
1488 errs += cfcrosscheck(cf, "dumps", cf->cf_dump);
1489 }
1490 }
1491 return (errs);
1492 }
1493
1494 /*
1495 * Check to see if there is a *'d unit with a needs-count file.
1496 */
1497 int
badstar(void)1498 badstar(void)
1499 {
1500 struct devbase *d;
1501 struct deva *da;
1502 struct devi *i;
1503 int errs, n;
1504
1505 errs = 0;
1506 TAILQ_FOREACH(d, &allbases, d_next) {
1507 for (da = d->d_ahead; da != NULL; da = da->d_bsame)
1508 for (i = da->d_ihead; i != NULL; i = i->i_asame) {
1509 if (i->i_unit == STAR)
1510 goto aybabtu;
1511 }
1512 continue;
1513 aybabtu:
1514 if (ht_lookup(needcnttab, d->d_name)) {
1515 warnx("%s's cannot be *'d until its driver is fixed",
1516 d->d_name);
1517 errs++;
1518 continue;
1519 }
1520 for (n = 0; i != NULL; i = i->i_alias)
1521 if (!i->i_collapsed)
1522 n++;
1523 if (n < 1)
1524 panic("badstar() n<1");
1525 }
1526 return (errs);
1527 }
1528
1529 /*
1530 * Verify/create builddir if necessary, change to it, and verify srcdir.
1531 * This will be called when we see the first include.
1532 */
1533 void
setupdirs(void)1534 setupdirs(void)
1535 {
1536 struct stat st;
1537
1538 /* srcdir must be specified if builddir is not specified or if
1539 * no configuration filename was specified. */
1540 if ((builddir || strcmp(defbuilddir, ".") == 0) && !srcdir) {
1541 cfgerror("source directory must be specified");
1542 exit(1);
1543 }
1544
1545 if (Lflag) {
1546 if (srcdir == NULL)
1547 srcdir = "../../..";
1548 return;
1549 }
1550
1551 if (srcdir == NULL)
1552 srcdir = "../../../..";
1553 if (builddir == NULL)
1554 builddir = defbuilddir;
1555
1556 if (stat(builddir, &st) == -1) {
1557 if (mkdir(builddir, 0777) == -1)
1558 errx(EXIT_FAILURE, "cannot create %s", builddir);
1559 } else if (!S_ISDIR(st.st_mode))
1560 errx(EXIT_FAILURE, "%s is not a directory", builddir);
1561 if (chdir(builddir) == -1)
1562 err(EXIT_FAILURE, "cannot change to %s", builddir);
1563 if (stat(srcdir, &st) == -1)
1564 err(EXIT_FAILURE, "cannot stat %s", srcdir);
1565 if (!S_ISDIR(st.st_mode))
1566 errx(EXIT_FAILURE, "%s is not a directory", srcdir);
1567 }
1568
1569 /*
1570 * Write identifier from "ident" directive into file, for
1571 * newvers.sh to pick it up.
1572 */
1573 int
mkident(void)1574 mkident(void)
1575 {
1576 FILE *fp;
1577 int error = 0;
1578
1579 (void)unlink("ident");
1580
1581 if (ident == NULL)
1582 return (0);
1583
1584 if ((fp = fopen("ident", "w")) == NULL) {
1585 warn("cannot write ident");
1586 return (1);
1587 }
1588 if (vflag)
1589 (void)printf("using ident '%s'\n", ident);
1590 fprintf(fp, "%s\n", ident);
1591 fflush(fp);
1592 if (ferror(fp))
1593 error = 1;
1594 (void)fclose(fp);
1595
1596 return error;
1597 }
1598
1599 void
logconfig_start(void)1600 logconfig_start(void)
1601 {
1602 extern FILE *yyin;
1603 char line[1024];
1604 const char *tmpdir;
1605 struct stat st;
1606 int fd;
1607
1608 if (yyin == NULL || fstat(fileno(yyin), &st) == -1)
1609 return;
1610 cfgtime = st.st_mtime;
1611
1612 tmpdir = getenv("TMPDIR");
1613 if (tmpdir == NULL)
1614 tmpdir = _PATH_TMP;
1615 (void)snprintf(line, sizeof(line), "%s/config.tmp.XXXXXX", tmpdir);
1616 if ((fd = mkstemp(line)) == -1 ||
1617 (cfg = fdopen(fd, "r+")) == NULL) {
1618 if (fd != -1) {
1619 (void)unlink(line);
1620 (void)close(fd);
1621 }
1622 cfg = NULL;
1623 return;
1624 }
1625 (void)unlink(line);
1626
1627 (void)fprintf(cfg, "#include <sys/cdefs.h>\n\n");
1628 (void)fprintf(cfg, "#include \"opt_config.h\"\n");
1629 (void)fprintf(cfg, "\n");
1630 (void)fprintf(cfg, "/*\n");
1631 (void)fprintf(cfg, " * Add either (or both) of\n");
1632 (void)fprintf(cfg, " *\n");
1633 (void)fprintf(cfg, " *\toptions %s\n", LOGCONFIG_LARGE);
1634 (void)fprintf(cfg, " *\toptions %s\n", LOGCONFIG_SMALL);
1635 (void)fprintf(cfg, " *\n");
1636 (void)fprintf(cfg,
1637 " * to your kernel config file to embed it in the resulting\n");
1638 (void)fprintf(cfg,
1639 " * kernel. The latter option does not include files that are\n");
1640 (void)fprintf(cfg,
1641 " * included (recursively) by your config file. The embedded\n");
1642 (void)fprintf(cfg,
1643 " * data be extracted by using the command:\n");
1644 (void)fprintf(cfg, " *\n");
1645 (void)fprintf(cfg,
1646 " *\tstrings netbsd | sed -n 's/^_CFG_//p' | unvis\n");
1647 (void)fprintf(cfg, " */\n");
1648 (void)fprintf(cfg, "\n");
1649 (void)fprintf(cfg, "#ifdef CONFIG_FILE\n");
1650 (void)fprintf(cfg, "#if defined(%s) || defined(%s)\n\n",
1651 LOGCONFIG_LARGE, LOGCONFIG_SMALL);
1652 (void)fprintf(cfg, "static const char config[] __used =\n\n");
1653
1654 (void)fprintf(cfg, "#ifdef %s\n\n", LOGCONFIG_LARGE);
1655 (void)fprintf(cfg, "\"_CFG_### START CONFIG FILE \\\"%s\\\"\\n\"\n\n",
1656 conffile);
1657 (void)fprintf(cfg, "#endif /* %s */\n\n", LOGCONFIG_LARGE);
1658
1659 logconfig_include(yyin, NULL);
1660
1661 (void)fprintf(cfg, "#ifdef %s\n\n", LOGCONFIG_LARGE);
1662 (void)fprintf(cfg, "\"_CFG_### END CONFIG FILE \\\"%s\\\"\\n\"\n",
1663 conffile);
1664
1665 rewind(yyin);
1666 }
1667
1668 void
logconfig_include(FILE * cf,const char * filename)1669 logconfig_include(FILE *cf, const char *filename)
1670 {
1671 char line[1024], in[2048], *out;
1672 struct stat st;
1673 int missingeol;
1674
1675 if (!cfg)
1676 return;
1677
1678 missingeol = 0;
1679 if (fstat(fileno(cf), &st) == -1)
1680 return;
1681 if (cfgtime < st.st_mtime)
1682 cfgtime = st.st_mtime;
1683
1684 if (filename)
1685 (void)fprintf(cfg,
1686 "\"_CFG_### (included from \\\"%s\\\")\\n\"\n",
1687 filename);
1688 while (fgets(line, sizeof(line), cf) != NULL) {
1689 missingeol = 1;
1690 (void)fprintf(cfg, "\"_CFG_");
1691 if (filename)
1692 (void)fprintf(cfg, "###> ");
1693 strvis(in, line, VIS_TAB);
1694 for (out = in; *out; out++)
1695 switch (*out) {
1696 case '\n':
1697 (void)fprintf(cfg, "\\n\"\n");
1698 missingeol = 0;
1699 break;
1700 case '"': case '\\':
1701 (void)fputc('\\', cfg);
1702 /* FALLTHROUGH */
1703 default:
1704 (void)fputc(*out, cfg);
1705 break;
1706 }
1707 }
1708 if (missingeol) {
1709 (void)fprintf(cfg, "\\n\"\n");
1710 warnx("%s: newline missing at EOF",
1711 filename != NULL ? filename : conffile);
1712 }
1713 if (filename)
1714 (void)fprintf(cfg, "\"_CFG_### (end include \\\"%s\\\")\\n\"\n",
1715 filename);
1716
1717 rewind(cf);
1718 }
1719
1720 void
logconfig_end(void)1721 logconfig_end(void)
1722 {
1723 char line[1024];
1724 FILE *fp;
1725 struct stat st;
1726
1727 if (!cfg)
1728 return;
1729
1730 (void)fprintf(cfg, "#endif /* %s */\n", LOGCONFIG_LARGE);
1731 (void)fprintf(cfg, ";\n");
1732 (void)fprintf(cfg, "#endif /* %s || %s */\n",
1733 LOGCONFIG_LARGE, LOGCONFIG_SMALL);
1734 (void)fprintf(cfg, "#endif /* CONFIG_FILE */\n");
1735 fflush(cfg);
1736 if (ferror(cfg))
1737 err(EXIT_FAILURE, "write to temporary file for config.h failed");
1738 rewind(cfg);
1739
1740 if (stat("config_file.h", &st) != -1) {
1741 if (cfgtime < st.st_mtime) {
1742 fclose(cfg);
1743 return;
1744 }
1745 }
1746
1747 fp = fopen("config_file.h", "w");
1748 if (!fp)
1749 err(EXIT_FAILURE, "cannot open \"config.h\"");
1750
1751 while (fgets(line, sizeof(line), cfg) != NULL)
1752 fputs(line, fp);
1753 fflush(fp);
1754 if (ferror(fp))
1755 err(EXIT_FAILURE, "write to \"config.h\" failed");
1756 fclose(fp);
1757 fclose(cfg);
1758 }
1759
1760 const char *
strtolower(const char * name)1761 strtolower(const char *name)
1762 {
1763 const char *n;
1764 char *p, low[500];
1765 char c;
1766
1767 for (n = name, p = low; (c = *n) != '\0'; n++)
1768 *p++ = (char)(isupper((u_char)c) ? tolower((u_char)c) : c);
1769 *p = '\0';
1770 return (intern(low));
1771 }
1772
1773 static int
is_elf(const char * file)1774 is_elf(const char *file)
1775 {
1776 int kernel;
1777 char hdr[4];
1778
1779 kernel = open(file, O_RDONLY);
1780 if (kernel == -1)
1781 err(EXIT_FAILURE, "cannot open %s", file);
1782 if (read(kernel, hdr, 4) != 4)
1783 err(EXIT_FAILURE, "Cannot read from %s", file);
1784 (void)close(kernel);
1785
1786 return memcmp("\177ELF", hdr, 4) == 0 ? 1 : 0;
1787 }
1788
1789 static int
extract_config(const char * kname,const char * cname,int cfd)1790 extract_config(const char *kname, const char *cname, int cfd)
1791 {
1792 char *ptr;
1793 void *base;
1794 int found, kfd;
1795 struct stat st;
1796 off_t i;
1797
1798 found = 0;
1799
1800 /* mmap(2) binary kernel */
1801 kfd = open(conffile, O_RDONLY);
1802 if (kfd == -1)
1803 err(EXIT_FAILURE, "cannot open %s", kname);
1804 if (fstat(kfd, &st) == -1)
1805 err(EXIT_FAILURE, "cannot stat %s", kname);
1806 base = mmap(0, (size_t)st.st_size, PROT_READ, MAP_FILE | MAP_SHARED,
1807 kfd, 0);
1808 if (base == MAP_FAILED)
1809 err(EXIT_FAILURE, "cannot mmap %s", kname);
1810 ptr = base;
1811
1812 /* Scan mmap(2)'ed region, extracting kernel configuration */
1813 for (i = 0; i < st.st_size; i++) {
1814 if ((*ptr == '_') && (st.st_size - i > 5) && memcmp(ptr,
1815 "_CFG_", 5) == 0) {
1816 /* Line found */
1817 char *oldptr, line[LINE_MAX + 1], uline[LINE_MAX + 1];
1818 int j;
1819
1820 found = 1;
1821
1822 oldptr = (ptr += 5);
1823 while (*ptr != '\n' && *ptr != '\0')
1824 ptr++;
1825 if (ptr - oldptr > LINE_MAX)
1826 errx(EXIT_FAILURE, "line too long");
1827 i += ptr - oldptr + 5;
1828 (void)memcpy(line, oldptr, (size_t)(ptr - oldptr));
1829 line[ptr - oldptr] = '\0';
1830 j = strunvis(uline, line);
1831 if (j == -1)
1832 errx(EXIT_FAILURE, "unvis: invalid "
1833 "encoded sequence");
1834 uline[j] = '\n';
1835 if (write(cfd, uline, (size_t)j + 1) == -1)
1836 err(EXIT_FAILURE, "cannot write to %s", cname);
1837 } else
1838 ptr++;
1839 }
1840
1841 (void)close(kfd);
1842 (void)munmap(base, (size_t)st.st_size);
1843
1844 return found;
1845 }
1846
1847 struct dhdi_params {
1848 struct devbase *d;
1849 int unit;
1850 int level;
1851 };
1852
1853 static int
devbase_has_dead_instances(const char * key,void * value,void * aux)1854 devbase_has_dead_instances(const char *key, void *value, void *aux)
1855 {
1856 struct devi *i;
1857 struct dhdi_params *dhdi = aux;
1858
1859 for (i = value; i != NULL; i = i->i_alias)
1860 if (i->i_base == dhdi->d &&
1861 (dhdi->unit == WILD || dhdi->unit == i->i_unit ||
1862 i->i_unit == STAR) &&
1863 i->i_level >= dhdi->level)
1864 return 1;
1865 return 0;
1866 }
1867
1868 /*
1869 * This is almost the same as devbase_has_instances, except it
1870 * may have special considerations regarding ignored instances.
1871 */
1872
1873 static int
devbase_has_any_instance(struct devbase * dev,int unit,int state,int level)1874 devbase_has_any_instance(struct devbase *dev, int unit, int state, int level)
1875 {
1876 struct deva *da;
1877 struct devi *i;
1878
1879 if (dev->d_ispseudo) {
1880 if (dev->d_ihead != NULL)
1881 return 1;
1882 else if (state != DEVI_IGNORED)
1883 return 0;
1884 if ((i = ht_lookup(deaddevitab, dev->d_name)) == NULL)
1885 return 0;
1886 return (i->i_level >= level);
1887 }
1888
1889 for (da = dev->d_ahead; da != NULL; da = da->d_bsame)
1890 for (i = da->d_ihead; i != NULL; i = i->i_asame)
1891 if ((i->i_active == DEVI_ACTIVE ||
1892 i->i_active == state) &&
1893 (unit == WILD || unit == i->i_unit ||
1894 i->i_unit == STAR))
1895 return 1;
1896
1897 if (state == DEVI_IGNORED) {
1898 struct dhdi_params dhdi = { dev, unit, level };
1899 /* also check dead devices */
1900 return ht_enumerate(deaddevitab, devbase_has_dead_instances,
1901 &dhdi);
1902 }
1903
1904 return 0;
1905 }
1906
1907 /*
1908 * check_dead_devi(), used with ht_enumerate, checks if any of the removed
1909 * device instances would have been a valid instance considering the devbase,
1910 * the parent device and the interface attribute.
1911 *
1912 * In other words, for a non-active device, it checks if children would be
1913 * actual orphans or the result of a negative statement in the config file.
1914 */
1915
1916 struct cdd_params {
1917 struct devbase *d;
1918 struct attr *at;
1919 struct devbase *parent;
1920 };
1921
1922 static int
check_dead_devi(const char * key,void * value,void * aux)1923 check_dead_devi(const char *key, void *value, void *aux)
1924 {
1925 struct cdd_params *cdd = aux;
1926 struct devi *i = value;
1927 struct pspec *p;
1928
1929 if (i->i_base != cdd->d)
1930 return 0;
1931
1932 for (; i != NULL; i = i->i_alias) {
1933 p = i->i_pspec;
1934 if ((p == NULL && cdd->at == NULL) ||
1935 (p != NULL && p->p_iattr == cdd->at &&
1936 (p->p_atdev == NULL || p->p_atdev == cdd->parent))) {
1937 if (p != NULL &&
1938 !devbase_has_any_instance(cdd->parent, p->p_atunit,
1939 DEVI_IGNORED, i->i_level))
1940 return 0;
1941 else
1942 return 1;
1943 }
1944 }
1945 return 0;
1946 }
1947
1948 static struct devbase root;
1949
1950 static int
addlevelparent(struct devbase * d,struct devbase * parent)1951 addlevelparent(struct devbase *d, struct devbase *parent)
1952 {
1953 struct devbase *p;
1954
1955 if (d == parent) {
1956 if (d->d_level > 1)
1957 return 0;
1958 return 1;
1959 }
1960
1961 if (d->d_levelparent) {
1962 if (d->d_level > 1)
1963 return 0;
1964 return 1;
1965 }
1966
1967 for (p = parent; p != NULL; p = p->d_levelparent)
1968 if (d == p && d->d_level > 1)
1969 return 0;
1970 d->d_levelparent = p ? p : &root;
1971 d->d_level++;
1972 return 1;
1973 }
1974
1975 static void
do_kill_orphans(struct devbase * d,struct attr * at,struct devbase * parent,int state)1976 do_kill_orphans(struct devbase *d, struct attr *at, struct devbase *parent,
1977 int state)
1978 {
1979 struct nvlist *nv1;
1980 struct attrlist *al;
1981 struct attr *a;
1982 struct devi *i, *j = NULL;
1983 struct pspec *p;
1984 int active = 0;
1985
1986 if (!addlevelparent(d, parent))
1987 return;
1988
1989 /*
1990 * A pseudo-device will always attach at root, and if it has an
1991 * instance (it cannot have more than one), it is enough to consider
1992 * it active, as there is no real attachment.
1993 *
1994 * A pseudo device can never be marked DEVI_IGNORED.
1995 */
1996 if (d->d_ispseudo) {
1997 if (d->d_ihead != NULL)
1998 d->d_ihead->i_active = active = DEVI_ACTIVE;
1999 else {
2000 if (ht_lookup(deaddevitab, d->d_name) != NULL)
2001 active = DEVI_IGNORED;
2002 else
2003 return;
2004 }
2005 } else {
2006 int seen = 0;
2007 int changed = 0;
2008
2009 for (i = d->d_ihead; i != NULL; i = i->i_bsame) {
2010 for (j = i; j != NULL; j = j->i_alias) {
2011 p = j->i_pspec;
2012 if ((p == NULL && at == NULL) ||
2013 (p != NULL && p->p_iattr == at &&
2014 (p->p_atdev == NULL ||
2015 p->p_atdev == parent))) {
2016 if (p != NULL &&
2017 !devbase_has_any_instance(parent,
2018 p->p_atunit, state, j->i_level))
2019 continue;
2020 /*
2021 * There are Fry-like devices which can
2022 * be their own grand-parent (or even
2023 * parent, like uhub). We don't want
2024 * to loop, so if we've already reached
2025 * an instance for one reason or
2026 * another, stop there.
2027 */
2028 if (j->i_active == DEVI_ACTIVE ||
2029 j->i_active == state) {
2030 /*
2031 * Device has already been
2032 * seen. However it might
2033 * have siblings who still
2034 * have to be activated or
2035 * orphaned.
2036 */
2037 seen = 1;
2038 continue;
2039 }
2040 changed |= j->i_active != state;
2041 j->i_active = active = state;
2042 if (p != NULL) {
2043 if (state == DEVI_ACTIVE ||
2044 --p->p_ref == 0)
2045 p->p_active = state;
2046 }
2047 if (state == DEVI_IGNORED) {
2048 CFGDBG(5,
2049 "`%s' at '%s' ignored",
2050 d->d_name, parent ?
2051 parent->d_name : "(root)");
2052 }
2053 }
2054 }
2055 }
2056 /*
2057 * If we've been there but have made no change, stop.
2058 */
2059 if (seen && active != DEVI_ACTIVE)
2060 goto out;
2061 if (active != DEVI_ACTIVE) {
2062 struct cdd_params cdd = { d, at, parent };
2063 /* Look for a matching dead devi */
2064 if (ht_enumerate(deaddevitab, check_dead_devi, &cdd) &&
2065 d != parent) {
2066 /*
2067 * That device had its instances removed.
2068 * Continue the loop marking descendants
2069 * with DEVI_IGNORED instead of DEVI_ACTIVE.
2070 *
2071 * There is one special case for devices that
2072 * are their own parent: if that instance is
2073 * removed (e.g., no uhub* at uhub?), we don't
2074 * have to continue looping.
2075 */
2076 active = DEVI_IGNORED;
2077 CFGDBG(5, "`%s' at '%s' ignored", d->d_name,
2078 parent ? parent->d_name : "(root)");
2079
2080 } else if (!changed)
2081 goto out;
2082 }
2083 }
2084
2085 for (al = d->d_attrs; al != NULL; al = al->al_next) {
2086 a = al->al_this;
2087 for (nv1 = a->a_devs; nv1 != NULL; nv1 = nv1->nv_next) {
2088 do_kill_orphans(nv1->nv_ptr, a, d, active);
2089 }
2090 }
2091 out:
2092 d->d_levelparent = NULL;
2093 d->d_level--;
2094 }
2095
2096 static int
2097 /*ARGSUSED*/
kill_orphans_cb(const char * key,void * value,void * aux)2098 kill_orphans_cb(const char *key, void *value, void *aux)
2099 {
2100 do_kill_orphans((struct devbase *)value, NULL, NULL, DEVI_ACTIVE);
2101 return 0;
2102 }
2103
2104 static void
kill_orphans(void)2105 kill_orphans(void)
2106 {
2107 ht_enumerate(devroottab, kill_orphans_cb, NULL);
2108 }
2109
2110 static void
add_makeopt(const char * opt)2111 add_makeopt(const char *opt)
2112 {
2113 struct nvlist *p;
2114 char *buf = estrdup(opt);
2115 char *eq = strchr(buf, '=');
2116
2117 if (!eq)
2118 errx(EXIT_FAILURE, "-D %s is not in var=value format", opt);
2119
2120 *eq = 0;
2121 p = newnv(estrdup(buf), estrdup(eq+1), NULL, 0, NULL);
2122 free(buf);
2123 p->nv_next = cmdlinedefs;
2124 cmdlinedefs = p;
2125 }
2126
2127 static void
remove_makeopt(const char * opt)2128 remove_makeopt(const char *opt)
2129 {
2130 struct nvlist *p;
2131
2132 p = newnv(estrdup(opt), NULL, NULL, 0, NULL);
2133 p->nv_next = cmdlineundefs;
2134 cmdlineundefs = p;
2135 }
2136
2137 static void
handle_cmdline_makeoptions(void)2138 handle_cmdline_makeoptions(void)
2139 {
2140 struct nvlist *p, *n;
2141
2142 handling_cmdlineopts = 1;
2143 for (p = cmdlineundefs; p; p = n) {
2144 n = p->nv_next;
2145 delmkoption(intern(p->nv_name), 0);
2146 free(__UNCONST(p->nv_name));
2147 nvfree(p);
2148 }
2149 for (p = cmdlinedefs; p; p = n) {
2150 const char *name = intern(p->nv_name);
2151
2152 n = p->nv_next;
2153 delmkoption(name, 0);
2154 addmkoption(name, intern(p->nv_str));
2155 free(__UNCONST(p->nv_name));
2156 free(__UNCONST(p->nv_str));
2157
2158 nvfree(p);
2159 }
2160 handling_cmdlineopts = 0;
2161 }
2162