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