1 /* $NetBSD: main.c,v 1.13 2006/05/25 22:28:38 cube 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 #ifndef MAKE_BOOTSTRAP 48 #include <sys/cdefs.h> 49 #define COPYRIGHT(x) __COPYRIGHT(x) 50 #else 51 #define COPYRIGHT(x) static const char copyright[] = x 52 #endif 53 54 #ifndef lint 55 COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\ 56 The Regents of the University of California. All rights reserved.\n"); 57 #endif /* not lint */ 58 59 #include <sys/types.h> 60 #include <sys/stat.h> 61 #include <sys/param.h> 62 #include <sys/mman.h> 63 #include <paths.h> 64 #include <ctype.h> 65 #include <errno.h> 66 #include <fcntl.h> 67 #include <stdio.h> 68 #include <stdlib.h> 69 #include <string.h> 70 #include <unistd.h> 71 #include "defs.h" 72 #include "sem.h" 73 #include <vis.h> 74 75 #ifndef LINE_MAX 76 #define LINE_MAX 1024 77 #endif 78 79 int vflag; /* verbose output */ 80 int Pflag; /* pack locators */ 81 82 int yyparse(void); 83 84 #ifndef MAKE_BOOTSTRAP 85 extern int yydebug; 86 #endif 87 88 static struct hashtab *obsopttab; 89 static struct hashtab *mkopttab; 90 static struct nvlist **nextopt; 91 static struct nvlist **nextmkopt; 92 static struct nvlist **nextappmkopt; 93 static struct nvlist **nextfsopt; 94 95 static void usage(void); 96 static void dependopts(void); 97 static void do_depend(struct nvlist *); 98 static void stop(void); 99 static int do_option(struct hashtab *, struct nvlist ***, 100 const char *, const char *, const char *); 101 static int undo_option(struct hashtab *, struct nvlist **, 102 struct nvlist ***, const char *, const char *); 103 static int crosscheck(void); 104 static int badstar(void); 105 int main(int, char **); 106 static int mksymlinks(void); 107 static int mkident(void); 108 static int devbase_has_dead_instances(const char *, void *, void *); 109 static int devbase_has_any_instance(struct devbase *, int, int, int); 110 static int check_dead_devi(const char *, void *, void *); 111 static void kill_orphans(void); 112 static void do_kill_orphans(struct devbase *, struct attr *, 113 struct devbase *, int); 114 static int kill_orphans_cb(const char *, void *, void *); 115 static int cfcrosscheck(struct config *, const char *, struct nvlist *); 116 static const char *strtolower(const char *); 117 void defopt(struct hashtab *ht, const char *fname, 118 struct nvlist *opts, struct nvlist *deps, int obs); 119 120 #define LOGCONFIG_LARGE "INCLUDE_CONFIG_FILE" 121 #define LOGCONFIG_SMALL "INCLUDE_JUST_CONFIG" 122 123 static void logconfig_start(void); 124 static void logconfig_end(void); 125 static FILE *cfg; 126 static time_t cfgtime; 127 128 static int is_elf(const char *); 129 static int extract_config(const char *, const char *, int); 130 131 int badfilename(const char *fname); 132 133 const char *progname; 134 135 int 136 main(int argc, char **argv) 137 { 138 char *p, cname[20]; 139 const char *last_component; 140 int pflag, xflag, ch, removeit; 141 142 setprogname(argv[0]); 143 144 pflag = 0; 145 xflag = 0; 146 while ((ch = getopt(argc, argv, "DPgpvb:s:x")) != -1) { 147 switch (ch) { 148 149 #ifndef MAKE_BOOTSTRAP 150 case 'D': 151 yydebug = 1; 152 break; 153 #endif 154 155 case 'P': 156 Pflag = 1; 157 break; 158 159 case 'g': 160 /* 161 * In addition to DEBUG, you probably wanted to 162 * set "options KGDB" and maybe others. We could 163 * do that for you, but you really should just 164 * put them in the config file. 165 */ 166 (void)fprintf(stderr, 167 "config: -g is obsolete (use makeoptions DEBUG=\"-g\")\n"); 168 usage(); 169 170 case 'p': 171 /* 172 * Essentially the same as makeoptions PROF="-pg", 173 * but also changes the path from ../../compile/FOO 174 * to ../../compile/FOO.PROF; i.e., compile a 175 * profiling kernel based on a typical "regular" 176 * kernel. 177 * 178 * Note that if you always want profiling, you 179 * can (and should) use a "makeoptions" line. 180 */ 181 pflag = 1; 182 break; 183 184 case 'v': 185 vflag = 1; 186 break; 187 188 case 'b': 189 builddir = optarg; 190 break; 191 192 case 's': 193 srcdir = optarg; 194 break; 195 196 case 'x': 197 xflag = 1; 198 break; 199 200 case '?': 201 default: 202 usage(); 203 } 204 } 205 206 argc -= optind; 207 argv += optind; 208 if (argc > 1) { 209 usage(); 210 } 211 212 if (xflag && (builddir != NULL || srcdir != NULL || Pflag || pflag || 213 vflag)) { 214 (void)fprintf(stderr, "config: -x must be used alone\n"); 215 exit(1); 216 } 217 218 if (xflag) { 219 #ifdef __NetBSD__ 220 conffile = (argc == 1) ? argv[0] : _PATH_UNIX; 221 #else 222 if (argc == 0) { 223 (void)fprintf(stderr, "config: no kernel supplied\n"); 224 exit(1); 225 } 226 #endif 227 if (!is_elf(conffile)) { 228 (void)fprintf(stderr, 229 "config: %s: not a binary kernel\n", 230 conffile); 231 exit(1); 232 } 233 if (!extract_config(conffile, "stdout", STDOUT_FILENO)) { 234 (void)fprintf(stderr, 235 "config: %s does not contain embedded " 236 "configuration data\n", conffile); 237 exit(2); 238 } 239 exit(0); 240 } 241 242 conffile = (argc == 1) ? argv[0] : "CONFIG"; 243 if (firstfile(conffile)) { 244 (void)fprintf(stderr, "config: cannot read %s: %s\n", 245 conffile, strerror(errno)); 246 exit(2); 247 } 248 249 /* 250 * Init variables. 251 */ 252 minmaxusers = 1; 253 maxmaxusers = 10000; 254 initintern(); 255 initfiles(); 256 initsem(); 257 ident = NULL; 258 devbasetab = ht_new(); 259 devroottab = ht_new(); 260 devatab = ht_new(); 261 devitab = ht_new(); 262 deaddevitab = ht_new(); 263 selecttab = ht_new(); 264 needcnttab = ht_new(); 265 opttab = ht_new(); 266 mkopttab = ht_new(); 267 condmkopttab = ht_new(); 268 fsopttab = ht_new(); 269 deffstab = ht_new(); 270 defopttab = ht_new(); 271 defparamtab = ht_new(); 272 defflagtab = ht_new(); 273 optfiletab = ht_new(); 274 obsopttab = ht_new(); 275 bdevmtab = ht_new(); 276 maxbdevm = 0; 277 cdevmtab = ht_new(); 278 maxcdevm = 0; 279 nextopt = &options; 280 nextmkopt = &mkoptions; 281 nextappmkopt = &appmkoptions; 282 nextfsopt = &fsoptions; 283 284 /* 285 * Handle profiling (must do this before we try to create any 286 * files). 287 */ 288 last_component = strrchr(conffile, '/'); 289 last_component = (last_component) ? last_component + 1 : conffile; 290 if (pflag) { 291 p = emalloc(strlen(last_component) + 17); 292 (void)sprintf(p, "../compile/%s.PROF", last_component); 293 (void)addmkoption(intern("PROF"), "-pg"); 294 (void)addoption(intern("GPROF"), NULL); 295 } else { 296 p = emalloc(strlen(last_component) + 13); 297 (void)sprintf(p, "../compile/%s", last_component); 298 } 299 defbuilddir = (argc == 0) ? "." : p; 300 301 removeit = 0; 302 if (is_elf(conffile)) { 303 const char *tmpdir; 304 int cfd; 305 306 if (builddir == NULL) { 307 (void)fprintf(stderr, 308 "config: build directory must be specified with " 309 "binary kernels\n"); 310 exit(1); 311 } 312 313 /* Open temporary configuration file */ 314 tmpdir = getenv("TMPDIR"); 315 if (tmpdir == NULL) 316 tmpdir = "/tmp"; 317 snprintf(cname, sizeof(cname), "%s/config.tmp.XXXXXX", tmpdir); 318 cfd = mkstemp(cname); 319 if (cfd == -1) { 320 fprintf(stderr, "config: cannot create %s: %s", cname, 321 strerror(errno)); 322 exit(2); 323 } 324 325 printf("Using configuration data embedded in kernel...\n"); 326 if (!extract_config(conffile, cname, cfd)) { 327 (void)fprintf(stderr, 328 "config: %s does not contain embedded " 329 "configuration data\n", conffile); 330 exit(2); 331 } 332 333 removeit = 1; 334 close(cfd); 335 firstfile(cname); 336 } 337 338 /* 339 * Parse config file (including machine definitions). 340 */ 341 logconfig_start(); 342 if (yyparse()) 343 stop(); 344 logconfig_end(); 345 346 if (removeit) 347 unlink(cname); 348 349 /* 350 * Detect and properly ignore orphaned devices 351 */ 352 kill_orphans(); 353 354 /* 355 * Select devices and pseudo devices and their attributes 356 */ 357 if (fixdevis()) 358 stop(); 359 360 /* 361 * Deal with option dependencies. 362 */ 363 dependopts(); 364 365 /* 366 * Fix (as in `set firmly in place') files. 367 */ 368 if (fixfiles()) 369 stop(); 370 371 /* 372 * Fix objects and libraries. 373 */ 374 if (fixobjects()) 375 stop(); 376 377 /* 378 * Fix device-majors. 379 */ 380 if (fixdevsw()) 381 stop(); 382 383 /* 384 * Perform cross-checking. 385 */ 386 if (maxusers == 0) { 387 if (defmaxusers) { 388 (void)printf("maxusers not specified; %d assumed\n", 389 defmaxusers); 390 maxusers = defmaxusers; 391 } else { 392 (void)fprintf(stderr, 393 "config: need \"maxusers\" line\n"); 394 errors++; 395 } 396 } 397 if (fsoptions == NULL) { 398 (void)fprintf(stderr, 399 "config: need at least one \"file-system\" line\n"); 400 errors++; 401 } 402 if (crosscheck() || errors) 403 stop(); 404 405 /* 406 * Squeeze things down and finish cross-checks (STAR checks must 407 * run after packing). 408 */ 409 pack(); 410 if (badstar()) 411 stop(); 412 413 /* 414 * Ready to go. Build all the various files. 415 */ 416 if (mksymlinks() || mkmakefile() || mkheaders() || mkswap() || 417 mkioconf() || (do_devsw ? mkdevsw() : 0) || mkident()) 418 stop(); 419 (void)printf("Build directory is %s\n", builddir); 420 (void)printf("Don't forget to run \"make depend\"\n"); 421 exit(0); 422 } 423 424 static void 425 usage(void) 426 { 427 (void)fputs("usage: config [-Ppv] [-s srcdir] [-b builddir] " 428 "[sysname]\n", stderr); 429 (void)fputs(" config -x [kernel-file]\n", stderr); 430 exit(1); 431 } 432 433 /* 434 * Set any options that are implied by other options. 435 */ 436 static void 437 dependopts(void) 438 { 439 struct nvlist *nv, *opt; 440 441 for (nv = options; nv != NULL; nv = nv->nv_next) { 442 if ((opt = find_declared_option(nv->nv_name)) != NULL) { 443 for (opt = opt->nv_ptr; opt != NULL; 444 opt = opt->nv_next) { 445 do_depend(opt); 446 } 447 } 448 } 449 } 450 451 static void 452 do_depend(struct nvlist *nv) 453 { 454 struct nvlist *nextnv; 455 struct attr *a; 456 457 if (nv != NULL && (nv->nv_flags & NV_DEPENDED) == 0) { 458 nv->nv_flags |= NV_DEPENDED; 459 /* 460 * If the dependency is an attribute, then just add 461 * it to the selecttab. 462 */ 463 if ((a = ht_lookup(attrtab, nv->nv_name)) != NULL) { 464 if (a->a_iattr) 465 panic("do_depend(%s): dep `%s' is an iattr", 466 nv->nv_name, a->a_name); 467 expandattr(a, selectattr); 468 } else { 469 if (ht_lookup(opttab, nv->nv_name) == NULL) 470 addoption(nv->nv_name, NULL); 471 if ((nextnv = 472 find_declared_option(nv->nv_name)) != NULL) 473 do_depend(nextnv->nv_ptr); 474 } 475 } 476 } 477 478 /* 479 * Make a symlink for "machine" so that "#include <machine/foo.h>" works, 480 * and for the machine's CPU architecture, so that works as well. 481 */ 482 static int 483 mksymlinks(void) 484 { 485 int ret; 486 char *p, buf[MAXPATHLEN]; 487 const char *q; 488 struct nvlist *nv; 489 490 snprintf(buf, sizeof(buf), "arch/%s/include", machine); 491 p = sourcepath(buf); 492 ret = unlink("machine"); 493 if (ret && errno != ENOENT) 494 (void)fprintf(stderr, "config: unlink(machine): %s\n", 495 strerror(errno)); 496 ret = symlink(p, "machine"); 497 if (ret) 498 (void)fprintf(stderr, "config: symlink(machine -> %s): %s\n", 499 p, strerror(errno)); 500 free(p); 501 502 if (machinearch != NULL) { 503 snprintf(buf, sizeof(buf), "arch/%s/include", machinearch); 504 p = sourcepath(buf); 505 q = machinearch; 506 } else { 507 p = estrdup("machine"); 508 q = machine; 509 } 510 ret = unlink(q); 511 if (ret && errno != ENOENT) 512 (void)fprintf(stderr, "config: unlink(%s): %s\n", 513 q, strerror(errno)); 514 ret = symlink(p, q); 515 if (ret) 516 (void)fprintf(stderr, "config: symlink(%s -> %s): %s\n", 517 q, p, strerror(errno)); 518 free(p); 519 520 for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) { 521 q = nv->nv_name; 522 snprintf(buf, sizeof(buf), "arch/%s/include", q); 523 p = sourcepath(buf); 524 ret = unlink(q); 525 if (ret && errno != ENOENT) 526 (void)fprintf(stderr, "config: unlink(%s): %s\n", 527 q, strerror(errno)); 528 ret = symlink(p, q); 529 if (ret) 530 (void)fprintf(stderr, "config: symlink(%s -> %s): %s\n", 531 q, p, strerror(errno)); 532 free(p); 533 } 534 535 return (ret); 536 } 537 538 static __dead void 539 stop(void) 540 { 541 (void)fprintf(stderr, "*** Stop.\n"); 542 exit(1); 543 } 544 545 /* 546 * Define one or more file systems. If file system options file name is 547 * specified, a preprocessor #define for that file system will be placed 548 * in that file. In this case, only one file system may be specified. 549 * Otherwise, no preprocessor #defines will be generated. 550 */ 551 void 552 deffilesystem(const char *fname, struct nvlist *fses) 553 { 554 struct nvlist *nv; 555 556 /* 557 * Mark these options as ones to skip when creating the Makefile. 558 */ 559 for (nv = fses; nv != NULL; nv = nv->nv_next) { 560 if (ht_insert(defopttab, nv->nv_name, nv)) { 561 error("file system or option `%s' already defined", 562 nv->nv_name); 563 return; 564 } 565 566 /* 567 * Also mark it as a valid file system, which may be 568 * used in "file-system" directives in the config 569 * file. 570 */ 571 if (ht_insert(deffstab, nv->nv_name, nv)) 572 panic("file system `%s' already in table?!", 573 nv->nv_name); 574 575 if (fname != NULL) { 576 /* 577 * Only one file system allowed in this case. 578 */ 579 if (nv->nv_next != NULL) { 580 error("only one file system per option " 581 "file may be specified"); 582 return; 583 } 584 585 if (ht_insert(optfiletab, fname, nv)) { 586 error("option file `%s' already exists", 587 fname); 588 return; 589 } 590 } 591 } 592 } 593 594 /* 595 * Sanity check a file name. 596 */ 597 int 598 badfilename(const char *fname) 599 { 600 const char *n; 601 602 /* 603 * We're putting multiple options into one file. Sanity 604 * check the file name. 605 */ 606 if (strchr(fname, '/') != NULL) { 607 error("option file name contains a `/'"); 608 return 1; 609 } 610 if ((n = strrchr(fname, '.')) == NULL || strcmp(n, ".h") != 0) { 611 error("option file name does not end in `.h'"); 612 return 1; 613 } 614 return 0; 615 } 616 617 618 /* 619 * Search for a defined option (defopt, filesystem, etc), and if found, 620 * return the option's struct nvlist. 621 */ 622 struct nvlist * 623 find_declared_option(const char *name) 624 { 625 struct nvlist *option = NULL; 626 627 if ((option = ht_lookup(defopttab, name)) != NULL || 628 (option = ht_lookup(defparamtab, name)) != NULL || 629 (option = ht_lookup(defflagtab, name)) != NULL || 630 (option = ht_lookup(fsopttab, name)) != NULL) { 631 return (option); 632 } 633 634 return (NULL); 635 } 636 637 638 /* 639 * Define one or more standard options. If an option file name is specified, 640 * place all options in one file with the specified name. Otherwise, create 641 * an option file for each option. 642 * record the option information in the specified table. 643 */ 644 void 645 defopt(struct hashtab *ht, const char *fname, struct nvlist *opts, 646 struct nvlist *deps, int obs) 647 { 648 struct nvlist *nv, *nextnv, *oldnv, *dep; 649 struct attr *a; 650 const char *name; 651 char buf[500]; 652 653 if (fname != NULL && badfilename(fname)) { 654 return; 655 } 656 657 /* 658 * Mark these options as ones to skip when creating the Makefile. 659 */ 660 for (nv = opts; nv != NULL; nv = nextnv) { 661 nextnv = nv->nv_next; 662 663 /* An option name can be declared at most once. */ 664 if (DEFINED_OPTION(nv->nv_name)) { 665 error("file system or option `%s' already defined", 666 nv->nv_name); 667 return; 668 } 669 670 if (ht_insert(ht, nv->nv_name, nv)) { 671 error("file system or option `%s' already defined", 672 nv->nv_name); 673 return; 674 } 675 676 if (fname == NULL) { 677 /* 678 * Each option will be going into its own file. 679 * Convert the option name to lower case. This 680 * lower case name will be used as the option 681 * file name. 682 */ 683 (void) snprintf(buf, sizeof(buf), "opt_%s.h", 684 strtolower(nv->nv_name)); 685 name = intern(buf); 686 } else { 687 name = fname; 688 } 689 690 /* Use nv_ptr to link any other options that are implied. */ 691 nv->nv_ptr = deps; 692 for (dep = deps; dep != NULL; dep = dep->nv_next) { 693 /* 694 * If the dependency is an attribute, it must not 695 * be an interface attribute. Otherwise, it must 696 * be a previously declared option. 697 */ 698 if ((a = ht_lookup(attrtab, dep->nv_name)) != NULL) { 699 if (a->a_iattr) 700 error("option `%s' dependency `%s' " 701 "is an interface attribute", 702 nv->nv_name, a->a_name); 703 } else if (OPT_OBSOLETE(dep->nv_name)) { 704 error("option `%s' dependency `%s' " 705 "is obsolete", nv->nv_name, dep->nv_name); 706 } else if (find_declared_option(dep->nv_name) == NULL) { 707 error("option `%s' dependency `%s' " 708 "is an unknown option", 709 nv->nv_name, dep->nv_name); 710 } 711 } 712 713 /* 714 * Remove this option from the parameter list before adding 715 * it to the list associated with this option file. 716 */ 717 nv->nv_next = NULL; 718 719 /* 720 * Flag as obsolete, if requested. 721 */ 722 if (obs) { 723 nv->nv_flags |= NV_OBSOLETE; 724 (void)ht_insert(obsopttab, nv->nv_name, nv); 725 } 726 727 /* 728 * Add this option file if we haven't seen it yet. 729 * Otherwise, append to the list of options already 730 * associated with this file. 731 */ 732 if ((oldnv = ht_lookup(optfiletab, name)) == NULL) { 733 (void)ht_insert(optfiletab, name, nv); 734 } else { 735 while (oldnv->nv_next != NULL) 736 oldnv = oldnv->nv_next; 737 oldnv->nv_next = nv; 738 } 739 } 740 } 741 742 /* 743 * Define one or more standard options. If an option file name is specified, 744 * place all options in one file with the specified name. Otherwise, create 745 * an option file for each option. 746 */ 747 void 748 defoption(const char *fname, struct nvlist *opts, struct nvlist *deps) 749 { 750 751 warn("The use of `defopt' is deprecated"); 752 defopt(defopttab, fname, opts, deps, 0); 753 } 754 755 756 /* 757 * Define an option for which a value is required. 758 */ 759 void 760 defparam(const char *fname, struct nvlist *opts, struct nvlist *deps, int obs) 761 { 762 763 defopt(defparamtab, fname, opts, deps, obs); 764 } 765 766 /* 767 * Define an option which must not have a value, and which 768 * emits a "needs-flag" style output. 769 */ 770 void 771 defflag(const char *fname, struct nvlist *opts, struct nvlist *deps, int obs) 772 { 773 774 defopt(defflagtab, fname, opts, deps, obs); 775 } 776 777 778 /* 779 * Add an option from "options FOO". Note that this selects things that 780 * are "optional foo". 781 */ 782 void 783 addoption(const char *name, const char *value) 784 { 785 const char *n; 786 int is_fs, is_param, is_flag, is_opt, is_undecl, is_obs; 787 788 /* 789 * Figure out how this option was declared (if at all.) 790 * XXX should use "params" and "flags" in config. 791 * XXX crying out for a type field in a unified hashtab. 792 */ 793 is_fs = OPT_FSOPT(name); 794 is_param = OPT_DEFPARAM(name); 795 is_opt = OPT_DEFOPT(name); 796 is_flag = OPT_DEFFLAG(name); 797 is_obs = OPT_OBSOLETE(name); 798 is_undecl = !DEFINED_OPTION(name); 799 800 /* Warn and pretend the user had not selected the option */ 801 if (is_obs) { 802 warn("obsolete option `%s' will be ignored", name); 803 return; 804 } 805 806 /* Make sure this is not a defined file system. */ 807 if (is_fs) { 808 error("`%s' is a defined file system", name); 809 return; 810 } 811 /* A defparam must have a value */ 812 if (is_param && value == NULL) { 813 error("option `%s' must have a value", name); 814 return; 815 } 816 /* A defflag must not have a value */ 817 if (is_flag && value != NULL) { 818 error("option `%s' must not have a value", name); 819 return; 820 } 821 822 if (is_undecl && vflag) { 823 warn("undeclared option `%s' added to IDENT", name); 824 } 825 826 if (do_option(opttab, &nextopt, name, value, "options")) 827 return; 828 829 /* make lowercase, then add to select table */ 830 n = strtolower(name); 831 (void)ht_insert(selecttab, n, (void *)n); 832 } 833 834 void 835 deloption(const char *name) 836 { 837 838 if (undo_option(opttab, &options, &nextopt, name, "options")) 839 return; 840 if (undo_option(selecttab, NULL, NULL, strtolower(name), "options")) 841 return; 842 } 843 844 /* 845 * Add a file system option. This routine simply inserts the name into 846 * a list of valid file systems, which is used to validate the root 847 * file system type. The name is then treated like a standard option. 848 */ 849 void 850 addfsoption(const char *name) 851 { 852 const char *n; 853 854 /* Make sure this is a defined file system. */ 855 if (!OPT_FSOPT(name)) { 856 error("`%s' is not a defined file system", name); 857 return; 858 } 859 860 /* 861 * Convert to lower case. This will be used in the select 862 * table, to verify root file systems, and when the initial 863 * VFS list is created. 864 */ 865 n = strtolower(name); 866 867 if (do_option(fsopttab, &nextfsopt, name, n, "file-system")) 868 return; 869 870 /* 871 * Add a lower-case version to the table for root file system 872 * verification. 873 */ 874 if (ht_insert(fsopttab, n, (void *)n)) 875 panic("addfsoption: already in table"); 876 877 /* Add to select table. */ 878 (void)ht_insert(selecttab, n, (void *)n); 879 } 880 881 void 882 delfsoption(const char *name) 883 { 884 const char *n; 885 886 n = strtolower(name); 887 if (undo_option(fsopttab, &fsoptions, &nextfsopt, name, "file-system")) 888 return; 889 if (undo_option(fsopttab, NULL, NULL, n, "file-system")) 890 return; 891 if (undo_option(selecttab, NULL, NULL, n, "file-system")) 892 return; 893 } 894 895 /* 896 * Add a "make" option. 897 */ 898 void 899 addmkoption(const char *name, const char *value) 900 { 901 902 (void)do_option(mkopttab, &nextmkopt, name, value, "makeoptions"); 903 } 904 905 void 906 delmkoption(const char *name) 907 { 908 909 (void)undo_option(mkopttab, &mkoptions, &nextmkopt, name, 910 "makeoptions"); 911 } 912 913 /* 914 * Add an appending "make" option. 915 */ 916 void 917 appendmkoption(const char *name, const char *value) 918 { 919 struct nvlist *nv; 920 921 nv = newnv(name, value, NULL, 0, NULL); 922 *nextappmkopt = nv; 923 nextappmkopt = &nv->nv_next; 924 } 925 926 /* 927 * Add a conditional appending "make" option. 928 */ 929 void 930 appendcondmkoption(const char *selname, const char *name, const char *value) 931 { 932 struct nvlist *nv, *lnv; 933 const char *n; 934 935 n = strtolower(selname); 936 nv = newnv(name, value, NULL, 0, NULL); 937 if (ht_insert(condmkopttab, n, nv) == 0) 938 return; 939 940 if ((lnv = ht_lookup(condmkopttab, n)) == NULL) 941 panic("appendcondmkoption"); 942 for (; lnv->nv_next != NULL; lnv = lnv->nv_next) 943 /* search for the last list element */; 944 lnv->nv_next = nv; 945 } 946 947 /* 948 * Add a name=value pair to an option list. The value may be NULL. 949 */ 950 static int 951 do_option(struct hashtab *ht, struct nvlist ***nppp, const char *name, 952 const char *value, const char *type) 953 { 954 struct nvlist *nv; 955 956 /* 957 * If a defopt'ed or defflag'ed option was enabled but without 958 * an explicit value (always the case for defflag), supply a 959 * default value of 1, as for non-defopt options (where cc 960 * treats -DBAR as -DBAR=1.) 961 */ 962 if ((OPT_DEFOPT(name) || OPT_DEFFLAG(name)) && value == NULL) 963 value = "1"; 964 965 /* assume it will work */ 966 nv = newnv(name, value, NULL, 0, NULL); 967 if (ht_insert(ht, name, nv) == 0) { 968 **nppp = nv; 969 *nppp = &nv->nv_next; 970 return (0); 971 } 972 973 /* oops, already got that option */ 974 nvfree(nv); 975 if ((nv = ht_lookup(ht, name)) == NULL) 976 panic("do_option"); 977 if (nv->nv_str != NULL && !OPT_FSOPT(name)) 978 error("already have %s `%s=%s'", type, name, nv->nv_str); 979 else 980 error("already have %s `%s'", type, name); 981 return (1); 982 } 983 984 /* 985 * Remove a name from a hash table, 986 * and optionally, a name=value pair from an option list. 987 */ 988 static int 989 undo_option(struct hashtab *ht, struct nvlist **npp, 990 struct nvlist ***next, const char *name, const char *type) 991 { 992 struct nvlist *nv; 993 994 if (ht_remove(ht, name)) { 995 error("%s `%s' is not defined", type, name); 996 return (1); 997 } 998 if (npp == NULL) 999 return (0); 1000 1001 for ( ; *npp != NULL; npp = &(*npp)->nv_next) { 1002 if ((*npp)->nv_name != name) 1003 continue; 1004 if (next != NULL && *next == &(*npp)->nv_next) 1005 *next = npp; 1006 nv = (*npp)->nv_next; 1007 nvfree(*npp); 1008 *npp = nv; 1009 return (0); 1010 } 1011 panic("%s `%s' is not defined in nvlist", type, name); 1012 return (1); 1013 } 1014 1015 /* 1016 * Return true if there is at least one instance of the given unit 1017 * on the given device attachment (or any units, if unit == WILD). 1018 */ 1019 int 1020 deva_has_instances(struct deva *deva, int unit) 1021 { 1022 struct devi *i; 1023 1024 for (i = deva->d_ihead; i != NULL; i = i->i_asame) 1025 if (i->i_active == DEVI_ACTIVE && 1026 (unit == WILD || unit == i->i_unit || i->i_unit == STAR)) 1027 return (1); 1028 return (0); 1029 } 1030 1031 /* 1032 * Return true if there is at least one instance of the given unit 1033 * on the given base (or any units, if unit == WILD). 1034 */ 1035 int 1036 devbase_has_instances(struct devbase *dev, int unit) 1037 { 1038 struct deva *da; 1039 1040 /* 1041 * Pseudo-devices are a little special. We consider them 1042 * to have instances only if they are both: 1043 * 1044 * 1. Included in this kernel configuration. 1045 * 1046 * 2. Have one or more interface attributes. 1047 */ 1048 if (dev->d_ispseudo) { 1049 struct nvlist *nv; 1050 struct attr *a; 1051 1052 if (ht_lookup(devitab, dev->d_name) == NULL) 1053 return (0); 1054 1055 for (nv = dev->d_attrs; nv != NULL; nv = nv->nv_next) { 1056 a = nv->nv_ptr; 1057 if (a->a_iattr) 1058 return (1); 1059 } 1060 return (0); 1061 } 1062 1063 for (da = dev->d_ahead; da != NULL; da = da->d_bsame) 1064 if (deva_has_instances(da, unit)) 1065 return (1); 1066 return (0); 1067 } 1068 1069 static int 1070 cfcrosscheck(struct config *cf, const char *what, struct nvlist *nv) 1071 { 1072 struct devbase *dev; 1073 struct devi *pd; 1074 int errs, devunit; 1075 1076 if (maxpartitions <= 0) 1077 panic("cfcrosscheck"); 1078 1079 for (errs = 0; nv != NULL; nv = nv->nv_next) { 1080 if (nv->nv_name == NULL) 1081 continue; 1082 dev = ht_lookup(devbasetab, nv->nv_name); 1083 if (dev == NULL) 1084 panic("cfcrosscheck(%s)", nv->nv_name); 1085 if (has_attr(dev->d_attrs, s_ifnet)) 1086 devunit = nv->nv_ifunit; /* XXX XXX XXX */ 1087 else 1088 devunit = minor(nv->nv_int) / maxpartitions; 1089 if (devbase_has_instances(dev, devunit)) 1090 continue; 1091 if (devbase_has_instances(dev, STAR) && 1092 devunit >= dev->d_umax) 1093 continue; 1094 TAILQ_FOREACH(pd, &allpseudo, i_next) { 1095 if (pd->i_base == dev && devunit < dev->d_umax && 1096 devunit >= 0) 1097 goto loop; 1098 } 1099 (void)fprintf(stderr, 1100 "%s:%d: %s says %s on %s, but there's no %s\n", 1101 conffile, cf->cf_lineno, 1102 cf->cf_name, what, nv->nv_str, nv->nv_str); 1103 errs++; 1104 loop: 1105 ; 1106 } 1107 return (errs); 1108 } 1109 1110 /* 1111 * Cross-check the configuration: make sure that each target device 1112 * or attribute (`at foo[0*?]') names at least one real device. Also 1113 * see that the root and dump devices for all configurations are there. 1114 */ 1115 int 1116 crosscheck(void) 1117 { 1118 struct config *cf; 1119 int errs; 1120 1121 errs = 0; 1122 if (TAILQ_EMPTY(&allcf)) { 1123 (void)fprintf(stderr, "%s has no configurations!\n", 1124 conffile); 1125 errs++; 1126 } 1127 TAILQ_FOREACH(cf, &allcf, cf_next) { 1128 if (cf->cf_root != NULL) { /* i.e., not root on ? */ 1129 errs += cfcrosscheck(cf, "root", cf->cf_root); 1130 errs += cfcrosscheck(cf, "dumps", cf->cf_dump); 1131 } 1132 } 1133 return (errs); 1134 } 1135 1136 /* 1137 * Check to see if there is a *'d unit with a needs-count file. 1138 */ 1139 int 1140 badstar(void) 1141 { 1142 struct devbase *d; 1143 struct deva *da; 1144 struct devi *i; 1145 int errs, n; 1146 1147 errs = 0; 1148 TAILQ_FOREACH(d, &allbases, d_next) { 1149 for (da = d->d_ahead; da != NULL; da = da->d_bsame) 1150 for (i = da->d_ihead; i != NULL; i = i->i_asame) { 1151 if (i->i_unit == STAR) 1152 goto aybabtu; 1153 } 1154 continue; 1155 aybabtu: 1156 if (ht_lookup(needcnttab, d->d_name)) { 1157 (void)fprintf(stderr, 1158 "config: %s's cannot be *'d until its driver is fixed\n", 1159 d->d_name); 1160 errs++; 1161 continue; 1162 } 1163 for (n = 0; i != NULL; i = i->i_alias) 1164 if (!i->i_collapsed) 1165 n++; 1166 if (n < 1) 1167 panic("badstar() n<1"); 1168 } 1169 return (errs); 1170 } 1171 1172 /* 1173 * Verify/create builddir if necessary, change to it, and verify srcdir. 1174 * This will be called when we see the first include. 1175 */ 1176 void 1177 setupdirs(void) 1178 { 1179 struct stat st; 1180 1181 /* srcdir must be specified if builddir is not specified or if 1182 * no configuration filename was specified. */ 1183 if ((builddir || strcmp(defbuilddir, ".") == 0) && !srcdir) { 1184 error("source directory must be specified"); 1185 exit(1); 1186 } 1187 1188 if (srcdir == NULL) 1189 srcdir = "../../../.."; 1190 if (builddir == NULL) 1191 builddir = defbuilddir; 1192 1193 if (stat(builddir, &st) != 0) { 1194 if (mkdir(builddir, 0777)) { 1195 (void)fprintf(stderr, "config: cannot create %s: %s\n", 1196 builddir, strerror(errno)); 1197 exit(2); 1198 } 1199 } else if (!S_ISDIR(st.st_mode)) { 1200 (void)fprintf(stderr, "config: %s is not a directory\n", 1201 builddir); 1202 exit(2); 1203 } 1204 if (chdir(builddir) != 0) { 1205 (void)fprintf(stderr, "config: cannot change to %s\n", 1206 builddir); 1207 exit(2); 1208 } 1209 if (stat(srcdir, &st) != 0 || !S_ISDIR(st.st_mode)) { 1210 (void)fprintf(stderr, "config: %s is not a directory\n", 1211 srcdir); 1212 exit(2); 1213 } 1214 } 1215 1216 /* 1217 * Write identifier from "ident" directive into file, for 1218 * newvers.sh to pick it up. 1219 */ 1220 int 1221 mkident(void) 1222 { 1223 FILE *fp; 1224 int error = 0; 1225 1226 (void)unlink("ident"); 1227 1228 if (ident == NULL) 1229 return (0); 1230 1231 if ((fp = fopen("ident", "w")) == NULL) { 1232 (void)fprintf(stderr, "config: cannot write ident: %s\n", 1233 strerror(errno)); 1234 return (1); 1235 } 1236 if (vflag) 1237 (void)printf("using ident '%s'\n", ident); 1238 if (fprintf(fp, "%s\n", ident) < 0) 1239 error = 1; 1240 (void)fclose(fp); 1241 1242 return error; 1243 } 1244 1245 void 1246 logconfig_start(void) 1247 { 1248 extern FILE *yyin; 1249 char line[1024]; 1250 const char *tmpdir; 1251 struct stat st; 1252 int fd; 1253 1254 if (yyin == NULL || fstat(fileno(yyin), &st) == -1) 1255 return; 1256 cfgtime = st.st_mtime; 1257 1258 tmpdir = getenv("TMPDIR"); 1259 if (tmpdir == NULL) 1260 tmpdir = "/tmp"; 1261 snprintf(line, sizeof(line), "%s/config.tmp.XXXXXX", tmpdir); 1262 if ((fd = mkstemp(line)) == -1 || 1263 (cfg = fdopen(fd, "r+")) == NULL) { 1264 if (fd != -1) { 1265 unlink(line); 1266 close(fd); 1267 } 1268 cfg = NULL; 1269 return; 1270 } 1271 unlink(line); 1272 1273 (void)fprintf(cfg, "#include \"opt_config.h\"\n"); 1274 (void)fprintf(cfg, "\n"); 1275 (void)fprintf(cfg, "/*\n"); 1276 (void)fprintf(cfg, " * Add either (or both) of\n"); 1277 (void)fprintf(cfg, " *\n"); 1278 (void)fprintf(cfg, " *\toptions %s\n", LOGCONFIG_LARGE); 1279 (void)fprintf(cfg, " *\toptions %s\n", LOGCONFIG_SMALL); 1280 (void)fprintf(cfg, " *\n"); 1281 (void)fprintf(cfg, 1282 " * to your kernel config file to embed it in the resulting\n"); 1283 (void)fprintf(cfg, 1284 " * kernel. The latter option does not include files that are\n"); 1285 (void)fprintf(cfg, 1286 " * included (recursively) by your config file. The embedded\n"); 1287 (void)fprintf(cfg, 1288 " * data be extracted by using the command:\n"); 1289 (void)fprintf(cfg, " *\n"); 1290 (void)fprintf(cfg, 1291 " *\tstrings netbsd | sed -n 's/^_CFG_//p' | unvis\n"); 1292 (void)fprintf(cfg, " */\n"); 1293 (void)fprintf(cfg, "\n"); 1294 (void)fprintf(cfg, "#ifdef CONFIG_FILE\n"); 1295 (void)fprintf(cfg, "#if defined(%s) || defined(%s)\n\n", 1296 LOGCONFIG_LARGE, LOGCONFIG_SMALL); 1297 (void)fprintf(cfg, 1298 "static const char config[]\n#ifdef __vax__\n" 1299 "\t__attribute__((__unused__))\n#else\n" 1300 "\t__attribute__((__used__))\n#endif\n\t=\n\n"); 1301 1302 (void)fprintf(cfg, "#ifdef %s\n\n", LOGCONFIG_LARGE); 1303 (void)fprintf(cfg, "\"_CFG_### START CONFIG FILE \\\"%s\\\"\\n\"\n\n", 1304 conffile); 1305 (void)fprintf(cfg, "#endif /* %s */\n\n", LOGCONFIG_LARGE); 1306 1307 logconfig_include(yyin, NULL); 1308 1309 (void)fprintf(cfg, "#ifdef %s\n\n", LOGCONFIG_LARGE); 1310 (void)fprintf(cfg, "\"_CFG_### END CONFIG FILE \\\"%s\\\"\\n\"\n", 1311 conffile); 1312 1313 rewind(yyin); 1314 } 1315 1316 void 1317 logconfig_include(FILE *cf, const char *filename) 1318 { 1319 char line[1024], in[2048], *out; 1320 struct stat st; 1321 int missingeol; 1322 1323 if (!cfg) 1324 return; 1325 1326 missingeol = 0; 1327 if (fstat(fileno(cf), &st) == -1) 1328 return; 1329 if (cfgtime < st.st_mtime) 1330 cfgtime = st.st_mtime; 1331 1332 if (filename) 1333 (void)fprintf(cfg, 1334 "\"_CFG_### (included from \\\"%s\\\")\\n\"\n", 1335 filename); 1336 while (fgets(line, sizeof(line), cf) != NULL) { 1337 missingeol = 1; 1338 (void)fprintf(cfg, "\"_CFG_"); 1339 if (filename) 1340 (void)fprintf(cfg, "###> "); 1341 strvis(in, line, VIS_TAB); 1342 for (out = in; *out; out++) 1343 switch (*out) { 1344 case '\n': 1345 (void)fprintf(cfg, "\\n\"\n"); 1346 missingeol = 0; 1347 break; 1348 case '"': case '\\': 1349 (void)fputc('\\', cfg); 1350 /* FALLTHROUGH */ 1351 default: 1352 (void)fputc(*out, cfg); 1353 break; 1354 } 1355 } 1356 if (missingeol) { 1357 (void)fprintf(cfg, "\\n\"\n"); 1358 (void)fprintf(stderr, 1359 "config: %s: newline missing at EOF\n", 1360 filename != NULL ? filename : conffile); 1361 } 1362 if (filename) 1363 (void)fprintf(cfg, "\"_CFG_### (end include \\\"%s\\\")\\n\"\n", 1364 filename); 1365 1366 rewind(cf); 1367 } 1368 1369 void 1370 logconfig_end(void) 1371 { 1372 char line[1024]; 1373 FILE *fp; 1374 struct stat st; 1375 1376 if (!cfg) 1377 return; 1378 1379 (void)fprintf(cfg, "#endif /* %s */\n", LOGCONFIG_LARGE); 1380 (void)fprintf(cfg, ";\n"); 1381 (void)fprintf(cfg, "#endif /* %s || %s */\n", 1382 LOGCONFIG_LARGE, LOGCONFIG_SMALL); 1383 (void)fprintf(cfg, "#endif /* CONFIG_FILE */\n"); 1384 rewind(cfg); 1385 1386 if (stat("config_file.h", &st) != -1) { 1387 if (cfgtime < st.st_mtime) { 1388 fclose(cfg); 1389 return; 1390 } 1391 } 1392 1393 fp = fopen("config_file.h", "w"); 1394 if(!fp) { 1395 (void)fprintf(stderr, 1396 "config: cannot write to \"config_file.h\"\n"); 1397 exit(1); 1398 } 1399 1400 while (fgets(line, sizeof(line), cfg) != NULL) 1401 fputs(line, fp); 1402 fclose(fp); 1403 fclose(cfg); 1404 } 1405 1406 static const char * 1407 strtolower(const char *name) 1408 { 1409 const char *n; 1410 char *p, low[500]; 1411 unsigned char c; 1412 1413 for (n = name, p = low; (c = *n) != '\0'; n++) 1414 *p++ = isupper(c) ? tolower(c) : c; 1415 *p = 0; 1416 return (intern(low)); 1417 } 1418 1419 static int 1420 is_elf(const char *file) 1421 { 1422 int kernel; 1423 char hdr[4]; 1424 1425 kernel = open(file, O_RDONLY); 1426 if (kernel == -1) { 1427 fprintf(stderr, "config: cannot open %s: %s\n", file, 1428 strerror(errno)); 1429 exit(2); 1430 } 1431 if (read(kernel, hdr, 4) == -1) { 1432 fprintf(stderr, "config: cannot read from %s: %s\n", file, 1433 strerror(errno)); 1434 exit(2); 1435 } 1436 close(kernel); 1437 1438 return memcmp("\177ELF", hdr, 4) == 0 ? 1 : 0; 1439 } 1440 1441 static int 1442 extract_config(const char *kname, const char *cname, int cfd) 1443 { 1444 char *ptr; 1445 int found, kfd, i; 1446 struct stat st; 1447 1448 found = 0; 1449 1450 /* mmap(2) binary kernel */ 1451 kfd = open(conffile, O_RDONLY); 1452 if (kfd == -1) { 1453 fprintf(stderr, "config: cannot open %s: %s\n", kname, 1454 strerror(errno)); 1455 exit(2); 1456 } 1457 if ((fstat(kfd, &st) == -1)) { 1458 fprintf(stderr, "config: cannot stat %s: %s\n", kname, 1459 strerror(errno)); 1460 exit(2); 1461 } 1462 ptr = (char *)mmap(0, st.st_size, PROT_READ, MAP_FILE | MAP_SHARED, 1463 kfd, 0); 1464 if (ptr == MAP_FAILED) { 1465 fprintf(stderr, "config: cannot mmap %s: %s\n", kname, 1466 strerror(errno)); 1467 exit(2); 1468 } 1469 1470 /* Scan mmap(2)'ed region, extracting kernel configuration */ 1471 for (i = 0; i < st.st_size; i++) { 1472 if ((*ptr == '_') && (st.st_size - i > 5) && memcmp(ptr, 1473 "_CFG_", 5) == 0) { 1474 /* Line found */ 1475 char *oldptr, line[LINE_MAX + 1], uline[LINE_MAX + 1]; 1476 int j; 1477 1478 found = 1; 1479 1480 oldptr = (ptr += 5); 1481 while (*ptr != '\n' && *ptr != '\0') ptr++; 1482 if (ptr - oldptr > LINE_MAX) { 1483 fprintf(stderr, "config: line too long\n"); 1484 exit(2); 1485 } 1486 i += ptr - oldptr + 5; 1487 memcpy(line, oldptr, (ptr - oldptr)); 1488 line[ptr - oldptr] = '\0'; 1489 j = strunvis(uline, line); 1490 if (j == -1) { 1491 fprintf(stderr, "config: unvis: invalid " 1492 "encoded sequence\n"); 1493 exit(2); 1494 } 1495 uline[j] = '\n'; 1496 if (write(cfd, uline, j + 1) == -1) { 1497 fprintf(stderr, "config: cannot write to %s: " 1498 "%s\n", cname, strerror(errno)); 1499 exit(2); 1500 } 1501 } else ptr++; 1502 } 1503 1504 close(kfd); 1505 1506 return found; 1507 } 1508 1509 struct dhdi_params { 1510 struct devbase *d; 1511 int unit; 1512 int level; 1513 }; 1514 1515 static int 1516 devbase_has_dead_instances(const char *key, void *value, void *aux) 1517 { 1518 struct devi *i; 1519 struct dhdi_params *dhdi = aux; 1520 1521 for (i = value; i != NULL; i = i->i_alias) 1522 if (i->i_base == dhdi->d && 1523 (dhdi->unit == WILD || dhdi->unit == i->i_unit || 1524 i->i_unit == STAR) && 1525 i->i_level >= dhdi->level) 1526 return 1; 1527 return 0; 1528 } 1529 1530 /* 1531 * This is almost the same as devbase_has_instances, except it 1532 * may have special considerations regarding ignored instances. 1533 */ 1534 1535 static int 1536 devbase_has_any_instance(struct devbase *dev, int unit, int state, int level) 1537 { 1538 struct deva *da; 1539 struct devi *i; 1540 1541 if (dev->d_ispseudo) { 1542 if (dev->d_ihead != NULL) 1543 return 1; 1544 else if (state != DEVI_IGNORED) 1545 return 0; 1546 if ((i = ht_lookup(deaddevitab, dev->d_name)) == NULL) 1547 return 0; 1548 return (i->i_level >= level); 1549 } 1550 1551 for (da = dev->d_ahead; da != NULL; da = da->d_bsame) 1552 for (i = da->d_ihead; i != NULL; i = i->i_asame) 1553 if ((i->i_active == DEVI_ACTIVE || 1554 i->i_active == state) && 1555 (unit == WILD || unit == i->i_unit || 1556 i->i_unit == STAR)) 1557 return 1; 1558 1559 if (state == DEVI_IGNORED) { 1560 struct dhdi_params dhdi = { dev, unit, level }; 1561 /* also check dead devices */ 1562 return ht_enumerate(deaddevitab, devbase_has_dead_instances, 1563 &dhdi); 1564 } 1565 1566 return 0; 1567 } 1568 1569 /* 1570 * check_dead_devi(), used with ht_enumerate, checks if any of the removed 1571 * device instances would have been a valid instance considering the devbase, 1572 * the parent device and the interface attribute. 1573 * 1574 * In other words, for a non-active device, it checks if children would be 1575 * actual orphans or the result of a negative statement in the config file. 1576 */ 1577 1578 struct cdd_params { 1579 struct devbase *d; 1580 struct attr *at; 1581 struct devbase *parent; 1582 }; 1583 1584 static int 1585 check_dead_devi(const char *key, void *value, void *aux) 1586 { 1587 struct cdd_params *cdd = aux; 1588 struct devi *i = value; 1589 struct pspec *p; 1590 1591 if (i->i_base != cdd->d) 1592 return 0; 1593 1594 for (; i != NULL; i = i->i_alias) { 1595 p = i->i_pspec; 1596 if ((p == NULL && cdd->at == NULL) || 1597 (p != NULL && p->p_iattr == cdd->at && 1598 (p->p_atdev == NULL || p->p_atdev == cdd->parent))) { 1599 if (p != NULL && 1600 !devbase_has_any_instance(cdd->parent, p->p_atunit, 1601 DEVI_IGNORED, i->i_level)) 1602 return 0; 1603 else 1604 return 1; 1605 } 1606 } 1607 return 0; 1608 } 1609 1610 static void 1611 do_kill_orphans(struct devbase *d, struct attr *at, struct devbase *parent, 1612 int state) 1613 { 1614 struct nvlist *nv, *nv1; 1615 struct attr *a; 1616 struct devi *i, *j = NULL; 1617 struct pspec *p; 1618 int active = 0; 1619 1620 /* 1621 * A pseudo-device will always attach at root, and if it has an 1622 * instance (it cannot have more than one), it is enough to consider 1623 * it active, as there is no real attachment. 1624 * 1625 * A pseudo device can never be marked DEVI_IGNORED. 1626 */ 1627 if (d->d_ispseudo) { 1628 if (d->d_ihead != NULL) 1629 d->d_ihead->i_active = active = DEVI_ACTIVE; 1630 else { 1631 if (ht_lookup(deaddevitab, d->d_name) != NULL) 1632 active = DEVI_IGNORED; 1633 else 1634 return; 1635 } 1636 } else { 1637 int seen = 0; 1638 1639 for (i = d->d_ihead; i != NULL; i = i->i_bsame) { 1640 for (j = i; j != NULL; j = j->i_alias) { 1641 p = j->i_pspec; 1642 if ((p == NULL && at == NULL) || 1643 (p != NULL && p->p_iattr == at && 1644 (p->p_atdev == NULL || 1645 p->p_atdev == parent))) { 1646 if (p != NULL && 1647 !devbase_has_any_instance(parent, 1648 p->p_atunit, state, j->i_level)) 1649 continue; 1650 /* 1651 * There are Fry-like devices which can 1652 * be their own grand-parent (or even 1653 * parent, like uhub). We don't want 1654 * to loop, so if we've already reached 1655 * an instance for one reason or 1656 * another, stop there. 1657 */ 1658 if (j->i_active == DEVI_ACTIVE || 1659 j->i_active == state) { 1660 /* 1661 * Device has already been 1662 * seen. However it might 1663 * have siblings who still 1664 * have to be activated or 1665 * orphaned. 1666 */ 1667 seen = 1; 1668 continue; 1669 } 1670 j->i_active = active = state; 1671 if (p != NULL) 1672 p->p_active = state; 1673 } 1674 } 1675 } 1676 /* 1677 * If we've been there but have made no change, stop. 1678 */ 1679 if (seen && !active) 1680 return; 1681 if (!active) { 1682 struct cdd_params cdd = { d, at, parent }; 1683 /* Look for a matching dead devi */ 1684 if (ht_enumerate(deaddevitab, check_dead_devi, &cdd) && 1685 d != parent) 1686 /* 1687 * That device had its instances removed. 1688 * Continue the loop marking descendants 1689 * with DEVI_IGNORED instead of DEVI_ACTIVE. 1690 * 1691 * There is one special case for devices that 1692 * are their own parent: if that instance is 1693 * removed (e.g., no uhub* at uhub?), we don't 1694 * have to continue looping. 1695 */ 1696 active = DEVI_IGNORED; 1697 else 1698 return; 1699 } 1700 } 1701 1702 for (nv = d->d_attrs; nv != NULL; nv = nv->nv_next) { 1703 a = nv->nv_ptr; 1704 for (nv1 = a->a_devs; nv1 != NULL; nv1 = nv1->nv_next) 1705 do_kill_orphans(nv1->nv_ptr, a, d, active); 1706 } 1707 } 1708 1709 static int 1710 kill_orphans_cb(const char *key, void *value, void *aux) 1711 { 1712 do_kill_orphans((struct devbase *)value, NULL, NULL, DEVI_ACTIVE); 1713 return 0; 1714 } 1715 1716 static void 1717 kill_orphans() 1718 { 1719 ht_enumerate(devroottab, kill_orphans_cb, NULL); 1720 } 1721