Home | History | Annotate | Line # | Download | only in config
mkioconf.c revision 1.29
      1 /*	$NetBSD: mkioconf.c,v 1.29 2015/08/20 09:44:24 christos 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: @(#)mkioconf.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: mkioconf.c,v 1.29 2015/08/20 09:44:24 christos Exp $");
     49 
     50 #include <sys/param.h>
     51 #include <err.h>
     52 #include <errno.h>
     53 #include <stdio.h>
     54 #include <stdlib.h>
     55 #include <string.h>
     56 #include "defs.h"
     57 
     58 /*
     59  * Make ioconf.c.
     60  */
     61 static int cf_locators_print(const char *, void *, void *);
     62 static int cforder(const void *, const void *);
     63 static void emitcfdata(FILE *);
     64 static void emitcfdrivers(FILE *);
     65 static void emitexterns(FILE *);
     66 static void emitcfattachinit(FILE *);
     67 static void emithdr(FILE *);
     68 static void emitloc(FILE *);
     69 static void emitpseudo(FILE *);
     70 static void emitparents(FILE *);
     71 static void emitroots(FILE *);
     72 static void emitname2blk(FILE *);
     73 
     74 #define	SEP(pos, max)	(((u_int)(pos) % (max)) == 0 ? "\n\t" : " ")
     75 
     76 #define ARRNAME(n, l) (strchr((n), ARRCHR) && strncmp((n), (l), strlen((l))) == 0)
     77 
     78 /*
     79  * NEWLINE can only be used in the emitXXX functions.
     80  * In most cases it can be subsumed into an fprintf.
     81  */
     82 #define	NEWLINE		putc('\n', fp)
     83 
     84 int
     85 mkioconf(void)
     86 {
     87 	FILE *fp;
     88 
     89 	qsort(packed, npacked, sizeof *packed, cforder);
     90 	if ((fp = fopen("ioconf.c.tmp", "w")) == NULL) {
     91 		warn("cannot write ioconf.c");
     92 		return (1);
     93 	}
     94 
     95 	fprintf(fp, "#include \"ioconf.h\"\n");
     96 
     97 	emithdr(fp);
     98 	emitcfdrivers(fp);
     99 	emitexterns(fp);
    100 	emitloc(fp);
    101 	emitparents(fp);
    102 	emitcfdata(fp);
    103 	emitcfattachinit(fp);
    104 
    105 	if (ioconfname == NULL) {
    106 		emitroots(fp);
    107 		emitpseudo(fp);
    108 		if (!do_devsw)
    109 			emitname2blk(fp);
    110 	}
    111 
    112 	fflush(fp);
    113 	if (ferror(fp)) {
    114 		warn("error writing ioconf.c");
    115 		(void)fclose(fp);
    116 #if 0
    117 		(void)unlink("ioconf.c.tmp");
    118 #endif
    119 		return (1);
    120 	}
    121 
    122 	(void)fclose(fp);
    123 	if (moveifchanged("ioconf.c.tmp", "ioconf.c") != 0) {
    124 		warn("error renaming ioconf.c");
    125 		return (1);
    126 	}
    127 	return (0);
    128 }
    129 
    130 static int
    131 cforder(const void *a, const void *b)
    132 {
    133 	int n1, n2;
    134 
    135 	n1 = (*(const struct devi * const *)a)->i_cfindex;
    136 	n2 = (*(const struct devi * const *)b)->i_cfindex;
    137 	return (n1 - n2);
    138 }
    139 
    140 static void
    141 emithdr(FILE *ofp)
    142 {
    143 	FILE *ifp;
    144 	size_t n;
    145 	char ifnbuf[200], buf[BUFSIZ];
    146 	char *ifn;
    147 
    148 	autogen_comment(ofp, "ioconf.c");
    149 
    150 	(void)snprintf(ifnbuf, sizeof(ifnbuf), "arch/%s/conf/ioconf.incl.%s",
    151 	    machine ? machine : "(null)", machine ? machine : "(null)");
    152 	ifn = sourcepath(ifnbuf);
    153 	if ((ifp = fopen(ifn, "r")) != NULL) {
    154 		while ((n = fread(buf, 1, sizeof(buf), ifp)) > 0)
    155 			(void)fwrite(buf, 1, n, ofp);
    156 		if (ferror(ifp))
    157 			err(EXIT_FAILURE, "error reading %s", ifn);
    158 		(void)fclose(ifp);
    159 	} else {
    160 		fputs("#include <sys/param.h>\n"
    161 			"#include <sys/conf.h>\n"
    162 			"#include <sys/device.h>\n"
    163 			"#include <sys/mount.h>\n", ofp);
    164 	}
    165 	free(ifn);
    166 }
    167 
    168 /*
    169  * Emit an initialized array of character strings describing this
    170  * attribute's locators.
    171  */
    172 static int
    173 cf_locators_print(const char *name, void *value, void *arg)
    174 {
    175 	struct attr *a;
    176 	struct loclist *ll;
    177 	FILE *fp = arg;
    178 
    179 	a = value;
    180 	if (!a->a_iattr)
    181 		return (0);
    182 	if (ht_lookup(selecttab, name) == NULL)
    183 		return (0);
    184 
    185 	if (a->a_locs) {
    186 		fprintf(fp,
    187 		    "static const struct cfiattrdata %scf_iattrdata = {\n",
    188 			    name);
    189 		fprintf(fp, "\t\"%s\", %d, {\n", name, a->a_loclen);
    190 		for (ll = a->a_locs; ll; ll = ll->ll_next)
    191 			fprintf(fp, "\t\t{ \"%s\", \"%s\", %s },\n",
    192 				ll->ll_name,
    193 				(ll->ll_string ? ll->ll_string : "NULL"),
    194 				(ll->ll_string ? ll->ll_string : "0"));
    195 		fprintf(fp, "\t}\n};\n");
    196 	} else {
    197 		fprintf(fp,
    198 		    "static const struct cfiattrdata %scf_iattrdata = {\n"
    199 		    "\t\"%s\", 0, {\n\t\t{ NULL, NULL, 0 },\n\t}\n};\n",
    200 		    name, name);
    201 	}
    202 
    203 	return 0;
    204 }
    205 
    206 static void
    207 emitcfdrivers(FILE *fp)
    208 {
    209 	struct devbase *d;
    210 	struct attrlist *al;
    211 	struct attr *a;
    212 	int has_iattrs;
    213 
    214 	NEWLINE;
    215 	ht_enumerate(attrtab, cf_locators_print, fp);
    216 
    217 	NEWLINE;
    218 	TAILQ_FOREACH(d, &allbases, d_next) {
    219 		if (!devbase_has_instances(d, WILD))
    220 			continue;
    221 		has_iattrs = 0;
    222 		for (al = d->d_attrs; al != NULL; al = al->al_next) {
    223 			a = al->al_this;
    224 			if (a->a_iattr == 0)
    225 				continue;
    226 			if (has_iattrs == 0)
    227 				fprintf(fp,
    228 			    	    "static const struct cfiattrdata * const %s_attrs[] = { ",
    229 			    	    d->d_name);
    230 			has_iattrs = 1;
    231 			fprintf(fp, "&%scf_iattrdata, ", a->a_name);
    232 		}
    233 		if (has_iattrs)
    234 			fprintf(fp, "NULL };\n");
    235 		fprintf(fp, "CFDRIVER_DECL(%s, %s, ", d->d_name, /* ) */
    236 		    d->d_classattr != NULL ? d->d_classattr->a_devclass
    237 					   : "DV_DULL");
    238 		if (has_iattrs)
    239 			fprintf(fp, "%s_attrs", d->d_name);
    240 		else
    241 			fprintf(fp, "NULL");
    242 		fprintf(fp, /* ( */ ");\n\n");
    243 	}
    244 
    245 	NEWLINE;
    246 
    247 	fprintf(fp,
    248 	    "%sstruct cfdriver * const cfdriver_%s_%s[] = {\n",
    249 	    ioconfname ? "static " : "",
    250 	    ioconfname ? "ioconf" : "list",
    251 	    ioconfname ? ioconfname : "initial");
    252 
    253 	TAILQ_FOREACH(d, &allbases, d_next) {
    254 		if (!devbase_has_instances(d, WILD))
    255 			continue;
    256 		fprintf(fp, "\t&%s_cd,\n", d->d_name);
    257 	}
    258 	fprintf(fp, "\tNULL\n};\n");
    259 }
    260 
    261 static void
    262 emitexterns(FILE *fp)
    263 {
    264 	struct deva *da;
    265 
    266 	NEWLINE;
    267 	TAILQ_FOREACH(da, &alldevas, d_next) {
    268 		if (!deva_has_instances(da, WILD))
    269 			continue;
    270 		fprintf(fp, "extern struct cfattach %s_ca;\n",
    271 			    da->d_name);
    272 	}
    273 }
    274 
    275 static void
    276 emitcfattachinit(FILE *fp)
    277 {
    278 	struct devbase *d;
    279 	struct deva *da;
    280 
    281 	NEWLINE;
    282 	TAILQ_FOREACH(d, &allbases, d_next) {
    283 		if (!devbase_has_instances(d, WILD))
    284 			continue;
    285 		if (d->d_ahead == NULL)
    286 			continue;
    287 
    288 		fprintf(fp,
    289 		    "static struct cfattach * const %s_cfattachinit[] = {\n\t",
    290 			    d->d_name);
    291 		for (da = d->d_ahead; da != NULL; da = da->d_bsame) {
    292 			if (!deva_has_instances(da, WILD))
    293 				continue;
    294 			fprintf(fp, "&%s_ca, ", da->d_name);
    295 		}
    296 		fprintf(fp, "NULL\n};\n");
    297 	}
    298 
    299 	NEWLINE;
    300 	fprintf(fp, "%sconst struct cfattachinit cfattach%s%s[] = {\n",
    301 	    ioconfname ? "static " : "",
    302 	    ioconfname ? "_ioconf_" : "init",
    303 	    ioconfname ? ioconfname : "");
    304 
    305 	TAILQ_FOREACH(d, &allbases, d_next) {
    306 		if (!devbase_has_instances(d, WILD))
    307 			continue;
    308 		if (d->d_ahead == NULL)
    309 			continue;
    310 
    311 		fprintf(fp, "\t{ \"%s\", %s_cfattachinit },\n",
    312 			    d->d_name, d->d_name);
    313 	}
    314 
    315 	fprintf(fp, "\t{ NULL, NULL }\n};\n");
    316 }
    317 
    318 static void
    319 emitloc(FILE *fp)
    320 {
    321 	int i;
    322 
    323 	if (locators.used != 0) {
    324 		fprintf(fp, "\n/* locators */\n"
    325 			"static int loc[%d] = {", locators.used);
    326 		for (i = 0; i < locators.used; i++)
    327 			fprintf(fp, "%s%s,", SEP(i, 8), locators.vec[i]);
    328 		fprintf(fp, "\n};\n");
    329 	}
    330 }
    331 
    332 /*
    333  * Emit static parent data.
    334  */
    335 static void
    336 emitparents(FILE *fp)
    337 {
    338 	struct pspec *p;
    339 
    340 	NEWLINE;
    341 	TAILQ_FOREACH(p, &allpspecs, p_list) {
    342 		if (p->p_devs == NULL || p->p_active != DEVI_ACTIVE)
    343 			continue;
    344 		fprintf(fp,
    345 		    "static const struct cfparent pspec%d = {\n", p->p_inst);
    346 		fprintf(fp, "\t\"%s\", ", p->p_iattr->a_name);
    347 		if (p->p_atdev != NULL) {
    348 			fprintf(fp, "\"%s\", ", p->p_atdev->d_name);
    349 			if (p->p_atunit == WILD)
    350 				fprintf(fp, "DVUNIT_ANY");
    351 			else
    352 				fprintf(fp, "%d", p->p_atunit);
    353 		} else
    354 			fprintf(fp, "NULL, 0");
    355 		fprintf(fp, "\n};\n");
    356 	}
    357 }
    358 
    359 /*
    360  * Emit the cfdata array.
    361  */
    362 static void
    363 emitcfdata(FILE *fp)
    364 {
    365 	struct devi **p, *i;
    366 	struct pspec *ps;
    367 	int unit, v;
    368 	const char *state, *basename, *attachment;
    369 	struct loclist *ll;
    370 	struct attr *a;
    371 	const char *loc;
    372 	char locbuf[20];
    373 	const char *lastname = "";
    374 
    375 	fprintf(fp, "\n"
    376 		"#define NORM FSTATE_NOTFOUND\n"
    377 		"#define STAR FSTATE_STAR\n"
    378 		"\n"
    379 		"%sstruct cfdata cfdata%s%s[] = {\n"
    380 		"    /* driver           attachment    unit state "
    381 		"     loc   flags  pspec */\n",
    382 		    ioconfname ? "static " : "",
    383 		    ioconfname ? "_ioconf_" : "",
    384 		    ioconfname ? ioconfname : "");
    385 	for (p = packed; (i = *p) != NULL; p++) {
    386 		/* the description */
    387 		fprintf(fp, "/*%3d: %s at ", i->i_cfindex, i->i_name);
    388 		if ((ps = i->i_pspec) != NULL) {
    389 			if (ps->p_atdev != NULL &&
    390 			    ps->p_atunit != WILD) {
    391 				fprintf(fp, "%s%d", ps->p_atdev->d_name,
    392 					    ps->p_atunit);
    393 			} else if (ps->p_atdev != NULL) {
    394 				fprintf(fp, "%s?", ps->p_atdev->d_name);
    395 			} else {
    396 				fprintf(fp, "%s?", ps->p_iattr->a_name);
    397 			}
    398 
    399 			a = ps->p_iattr;
    400 			for (ll = a->a_locs, v = 0; ll != NULL;
    401 			     ll = ll->ll_next, v++) {
    402 				if (ARRNAME(ll->ll_name, lastname)) {
    403 					fprintf(fp, " %s %s",
    404 					    ll->ll_name, i->i_locs[v]);
    405 				} else {
    406 					fprintf(fp, " %s %s",
    407 						    ll->ll_name,
    408 						    i->i_locs[v]);
    409 					lastname = ll->ll_name;
    410 				}
    411 			}
    412 		} else {
    413 			a = NULL;
    414 			fputs("root", fp);
    415 		}
    416 
    417 		fputs(" */\n", fp);
    418 
    419 		/* then the actual defining line */
    420 		basename = i->i_base->d_name;
    421 		attachment = i->i_atdeva->d_name;
    422 		if (i->i_unit == STAR) {
    423 			unit = i->i_base->d_umax;
    424 			state = "STAR";
    425 		} else {
    426 			unit = i->i_unit;
    427 			state = "NORM";
    428 		}
    429 		if (i->i_locoff >= 0) {
    430 			(void)snprintf(locbuf, sizeof(locbuf), "loc+%3d",
    431 			    i->i_locoff);
    432 			loc = locbuf;
    433 		} else
    434 			loc = "NULL";
    435 		fprintf(fp, "    { \"%s\",%s\"%s\",%s%2d, %s, %7s, %#6x, ",
    436 			    basename, strlen(basename) < 7 ? "\t\t"
    437 			    				   : "\t",
    438 			    attachment, strlen(attachment) < 5 ? "\t\t"
    439 			    				       : "\t",
    440 			    unit, state, loc, i->i_cfflags);
    441 		if (ps != NULL)
    442 			fprintf(fp, "&pspec%d },\n", ps->p_inst);
    443 		else
    444 			fputs("NULL },\n", fp);
    445 	}
    446 	fprintf(fp, "    { %s,%s%s,%s%2d, %s, %7s, %#6x, %s }\n};\n",
    447 	    "NULL", "\t\t", "NULL", "\t\t", 0, "   0", "NULL", 0, "NULL");
    448 }
    449 
    450 /*
    451  * Emit the table of potential roots.
    452  */
    453 static void
    454 emitroots(FILE *fp)
    455 {
    456 	struct devi **p, *i;
    457 
    458 	fputs("\nconst short cfroots[] = {\n", fp);
    459 	for (p = packed; (i = *p) != NULL; p++) {
    460 		if (i->i_at != NULL)
    461 			continue;
    462 		if (i->i_unit != 0 &&
    463 		    (i->i_unit != STAR || i->i_base->d_umax != 0))
    464 			warnx("warning: `%s at root' is not unit 0", i->i_name);
    465 		fprintf(fp, "\t%2d /* %s */,\n",
    466 		    i->i_cfindex, i->i_name);
    467 	}
    468 	fputs("\t-1\n};\n", fp);
    469 }
    470 
    471 /*
    472  * Emit pseudo-device initialization.
    473  */
    474 static void
    475 emitpseudo(FILE *fp)
    476 {
    477 	struct devi *i;
    478 	struct devbase *d;
    479 
    480 	fputs("\n/* pseudo-devices */\n", fp);
    481 	fputs("\nconst struct pdevinit pdevinit[] = {\n", fp);
    482 	TAILQ_FOREACH(i, &allpseudo, i_next) {
    483 		d = i->i_base;
    484 		fprintf(fp, "\t{ %sattach, %d },\n",
    485 		    d->d_name, d->d_umax);
    486 	}
    487 	fputs("\t{ 0, 0 }\n};\n", fp);
    488 }
    489 
    490 /*
    491  * Emit name to major block number table.
    492  */
    493 void
    494 emitname2blk(FILE *fp)
    495 {
    496 	struct devbase *dev;
    497 
    498 	fputs("\n/* device name to major block number */\n", fp);
    499 
    500 	fprintf(fp, "struct devnametobdevmaj dev_name2blk[] = {\n");
    501 
    502 	TAILQ_FOREACH(dev, &allbases, d_next) {
    503 		if (dev->d_major == NODEVMAJOR)
    504 			continue;
    505 
    506 		fprintf(fp, "\t{ \"%s\", %d },\n",
    507 			    dev->d_name, dev->d_major);
    508 	}
    509 	fprintf(fp, "\t{ NULL, 0 }\n};\n");
    510 }
    511