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