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