1 /* $NetBSD: main.c,v 1.35 2009/03/13 18:24:41 cube Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
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.
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.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
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.
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
40 * from: @(#)main.c 8.1 (Berkeley) 6/6/93
43 #if HAVE_NBTOOL_CONFIG_H
44 #include "nbtool_config.h"
47 #ifndef MAKE_BOOTSTRAP
48 #include <sys/cdefs.h>
49 #define COPYRIGHT(x) __COPYRIGHT(x)
51 #define COPYRIGHT(x) static const char copyright[] = x
55 COPYRIGHT("@(#) Copyright (c) 1992, 1993\
56 The Regents of the University of California. All rights reserved.");
59 #include <sys/types.h>
61 #include <sys/param.h>
83 int vflag
; /* verbose output */
84 int Pflag
; /* pack locators */
85 int Lflag
; /* lint config generation */
89 #ifndef MAKE_BOOTSTRAP
93 static struct hashtab
*obsopttab
;
94 static struct hashtab
*mkopttab
;
95 static struct nvlist
**nextopt
;
96 static struct nvlist
**nextmkopt
;
97 static struct nvlist
**nextappmkopt
;
98 static struct nvlist
**nextcndmkopt
;
99 static struct nvlist
**nextfsopt
;
101 static void usage(void) __dead
;
102 static void dependopts(void);
103 static void do_depend(struct nvlist
*);
104 static void stop(void);
105 static int do_option(struct hashtab
*, struct nvlist
***,
106 const char *, const char *, const char *);
107 static int undo_option(struct hashtab
*, struct nvlist
**,
108 struct nvlist
***, const char *, const char *);
109 static int crosscheck(void);
110 static int badstar(void);
111 int main(int, char **);
112 static int mksymlinks(void);
113 static int mkident(void);
114 static int devbase_has_dead_instances(const char *, void *, void *);
115 static int devbase_has_any_instance(struct devbase
*, int, int, int);
116 static int check_dead_devi(const char *, void *, void *);
117 static void kill_orphans(void);
118 static void do_kill_orphans(struct devbase
*, struct attr
*,
119 struct devbase
*, int);
120 static int kill_orphans_cb(const char *, void *, void *);
121 static int cfcrosscheck(struct config
*, const char *, struct nvlist
*);
122 void defopt(struct hashtab
*ht
, const char *fname
,
123 struct nvlist
*opts
, struct nvlist
*deps
, int obs
);
125 #define LOGCONFIG_LARGE "INCLUDE_CONFIG_FILE"
126 #define LOGCONFIG_SMALL "INCLUDE_JUST_CONFIG"
128 static void logconfig_start(void);
129 static void logconfig_end(void);
131 static time_t cfgtime
;
133 static int is_elf(const char *);
134 static int extract_config(const char *, const char *, int);
136 int badfilename(const char *fname
);
138 const char *progname
;
141 main(int argc
, char **argv
)
143 char *p
, cname
[PATH_MAX
];
144 const char *last_component
;
145 int pflag
, xflag
, ch
, removeit
;
147 setprogname(argv
[0]);
151 while ((ch
= getopt(argc
, argv
, "DLPgpvb:s:x")) != -1) {
154 #ifndef MAKE_BOOTSTRAP
170 * In addition to DEBUG, you probably wanted to
171 * set "options KGDB" and maybe others. We could
172 * do that for you, but you really should just
173 * put them in the config file.
175 warnx("-g is obsolete (use makeoptions DEBUG=\"-g\")");
181 * Essentially the same as makeoptions PROF="-pg",
182 * but also changes the path from ../../compile/FOO
183 * to ../../compile/FOO.PROF; i.e., compile a
184 * profiling kernel based on a typical "regular"
187 * Note that if you always want profiling, you
188 * can (and should) use a "makeoptions" line.
221 if (xflag
&& (builddir
!= NULL
|| srcdir
!= NULL
|| Pflag
|| pflag
||
223 errx(EXIT_FAILURE
, "-x must be used alone");
224 if (Lflag
&& (builddir
!= NULL
|| Pflag
|| pflag
))
225 errx(EXIT_FAILURE
, "-L can only be used with -s and -v");
229 conffile
= (argc
== 1) ? argv
[0] : _PATH_UNIX
;
232 errx(EXIT_FAILURE
, "no kernel supplied");
234 if (!is_elf(conffile
))
235 errx(EXIT_FAILURE
, "%s: not a binary kernel",
237 if (!extract_config(conffile
, "stdout", STDOUT_FILENO
))
238 errx(EXIT_FAILURE
, "%s does not contain embedded "
239 "configuration data", conffile
);
243 conffile
= (argc
== 1) ? argv
[0] : "CONFIG";
244 if (firstfile(conffile
)) {
245 err(EXIT_FAILURE
, "Cannot read `%s'", conffile
);
258 devbasetab
= ht_new();
259 devroottab
= ht_new();
262 deaddevitab
= ht_new();
263 selecttab
= ht_new();
264 needcnttab
= ht_new();
269 defopttab
= ht_new();
270 defparamtab
= ht_new();
271 defoptlint
= ht_new();
272 defflagtab
= ht_new();
273 optfiletab
= ht_new();
274 obsopttab
= ht_new();
280 nextmkopt
= &mkoptions
;
281 nextappmkopt
= &appmkoptions
;
282 nextcndmkopt
= &condmkoptions
;
283 nextfsopt
= &fsoptions
;
286 * Handle profiling (must do this before we try to create any
289 last_component
= strrchr(conffile
, '/');
290 last_component
= (last_component
) ? last_component
+ 1 : conffile
;
292 p
= emalloc(strlen(last_component
) + 17);
293 (void)sprintf(p
, "../compile/%s.PROF", last_component
);
294 (void)addmkoption(intern("PROF"), "-pg");
295 (void)addoption(intern("GPROF"), NULL
);
297 p
= emalloc(strlen(last_component
) + 13);
298 (void)sprintf(p
, "../compile/%s", last_component
);
300 defbuilddir
= (argc
== 0) ? "." : p
;
303 char resolvedname
[MAXPATHLEN
];
305 if (realpath(conffile
, resolvedname
) == NULL
)
306 err(EXIT_FAILURE
, "realpath(%s)", conffile
);
311 printf("include \"%s\"\n", resolvedname
);
321 if (is_elf(conffile
)) {
325 if (builddir
== NULL
)
326 errx(EXIT_FAILURE
, "Build directory must be specified "
327 "with binary kernels");
329 /* Open temporary configuration file */
330 tmpdir
= getenv("TMPDIR");
333 snprintf(cname
, sizeof(cname
), "%s/config.tmp.XXXXXX", tmpdir
);
334 cfd
= mkstemp(cname
);
336 err(EXIT_FAILURE
, "Cannot create `%s'", cname
);
338 printf("Using configuration data embedded in kernel...\n");
339 if (!extract_config(conffile
, cname
, cfd
)) {
341 errx(EXIT_FAILURE
, "%s does not contain embedded "
342 "configuration data", conffile
);
351 * Parse config file (including machine definitions).
362 * Detect and properly ignore orphaned devices
367 * Select devices and pseudo devices and their attributes
373 * Deal with option dependencies.
378 * Fix (as in `set firmly in place') files.
384 * Fix objects and libraries.
396 * Perform cross-checking.
400 (void)printf("maxusers not specified; %d assumed\n",
402 maxusers
= defmaxusers
;
404 warnx("need \"maxusers\" line");
408 if (crosscheck() || errors
)
412 * Squeeze things down and finish cross-checks (STAR checks must
413 * run after packing).
420 * Ready to go. Build all the various files.
422 if (mksymlinks() || mkmakefile() || mkheaders() || mkswap() ||
423 mkioconf() || (do_devsw
? mkdevsw() : 0) || mkident() || errors
)
425 (void)printf("Build directory is %s\n", builddir
);
426 (void)printf("Don't forget to run \"make depend\"\n");
433 (void)fprintf(stderr
, "Usage: %s [-Ppv] [-s srcdir] [-b builddir] "
434 "[config-file]\n\t%s -x [kernel-file]\n"
435 "\t%s -L [-v] [-s srcdir] [config-file]\n",
436 getprogname(), getprogname(), getprogname());
441 * Set any options that are implied by other options.
446 struct nvlist
*nv
, *opt
;
448 for (nv
= options
; nv
!= NULL
; nv
= nv
->nv_next
) {
449 if ((opt
= find_declared_option(nv
->nv_name
)) != NULL
) {
450 for (opt
= opt
->nv_ptr
; opt
!= NULL
;
451 opt
= opt
->nv_next
) {
457 for (nv
= fsoptions
; nv
!= NULL
; nv
= nv
->nv_next
) {
458 if ((opt
= find_declared_option(nv
->nv_name
)) != NULL
) {
459 for (opt
= opt
->nv_ptr
; opt
!= NULL
;
460 opt
= opt
->nv_next
) {
468 do_depend(struct nvlist
*nv
)
470 struct nvlist
*nextnv
;
473 if (nv
!= NULL
&& (nv
->nv_flags
& NV_DEPENDED
) == 0) {
474 nv
->nv_flags
|= NV_DEPENDED
;
476 * If the dependency is an attribute, then just add
477 * it to the selecttab.
479 if ((a
= ht_lookup(attrtab
, nv
->nv_name
)) != NULL
) {
481 panic("do_depend(%s): dep `%s' is an iattr",
482 nv
->nv_name
, a
->a_name
);
483 expandattr(a
, selectattr
);
485 if (ht_lookup(opttab
, nv
->nv_name
) == NULL
)
486 addoption(nv
->nv_name
, NULL
);
488 find_declared_option(nv
->nv_name
)) != NULL
)
489 do_depend(nextnv
->nv_ptr
);
495 recreate(const char *p
, const char *q
)
499 if ((ret
= unlink(q
)) == -1 && errno
!= ENOENT
)
500 warn("unlink(%s)\n", q
);
501 if ((ret
= symlink(p
, q
)) == -1)
502 warn("symlink(%s -> %s)", q
, p
);
507 * Make a symlink for "machine" so that "#include <machine/foo.h>" works,
508 * and for the machine's CPU architecture, so that works as well.
514 char *p
, buf
[MAXPATHLEN
];
518 snprintf(buf
, sizeof(buf
), "arch/%s/include", machine
);
520 ret
= recreate(p
, "machine");
523 if (machinearch
!= NULL
) {
524 snprintf(buf
, sizeof(buf
), "arch/%s/include", machinearch
);
528 p
= estrdup("machine");
532 ret
= recreate(p
, q
);
535 for (nv
= machinesubarches
; nv
!= NULL
; nv
= nv
->nv_next
) {
537 snprintf(buf
, sizeof(buf
), "arch/%s/include", q
);
539 ret
= recreate(p
, q
);
549 (void)fprintf(stderr
, "*** Stop.\n");
554 add_dependencies(struct nvlist
*nv
, struct nvlist
*deps
)
559 /* Use nv_ptr to link any other options that are implied. */
561 for (dep
= deps
; dep
!= NULL
; dep
= dep
->nv_next
) {
563 * If the dependency is an attribute, it must not
564 * be an interface attribute. Otherwise, it must
565 * be a previously declared option.
567 if ((a
= ht_lookup(attrtab
, dep
->nv_name
)) != NULL
) {
569 cfgerror("option `%s' dependency `%s' "
570 "is an interface attribute",
571 nv
->nv_name
, a
->a_name
);
572 } else if (OPT_OBSOLETE(dep
->nv_name
)) {
573 cfgerror("option `%s' dependency `%s' "
574 "is obsolete", nv
->nv_name
, dep
->nv_name
);
575 } else if (find_declared_option(dep
->nv_name
) == NULL
) {
576 cfgerror("option `%s' dependency `%s' "
577 "is an unknown option",
578 nv
->nv_name
, dep
->nv_name
);
584 * Define one or more file systems. If file system options file name is
585 * specified, a preprocessor #define for that file system will be placed
586 * in that file. In this case, only one file system may be specified.
587 * Otherwise, no preprocessor #defines will be generated.
590 deffilesystem(const char *fname
, struct nvlist
*fses
, struct nvlist
*deps
)
595 * Mark these options as ones to skip when creating the Makefile.
597 for (nv
= fses
; nv
!= NULL
; nv
= nv
->nv_next
) {
598 if (DEFINED_OPTION(nv
->nv_name
)) {
599 cfgerror("file system or option `%s' already defined",
605 * Also mark it as a valid file system, which may be
606 * used in "file-system" directives in the config
609 if (ht_insert(deffstab
, nv
->nv_name
, nv
))
610 panic("file system `%s' already in table?!",
615 * Only one file system allowed in this case.
617 if (nv
->nv_next
!= NULL
) {
618 cfgerror("only one file system per option "
619 "file may be specified");
623 if (ht_insert(optfiletab
, fname
, nv
)) {
624 cfgerror("option file `%s' already exists",
630 add_dependencies(nv
, deps
);
635 * Sanity check a file name.
638 badfilename(const char *fname
)
643 * We're putting multiple options into one file. Sanity
644 * check the file name.
646 if (strchr(fname
, '/') != NULL
) {
647 cfgerror("option file name contains a `/'");
650 if ((n
= strrchr(fname
, '.')) == NULL
|| strcmp(n
, ".h") != 0) {
651 cfgerror("option file name does not end in `.h'");
659 * Search for a defined option (defopt, filesystem, etc), and if found,
660 * return the option's struct nvlist.
663 find_declared_option(const char *name
)
665 struct nvlist
*option
= NULL
;
667 if ((option
= ht_lookup(defopttab
, name
)) != NULL
||
668 (option
= ht_lookup(defparamtab
, name
)) != NULL
||
669 (option
= ht_lookup(defflagtab
, name
)) != NULL
||
670 (option
= ht_lookup(deffstab
, name
)) != NULL
) {
679 * Define one or more standard options. If an option file name is specified,
680 * place all options in one file with the specified name. Otherwise, create
681 * an option file for each option.
682 * record the option information in the specified table.
685 defopt(struct hashtab
*ht
, const char *fname
, struct nvlist
*opts
,
686 struct nvlist
*deps
, int obs
)
688 struct nvlist
*nv
, *nextnv
, *oldnv
;
692 if (fname
!= NULL
&& badfilename(fname
)) {
697 * Mark these options as ones to skip when creating the Makefile.
699 for (nv
= opts
; nv
!= NULL
; nv
= nextnv
) {
700 nextnv
= nv
->nv_next
;
702 if (*(nv
->nv_name
) == '\0') {
704 panic("invalid option chain");
706 * If an entry already exists, then we are about to
707 * complain, so no worry.
709 (void) ht_insert(defoptlint
, nextnv
->nv_name
,
712 nextnv
= nextnv
->nv_next
;
715 /* An option name can be declared at most once. */
716 if (DEFINED_OPTION(nv
->nv_name
)) {
717 cfgerror("file system or option `%s' already defined",
722 if (ht_insert(ht
, nv
->nv_name
, nv
)) {
723 cfgerror("file system or option `%s' already defined",
730 * Each option will be going into its own file.
731 * Convert the option name to lower case. This
732 * lower case name will be used as the option
735 (void) snprintf(buf
, sizeof(buf
), "opt_%s.h",
736 strtolower(nv
->nv_name
));
742 add_dependencies(nv
, deps
);
745 * Remove this option from the parameter list before adding
746 * it to the list associated with this option file.
751 * Flag as obsolete, if requested.
754 nv
->nv_flags
|= NV_OBSOLETE
;
755 (void)ht_insert(obsopttab
, nv
->nv_name
, nv
);
759 * Add this option file if we haven't seen it yet.
760 * Otherwise, append to the list of options already
761 * associated with this file.
763 if ((oldnv
= ht_lookup(optfiletab
, name
)) == NULL
) {
764 (void)ht_insert(optfiletab
, name
, nv
);
766 while (oldnv
->nv_next
!= NULL
)
767 oldnv
= oldnv
->nv_next
;
774 * Define one or more standard options. If an option file name is specified,
775 * place all options in one file with the specified name. Otherwise, create
776 * an option file for each option.
779 defoption(const char *fname
, struct nvlist
*opts
, struct nvlist
*deps
)
782 cfgwarn("The use of `defopt' is deprecated");
783 defopt(defopttab
, fname
, opts
, deps
, 0);
788 * Define an option for which a value is required.
791 defparam(const char *fname
, struct nvlist
*opts
, struct nvlist
*deps
, int obs
)
794 defopt(defparamtab
, fname
, opts
, deps
, obs
);
798 * Define an option which must not have a value, and which
799 * emits a "needs-flag" style output.
802 defflag(const char *fname
, struct nvlist
*opts
, struct nvlist
*deps
, int obs
)
805 defopt(defflagtab
, fname
, opts
, deps
, obs
);
810 * Add an option from "options FOO". Note that this selects things that
811 * are "optional foo".
814 addoption(const char *name
, const char *value
)
817 int is_fs
, is_param
, is_flag
, is_undecl
, is_obs
;
820 * Figure out how this option was declared (if at all.)
821 * XXX should use "params" and "flags" in config.
822 * XXX crying out for a type field in a unified hashtab.
824 is_fs
= OPT_FSOPT(name
);
825 is_param
= OPT_DEFPARAM(name
);
826 is_flag
= OPT_DEFFLAG(name
);
827 is_obs
= OPT_OBSOLETE(name
);
828 is_undecl
= !DEFINED_OPTION(name
);
830 /* Warn and pretend the user had not selected the option */
832 cfgwarn("obsolete option `%s' will be ignored", name
);
836 /* Make sure this is not a defined file system. */
838 cfgerror("`%s' is a defined file system", name
);
841 /* A defparam must have a value */
842 if (is_param
&& value
== NULL
) {
843 cfgerror("option `%s' must have a value", name
);
846 /* A defflag must not have a value */
847 if (is_flag
&& value
!= NULL
) {
848 cfgerror("option `%s' must not have a value", name
);
852 if (is_undecl
&& vflag
) {
853 cfgwarn("undeclared option `%s' added to IDENT", name
);
856 if (do_option(opttab
, &nextopt
, name
, value
, "options"))
859 /* make lowercase, then add to select table */
860 n
= strtolower(name
);
861 (void)ht_insert(selecttab
, n
, (void *)__UNCONST(n
));
865 deloption(const char *name
)
868 if (undo_option(opttab
, &options
, &nextopt
, name
, "options"))
870 if (undo_option(selecttab
, NULL
, NULL
, strtolower(name
), "options"))
875 * Add a file system option. This routine simply inserts the name into
876 * a list of valid file systems, which is used to validate the root
877 * file system type. The name is then treated like a standard option.
880 addfsoption(const char *name
)
884 /* Make sure this is a defined file system. */
885 if (!OPT_FSOPT(name
)) {
886 cfgerror("`%s' is not a defined file system", name
);
891 * Convert to lower case. This will be used in the select
892 * table, to verify root file systems.
894 n
= strtolower(name
);
896 if (do_option(fsopttab
, &nextfsopt
, name
, n
, "file-system"))
899 /* Add to select table. */
900 (void)ht_insert(selecttab
, n
, __UNCONST(n
));
904 delfsoption(const char *name
)
908 n
= strtolower(name
);
909 if (undo_option(fsopttab
, &fsoptions
, &nextfsopt
, name
, "file-system"))
911 if (undo_option(selecttab
, NULL
, NULL
, n
, "file-system"))
916 * Add a "make" option.
919 addmkoption(const char *name
, const char *value
)
922 (void)do_option(mkopttab
, &nextmkopt
, name
, value
, "makeoptions");
926 delmkoption(const char *name
)
929 (void)undo_option(mkopttab
, &mkoptions
, &nextmkopt
, name
,
934 * Add an appending "make" option.
937 appendmkoption(const char *name
, const char *value
)
941 nv
= newnv(name
, value
, NULL
, 0, NULL
);
943 nextappmkopt
= &nv
->nv_next
;
947 * Add a conditional appending "make" option.
950 appendcondmkoption(struct nvlist
*cnd
, const char *name
, const char *value
)
954 nv
= newnv(name
, value
, cnd
, 0, NULL
);
956 nextcndmkopt
= &nv
->nv_next
;
960 * Add a name=value pair to an option list. The value may be NULL.
963 do_option(struct hashtab
*ht
, struct nvlist
***nppp
, const char *name
,
964 const char *value
, const char *type
)
968 /* assume it will work */
969 nv
= newnv(name
, value
, NULL
, 0, NULL
);
970 if (ht_insert(ht
, name
, nv
) == 0) {
972 *nppp
= &nv
->nv_next
;
976 /* oops, already got that option */
978 if ((nv
= ht_lookup(ht
, name
)) == NULL
)
980 if (nv
->nv_str
!= NULL
&& !OPT_FSOPT(name
))
981 cfgerror("already have %s `%s=%s'", type
, name
, nv
->nv_str
);
983 cfgerror("already have %s `%s'", type
, name
);
988 * Remove a name from a hash table,
989 * and optionally, a name=value pair from an option list.
992 undo_option(struct hashtab
*ht
, struct nvlist
**npp
,
993 struct nvlist
***next
, const char *name
, const char *type
)
997 if (ht_remove(ht
, name
)) {
998 cfgerror("%s `%s' is not defined", type
, name
);
1004 for ( ; *npp
!= NULL
; npp
= &(*npp
)->nv_next
) {
1005 if ((*npp
)->nv_name
!= name
)
1007 if (next
!= NULL
&& *next
== &(*npp
)->nv_next
)
1009 nv
= (*npp
)->nv_next
;
1014 panic("%s `%s' is not defined in nvlist", type
, name
);
1019 * Return true if there is at least one instance of the given unit
1020 * on the given device attachment (or any units, if unit == WILD).
1023 deva_has_instances(struct deva
*deva
, int unit
)
1027 for (i
= deva
->d_ihead
; i
!= NULL
; i
= i
->i_asame
)
1028 if (i
->i_active
== DEVI_ACTIVE
&&
1029 (unit
== WILD
|| unit
== i
->i_unit
|| i
->i_unit
== STAR
))
1035 * Return true if there is at least one instance of the given unit
1036 * on the given base (or any units, if unit == WILD).
1039 devbase_has_instances(struct devbase
*dev
, int unit
)
1044 * Pseudo-devices are a little special. We consider them
1045 * to have instances only if they are both:
1047 * 1. Included in this kernel configuration.
1049 * 2. Be declared "defpseudodev".
1051 if (dev
->d_ispseudo
) {
1052 return ((ht_lookup(devitab
, dev
->d_name
) != NULL
)
1053 && (dev
->d_ispseudo
> 1));
1056 for (da
= dev
->d_ahead
; da
!= NULL
; da
= da
->d_bsame
)
1057 if (deva_has_instances(da
, unit
))
1063 cfcrosscheck(struct config
*cf
, const char *what
, struct nvlist
*nv
)
1065 struct devbase
*dev
;
1069 if (maxpartitions
<= 0)
1070 panic("cfcrosscheck");
1072 for (errs
= 0; nv
!= NULL
; nv
= nv
->nv_next
) {
1073 if (nv
->nv_name
== NULL
)
1075 dev
= ht_lookup(devbasetab
, nv
->nv_name
);
1077 panic("cfcrosscheck(%s)", nv
->nv_name
);
1078 if (has_attr(dev
->d_attrs
, s_ifnet
))
1079 devunit
= nv
->nv_ifunit
; /* XXX XXX XXX */
1081 devunit
= (int)(minor(nv
->nv_num
) / maxpartitions
);
1082 if (devbase_has_instances(dev
, devunit
))
1084 if (devbase_has_instances(dev
, STAR
) &&
1085 devunit
>= dev
->d_umax
)
1087 TAILQ_FOREACH(pd
, &allpseudo
, i_next
) {
1088 if (pd
->i_base
== dev
&& devunit
< dev
->d_umax
&&
1092 (void)fprintf(stderr
,
1093 "%s:%d: %s says %s on %s, but there's no %s\n",
1094 conffile
, cf
->cf_lineno
,
1095 cf
->cf_name
, what
, nv
->nv_str
, nv
->nv_str
);
1104 * Cross-check the configuration: make sure that each target device
1105 * or attribute (`at foo[0*?]') names at least one real device. Also
1106 * see that the root and dump devices for all configurations are there.
1115 if (TAILQ_EMPTY(&allcf
)) {
1116 warnx("%s has no configurations!", conffile
);
1119 TAILQ_FOREACH(cf
, &allcf
, cf_next
) {
1120 if (cf
->cf_root
!= NULL
) { /* i.e., not root on ? */
1121 errs
+= cfcrosscheck(cf
, "root", cf
->cf_root
);
1122 errs
+= cfcrosscheck(cf
, "dumps", cf
->cf_dump
);
1129 * Check to see if there is a *'d unit with a needs-count file.
1140 TAILQ_FOREACH(d
, &allbases
, d_next
) {
1141 for (da
= d
->d_ahead
; da
!= NULL
; da
= da
->d_bsame
)
1142 for (i
= da
->d_ihead
; i
!= NULL
; i
= i
->i_asame
) {
1143 if (i
->i_unit
== STAR
)
1148 if (ht_lookup(needcnttab
, d
->d_name
)) {
1149 warnx("%s's cannot be *'d until its driver is fixed",
1154 for (n
= 0; i
!= NULL
; i
= i
->i_alias
)
1155 if (!i
->i_collapsed
)
1158 panic("badstar() n<1");
1164 * Verify/create builddir if necessary, change to it, and verify srcdir.
1165 * This will be called when we see the first include.
1172 /* srcdir must be specified if builddir is not specified or if
1173 * no configuration filename was specified. */
1174 if ((builddir
|| strcmp(defbuilddir
, ".") == 0) && !srcdir
) {
1175 cfgerror("source directory must be specified");
1181 srcdir
= "../../..";
1186 srcdir
= "../../../..";
1187 if (builddir
== NULL
)
1188 builddir
= defbuilddir
;
1190 if (stat(builddir
, &st
) == -1) {
1191 if (mkdir(builddir
, 0777) == -1)
1192 errx(EXIT_FAILURE
, "cannot create %s", builddir
);
1193 } else if (!S_ISDIR(st
.st_mode
))
1194 errx(EXIT_FAILURE
, "%s is not a directory", builddir
);
1195 if (chdir(builddir
) == -1)
1196 err(EXIT_FAILURE
, "cannot change to %s", builddir
);
1197 if (stat(srcdir
, &st
) == -1)
1198 err(EXIT_FAILURE
, "cannot stat %s", srcdir
);
1199 if (!S_ISDIR(st
.st_mode
))
1200 errx(EXIT_FAILURE
, "%s is not a directory", srcdir
);
1204 * Write identifier from "ident" directive into file, for
1205 * newvers.sh to pick it up.
1213 (void)unlink("ident");
1218 if ((fp
= fopen("ident", "w")) == NULL
) {
1219 warn("cannot write ident");
1223 (void)printf("using ident '%s'\n", ident
);
1224 fprintf(fp
, "%s\n", ident
);
1234 logconfig_start(void)
1242 if (yyin
== NULL
|| fstat(fileno(yyin
), &st
) == -1)
1244 cfgtime
= st
.st_mtime
;
1246 tmpdir
= getenv("TMPDIR");
1249 (void)snprintf(line
, sizeof(line
), "%s/config.tmp.XXXXXX", tmpdir
);
1250 if ((fd
= mkstemp(line
)) == -1 ||
1251 (cfg
= fdopen(fd
, "r+")) == NULL
) {
1261 (void)fprintf(cfg
, "#include <sys/cdefs.h>\n\n");
1262 (void)fprintf(cfg
, "#include \"opt_config.h\"\n");
1263 (void)fprintf(cfg
, "\n");
1264 (void)fprintf(cfg
, "/*\n");
1265 (void)fprintf(cfg
, " * Add either (or both) of\n");
1266 (void)fprintf(cfg
, " *\n");
1267 (void)fprintf(cfg
, " *\toptions %s\n", LOGCONFIG_LARGE
);
1268 (void)fprintf(cfg
, " *\toptions %s\n", LOGCONFIG_SMALL
);
1269 (void)fprintf(cfg
, " *\n");
1271 " * to your kernel config file to embed it in the resulting\n");
1273 " * kernel. The latter option does not include files that are\n");
1275 " * included (recursively) by your config file. The embedded\n");
1277 " * data be extracted by using the command:\n");
1278 (void)fprintf(cfg
, " *\n");
1280 " *\tstrings netbsd | sed -n 's/^_CFG_//p' | unvis\n");
1281 (void)fprintf(cfg
, " */\n");
1282 (void)fprintf(cfg
, "\n");
1283 (void)fprintf(cfg
, "#ifdef CONFIG_FILE\n");
1284 (void)fprintf(cfg
, "#if defined(%s) || defined(%s)\n\n",
1285 LOGCONFIG_LARGE
, LOGCONFIG_SMALL
);
1286 (void)fprintf(cfg
, "static const char config[] __used =\n\n");
1288 (void)fprintf(cfg
, "#ifdef %s\n\n", LOGCONFIG_LARGE
);
1289 (void)fprintf(cfg
, "\"_CFG_### START CONFIG FILE \\\"%s\\\"\\n\"\n\n",
1291 (void)fprintf(cfg
, "#endif /* %s */\n\n", LOGCONFIG_LARGE
);
1293 logconfig_include(yyin
, NULL
);
1295 (void)fprintf(cfg
, "#ifdef %s\n\n", LOGCONFIG_LARGE
);
1296 (void)fprintf(cfg
, "\"_CFG_### END CONFIG FILE \\\"%s\\\"\\n\"\n",
1303 logconfig_include(FILE *cf
, const char *filename
)
1305 char line
[1024], in
[2048], *out
;
1313 if (fstat(fileno(cf
), &st
) == -1)
1315 if (cfgtime
< st
.st_mtime
)
1316 cfgtime
= st
.st_mtime
;
1320 "\"_CFG_### (included from \\\"%s\\\")\\n\"\n",
1322 while (fgets(line
, sizeof(line
), cf
) != NULL
) {
1324 (void)fprintf(cfg
, "\"_CFG_");
1326 (void)fprintf(cfg
, "###> ");
1327 strvis(in
, line
, VIS_TAB
);
1328 for (out
= in
; *out
; out
++)
1331 (void)fprintf(cfg
, "\\n\"\n");
1334 case '"': case '\\':
1335 (void)fputc('\\', cfg
);
1338 (void)fputc(*out
, cfg
);
1343 (void)fprintf(cfg
, "\\n\"\n");
1344 warnx("%s: newline missing at EOF",
1345 filename
!= NULL
? filename
: conffile
);
1348 (void)fprintf(cfg
, "\"_CFG_### (end include \\\"%s\\\")\\n\"\n",
1364 (void)fprintf(cfg
, "#endif /* %s */\n", LOGCONFIG_LARGE
);
1365 (void)fprintf(cfg
, ";\n");
1366 (void)fprintf(cfg
, "#endif /* %s || %s */\n",
1367 LOGCONFIG_LARGE
, LOGCONFIG_SMALL
);
1368 (void)fprintf(cfg
, "#endif /* CONFIG_FILE */\n");
1371 err(EXIT_FAILURE
, "write to temporary file for config.h failed");
1374 if (stat("config_file.h", &st
) != -1) {
1375 if (cfgtime
< st
.st_mtime
) {
1381 fp
= fopen("config_file.h", "w");
1383 err(EXIT_FAILURE
, "cannot open \"config.h\"");
1385 while (fgets(line
, sizeof(line
), cfg
) != NULL
)
1389 err(EXIT_FAILURE
, "write to \"config.h\" failed");
1395 strtolower(const char *name
)
1401 for (n
= name
, p
= low
; (c
= *n
) != '\0'; n
++)
1402 *p
++ = isupper(c
) ? tolower(c
) : c
;
1404 return (intern(low
));
1408 is_elf(const char *file
)
1413 kernel
= open(file
, O_RDONLY
);
1415 err(EXIT_FAILURE
, "cannot open %s", file
);
1416 if (read(kernel
, hdr
, 4) != 4)
1417 err(EXIT_FAILURE
, "Cannot read from %s", file
);
1418 (void)close(kernel
);
1420 return memcmp("\177ELF", hdr
, 4) == 0 ? 1 : 0;
1424 extract_config(const char *kname
, const char *cname
, int cfd
)
1432 /* mmap(2) binary kernel */
1433 kfd
= open(conffile
, O_RDONLY
);
1435 err(EXIT_FAILURE
, "cannot open %s", kname
);
1436 if (fstat(kfd
, &st
) == -1)
1437 err(EXIT_FAILURE
, "cannot stat %s", kname
);
1438 ptr
= mmap(0, st
.st_size
, PROT_READ
, MAP_FILE
| MAP_SHARED
,
1440 if (ptr
== MAP_FAILED
)
1441 err(EXIT_FAILURE
, "cannot mmap %s", kname
);
1443 /* Scan mmap(2)'ed region, extracting kernel configuration */
1444 for (i
= 0; i
< st
.st_size
; i
++) {
1445 if ((*ptr
== '_') && (st
.st_size
- i
> 5) && memcmp(ptr
,
1448 char *oldptr
, line
[LINE_MAX
+ 1], uline
[LINE_MAX
+ 1];
1453 oldptr
= (ptr
+= 5);
1454 while (*ptr
!= '\n' && *ptr
!= '\0')
1456 if (ptr
- oldptr
> LINE_MAX
)
1457 errx(EXIT_FAILURE
, "line too long");
1458 i
+= ptr
- oldptr
+ 5;
1459 (void)memcpy(line
, oldptr
, (size_t)(ptr
- oldptr
));
1460 line
[ptr
- oldptr
] = '\0';
1461 j
= strunvis(uline
, line
);
1463 errx(EXIT_FAILURE
, "unvis: invalid "
1464 "encoded sequence");
1466 if (write(cfd
, uline
, (size_t)j
+ 1) == -1)
1467 err(EXIT_FAILURE
, "cannot write to %s", cname
);
1477 struct dhdi_params
{
1484 devbase_has_dead_instances(const char *key
, void *value
, void *aux
)
1487 struct dhdi_params
*dhdi
= aux
;
1489 for (i
= value
; i
!= NULL
; i
= i
->i_alias
)
1490 if (i
->i_base
== dhdi
->d
&&
1491 (dhdi
->unit
== WILD
|| dhdi
->unit
== i
->i_unit
||
1492 i
->i_unit
== STAR
) &&
1493 i
->i_level
>= dhdi
->level
)
1499 * This is almost the same as devbase_has_instances, except it
1500 * may have special considerations regarding ignored instances.
1504 devbase_has_any_instance(struct devbase
*dev
, int unit
, int state
, int level
)
1509 if (dev
->d_ispseudo
) {
1510 if (dev
->d_ihead
!= NULL
)
1512 else if (state
!= DEVI_IGNORED
)
1514 if ((i
= ht_lookup(deaddevitab
, dev
->d_name
)) == NULL
)
1516 return (i
->i_level
>= level
);
1519 for (da
= dev
->d_ahead
; da
!= NULL
; da
= da
->d_bsame
)
1520 for (i
= da
->d_ihead
; i
!= NULL
; i
= i
->i_asame
)
1521 if ((i
->i_active
== DEVI_ACTIVE
||
1522 i
->i_active
== state
) &&
1523 (unit
== WILD
|| unit
== i
->i_unit
||
1527 if (state
== DEVI_IGNORED
) {
1528 struct dhdi_params dhdi
= { dev
, unit
, level
};
1529 /* also check dead devices */
1530 return ht_enumerate(deaddevitab
, devbase_has_dead_instances
,
1538 * check_dead_devi(), used with ht_enumerate, checks if any of the removed
1539 * device instances would have been a valid instance considering the devbase,
1540 * the parent device and the interface attribute.
1542 * In other words, for a non-active device, it checks if children would be
1543 * actual orphans or the result of a negative statement in the config file.
1549 struct devbase
*parent
;
1553 check_dead_devi(const char *key
, void *value
, void *aux
)
1555 struct cdd_params
*cdd
= aux
;
1556 struct devi
*i
= value
;
1559 if (i
->i_base
!= cdd
->d
)
1562 for (; i
!= NULL
; i
= i
->i_alias
) {
1564 if ((p
== NULL
&& cdd
->at
== NULL
) ||
1565 (p
!= NULL
&& p
->p_iattr
== cdd
->at
&&
1566 (p
->p_atdev
== NULL
|| p
->p_atdev
== cdd
->parent
))) {
1568 !devbase_has_any_instance(cdd
->parent
, p
->p_atunit
,
1569 DEVI_IGNORED
, i
->i_level
))
1579 do_kill_orphans(struct devbase
*d
, struct attr
*at
, struct devbase
*parent
,
1582 struct nvlist
*nv
, *nv1
;
1584 struct devi
*i
, *j
= NULL
;
1589 * A pseudo-device will always attach at root, and if it has an
1590 * instance (it cannot have more than one), it is enough to consider
1591 * it active, as there is no real attachment.
1593 * A pseudo device can never be marked DEVI_IGNORED.
1595 if (d
->d_ispseudo
) {
1596 if (d
->d_ihead
!= NULL
)
1597 d
->d_ihead
->i_active
= active
= DEVI_ACTIVE
;
1599 if (ht_lookup(deaddevitab
, d
->d_name
) != NULL
)
1600 active
= DEVI_IGNORED
;
1607 for (i
= d
->d_ihead
; i
!= NULL
; i
= i
->i_bsame
) {
1608 for (j
= i
; j
!= NULL
; j
= j
->i_alias
) {
1610 if ((p
== NULL
&& at
== NULL
) ||
1611 (p
!= NULL
&& p
->p_iattr
== at
&&
1612 (p
->p_atdev
== NULL
||
1613 p
->p_atdev
== parent
))) {
1615 !devbase_has_any_instance(parent
,
1616 p
->p_atunit
, state
, j
->i_level
))
1619 * There are Fry-like devices which can
1620 * be their own grand-parent (or even
1621 * parent, like uhub). We don't want
1622 * to loop, so if we've already reached
1623 * an instance for one reason or
1624 * another, stop there.
1626 if (j
->i_active
== DEVI_ACTIVE
||
1627 j
->i_active
== state
) {
1629 * Device has already been
1630 * seen. However it might
1631 * have siblings who still
1632 * have to be activated or
1638 j
->i_active
= active
= state
;
1640 p
->p_active
= state
;
1645 * If we've been there but have made no change, stop.
1647 if (seen
&& !active
)
1650 struct cdd_params cdd
= { d
, at
, parent
};
1651 /* Look for a matching dead devi */
1652 if (ht_enumerate(deaddevitab
, check_dead_devi
, &cdd
) &&
1655 * That device had its instances removed.
1656 * Continue the loop marking descendants
1657 * with DEVI_IGNORED instead of DEVI_ACTIVE.
1659 * There is one special case for devices that
1660 * are their own parent: if that instance is
1661 * removed (e.g., no uhub* at uhub?), we don't
1662 * have to continue looping.
1664 active
= DEVI_IGNORED
;
1670 for (nv
= d
->d_attrs
; nv
!= NULL
; nv
= nv
->nv_next
) {
1672 for (nv1
= a
->a_devs
; nv1
!= NULL
; nv1
= nv1
->nv_next
)
1673 do_kill_orphans(nv1
->nv_ptr
, a
, d
, active
);
1679 kill_orphans_cb(const char *key
, void *value
, void *aux
)
1681 do_kill_orphans((struct devbase
*)value
, NULL
, NULL
, DEVI_ACTIVE
);
1688 ht_enumerate(devroottab
, kill_orphans_cb
, NULL
);