1 /*	$OpenBSD: mkioconf.c,v 1.27 2005/01/02 21:59:33 deraadt Exp $	*/
2 /*	$NetBSD: mkioconf.c,v 1.41 1996/11/11 14:18:49 mycroft Exp $	*/
3 
4 /*
5  * Copyright (c) 1992, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This software was developed by the Computer Systems Engineering group
9  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
10  * contributed to Berkeley.
11  *
12  * All advertising materials mentioning features or use of this software
13  * must display the following acknowledgement:
14  *	This product includes software developed by the University of
15  *	California, Lawrence Berkeley Laboratories.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  * 3. Neither the name of the University nor the names of its contributors
26  *    may be used to endorse or promote products derived from this software
27  *    without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39  * SUCH DAMAGE.
40  *
41  *	from: @(#)mkioconf.c	8.1 (Berkeley) 6/6/93
42  */
43 
44 #include <sys/param.h>
45 #include <errno.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include "config.h"
50 
51 /*
52  * Make ioconf.c.
53  */
54 static int cforder(const void *, const void *);
55 static int emitcfdata(FILE *);
56 static int emitexterns(FILE *);
57 static int emithdr(FILE *);
58 static int emitloc(FILE *);
59 static int emitlocnames(FILE *);
60 static int emitpseudo(FILE *);
61 static int emitpv(FILE *);
62 static int emitroots(FILE *);
63 short addlocname(const char *);
64 void addlocnami(short);
65 
66 #define	SEP(pos, max)	(((u_int)(pos) % (max)) == 0 ? "\n\t" : " ")
67 
68 /*
69  * NEWLINE can only be used in the emitXXX functions.
70  * In most cases it can be subsumed into an fprintf.
71  */
72 #define	NEWLINE		if (putc('\n', fp) < 0) return (1)
73 
74 int
mkioconf(void)75 mkioconf(void)
76 {
77 	FILE *fp;
78 	int v;
79 
80 	qsort(packed, npacked, sizeof *packed, cforder);
81 	if ((fp = fopen("ioconf.c", "w")) == NULL) {
82 		(void)fprintf(stderr, "config: cannot write ioconf.c: %s\n",
83 		    strerror(errno));
84 		return (1);
85 	}
86 	v = emithdr(fp);
87 	if (v != 0 || emitexterns(fp) || emitloc(fp) ||
88 	    emitlocnames(fp) || emitpv(fp) || emitcfdata(fp) ||
89 	    emitroots(fp) || emitpseudo(fp)) {
90 		if (v >= 0)
91 			(void)fprintf(stderr,
92 			    "config: error writing ioconf.c: %s\n",
93 			    strerror(errno));
94 		(void)fclose(fp);
95 		/* (void)unlink("ioconf.c"); */
96 		return (1);
97 	}
98 	(void)fclose(fp);
99 	return (0);
100 }
101 
102 static int
cforder(const void * a,const void * b)103 cforder(const void *a, const void *b)
104 {
105 	int n1, n2;
106 
107 	n1 = (*(struct devi * const *)a)->i_cfindex;
108 	n2 = (*(struct devi * const *)b)->i_cfindex;
109 	return (n1 - n2);
110 }
111 
112 static int
emithdr(FILE * ofp)113 emithdr(FILE *ofp)
114 {
115 	FILE *ifp;
116 	size_t n;
117 	char ifn[200], buf[BUFSIZ];
118 
119 	if (fprintf(ofp, "\
120 /*\n\
121  * MACHINE GENERATED: DO NOT EDIT\n\
122  *\n\
123  * ioconf.c, from \"%s\"\n\
124  */\n\n", conffile) < 0)
125 		return (1);
126 	(void)snprintf(ifn, sizeof ifn, "ioconf.incl.%s", machine);
127 	if ((ifp = fopen(ifn, "r")) != NULL) {
128 		while ((n = fread(buf, 1, sizeof(buf), ifp)) > 0)
129 			if (fwrite(buf, 1, n, ofp) != n)
130 				return (1);
131 		if (ferror(ifp)) {
132 			(void)fprintf(stderr, "config: error reading %s: %s\n",
133 			    ifn, strerror(errno));
134 			(void)fclose(ifp);
135 			return (-1);
136 		}
137 		(void)fclose(ifp);
138 	} else {
139 		if (fputs("\
140 #include <sys/param.h>\n\
141 #include <sys/device.h>\n", ofp) < 0)
142 			return (1);
143 	}
144 	return (0);
145 }
146 
147 static int
emitexterns(FILE * fp)148 emitexterns(FILE *fp)
149 {
150 	struct devbase *d;
151 	struct deva *da;
152 
153 	NEWLINE;
154 	for (d = allbases; d != NULL; d = d->d_next) {
155 		if (!devbase_has_instances(d, WILD))
156 			continue;
157 		if (fprintf(fp, "extern struct cfdriver %s_cd;\n",
158 			    d->d_name) < 0)
159 			return (1);
160 	}
161 	NEWLINE;
162 	for (da = alldevas; da != NULL; da = da->d_next) {
163 		if (!deva_has_instances(da, WILD))
164 			continue;
165 		if (fprintf(fp, "extern struct cfattach %s_ca;\n",
166 			    da->d_name) < 0)
167 			return (1);
168 	}
169 	NEWLINE;
170 	return (0);
171 }
172 
173 static int
emitloc(FILE * fp)174 emitloc(FILE *fp)
175 {
176 	int i;
177 
178 	if (fprintf(fp, "\n/* locators */\n\
179 static int loc[%d] = {", locators.used) < 0)
180 		return (1);
181 	for (i = 0; i < locators.used; i++)
182 		if (fprintf(fp, "%s%s,", SEP(i, 8), locators.vec[i]) < 0)
183 			return (1);
184 	if (fprintf(fp, "\n};\n") < 0)
185 		return(1);
186 	return (fprintf(fp, "\n#ifndef MAXEXTRALOC\n\
187 #define MAXEXTRALOC 32\n\
188 #endif\n\
189 int extraloc[MAXEXTRALOC] = { -1 };\n\
190 int nextraloc = MAXEXTRALOC;\n\
191 int uextraloc = 0;\n") < 0);
192 }
193 
194 static int nlocnames, maxlocnames = 8;
195 static const char **locnames;
196 
197 short
addlocname(const char * name)198 addlocname(const char *name)
199 {
200 	int i;
201 
202 	if (locnames == NULL || nlocnames+1 > maxlocnames) {
203 		maxlocnames *= 4;
204 		locnames = (const char **)erealloc(locnames,
205 		     maxlocnames * sizeof(char *));
206 	}
207 	for (i = 0; i < nlocnames; i++)
208 		if (strcmp(name, locnames[i]) == 0)
209 			return (i);
210 	/*printf("adding %s at %d\n", name, nlocnames);*/
211 	locnames[nlocnames++] = name;
212 	return (nlocnames - 1);
213 }
214 
215 static int nlocnami, maxlocnami = 8;
216 static short *locnami;
217 
218 void
addlocnami(short idx)219 addlocnami(short idx)
220 {
221 	if (locnami == NULL || nlocnami+1 > maxlocnami) {
222 		maxlocnami *= 4;
223 		locnami = (short *)erealloc(locnami, maxlocnami * sizeof(short));
224 	}
225 	locnami[nlocnami++] = idx;
226 }
227 
228 
229 /*
230  * Emit locator names
231  * XXX the locnamp[] table is not compressed like it should be!
232  */
233 static int
emitlocnames(FILE * fp)234 emitlocnames(FILE *fp)
235 {
236 	struct devi **p, *i;
237 	struct nvlist *nv;
238 	struct attr *a;
239 	int added, start;
240 	int v, j, x;
241 
242 #if 1
243 	addlocnami(-1);
244 	for (p = packed; (i = *p) != NULL; p++) {
245 		/*printf("child %s\n", i->i_name);*/
246 
247 		/* initialize all uninitialized parents */
248 		for (x = 0; x < i->i_pvlen; x++) {
249 			if (i->i_parents[x]->i_plocnami)
250 				continue;
251 			start = nlocnami;
252 
253 			/* add all the names */
254 			a = i->i_atattr;
255 			nv = a->a_locs;
256 			added = 0;
257 			for (nv = a->a_locs, v = 0; nv != NULL;
258 			    nv = nv->nv_next, v++) {
259 				addlocnami(addlocname(nv->nv_name));
260 				added = 1;
261 			}
262 			/* terminate list of names */
263 			if (added)
264 				addlocnami(-1);
265 			else
266 				start--;
267 
268 			/*printf("bus %s starts at %d\n", i->i_parents[x]->i_name,
269 			    start);*/
270 			i->i_parents[x]->i_plocnami = start;
271 
272 		}
273 	}
274 	for (p = packed; (i = *p) != NULL; p++)
275 		if (i->i_pvlen)
276 			i->i_locnami = i->i_parents[0]->i_plocnami;
277 #else
278 	addlocnami(-1);
279 	for (p = packed; (i = *p) != NULL; p++) {
280 
281 		i->i_locnami = nlocnami;
282 
283 		/* add all the names */
284 		a = i->i_atattr;
285 		nv = a->a_locs;
286 		for (nv = a->a_locs, v = 0; nv != NULL; nv = nv->nv_next, v++)
287 			addlocnami(addlocname(nv->nv_name));
288 
289 		/* terminate list of names */
290 		addlocnami(-1);
291 
292 	}
293 #endif
294 	if (fprintf(fp, "\nchar *locnames[] = {\n") < 0)
295 		return (1);
296 	for (j = 0; j < nlocnames; j++)
297 		if (fprintf(fp, "\t\"%s\",\n", locnames[j]) < 0)
298 			return (1);
299 	if (fprintf(fp, "};\n\n") < 0)
300 		return (1);
301 
302 	if (fprintf(fp,
303 	    "/* each entry is an index into locnames[]; -1 terminates */\n") < 0)
304 		return (1);
305 	if (fprintf(fp, "short locnamp[] = {") < 0)
306 		return (1);
307 	for (j = 0; j < nlocnami; j++)
308 		if (fprintf(fp, "%s%d,", SEP(j, 8), locnami[j]) < 0)
309 			return (1);
310 	return (fprintf(fp, "\n};\n") < 0);
311 }
312 
313 
314 /*
315  * Emit global parents-vector.
316  */
317 static int
emitpv(FILE * fp)318 emitpv(FILE *fp)
319 {
320 	int i;
321 
322 	if (fprintf(fp, "\n/* size of parent vectors */\n\
323 int pv_size = %d;\n", parents.used) < 0)
324 		return (1);
325 	if (fprintf(fp, "\n/* parent vectors */\n\
326 short pv[%d] = {", parents.used) < 0)
327 		return (1);
328 	for (i = 0; i < parents.used; i++)
329 		if (fprintf(fp, "%s%d,", SEP(i, 16), parents.vec[i]) < 0)
330 			return (1);
331 	return (fprintf(fp, "\n};\n") < 0);
332 }
333 
334 /*
335  * Emit the cfdata array.
336  */
337 static int
emitcfdata(FILE * fp)338 emitcfdata(FILE *fp)
339 {
340 	struct devi **p, *i;
341 	int unit, v;
342 	const char *vs, *state, *basename, *attachment;
343 	struct nvlist *nv;
344 	struct attr *a;
345 	const char *loc;
346 	char locbuf[20];
347 
348 	if (fprintf(fp, "\n\
349 #define NORM FSTATE_NOTFOUND\n\
350 #define STAR FSTATE_STAR\n\
351 #define DNRM FSTATE_DNOTFOUND\n\
352 #define DSTR FSTATE_DSTAR\n\
353 \n\
354 struct cfdata cfdata[] = {\n\
355     /* attachment       driver        unit  state loc     flags parents nm ivstubs starunit1 */\n") < 0)
356 		return (1);
357 	for (p = packed; (i = *p) != NULL; p++) {
358 		/* the description */
359 		if (fprintf(fp, "/*%3d: %s at ", i->i_cfindex, i->i_name) < 0)
360 			return (1);
361 		for (v = 0; v < i->i_pvlen; v++)
362 			if (fprintf(fp, "%s%s", v == 0 ? "" : "|",
363 			    i->i_parents[v]->i_name) < 0)
364 				return (1);
365 		if (v == 0 && fputs("root", fp) < 0)
366 			return (1);
367 		a = i->i_atattr;
368 		nv = a->a_locs;
369 		for (nv = a->a_locs, v = 0; nv != NULL; nv = nv->nv_next, v++)
370 			if (fprintf(fp, " %s %s",
371 			    nv->nv_name, i->i_locs[v]) < 0)
372 				return (1);
373 		if (fputs(" */\n", fp) < 0)
374 			return (-1);
375 
376 		/* then the actual defining line */
377 		basename = i->i_base->d_name;
378 		attachment = i->i_atdeva->d_name;
379 		if (i->i_unit == STAR) {
380 			unit = i->i_base->d_umax;
381 			if (i->i_disable) {
382 				state = "DSTR";
383 			} else {
384 				state = "STAR";
385 			}
386 		} else {
387 			unit = i->i_unit;
388 			if (i->i_disable) {
389 				state = "DNRM";
390 			} else {
391 				state = "NORM";
392 			}
393 		}
394 		vs = "";
395 		v = 0;
396 		if (i->i_locoff >= 0) {
397 			(void)snprintf(locbuf, sizeof locbuf, "loc+%3d",
398 			    i->i_locoff);
399 			loc = locbuf;
400 		} else
401 			loc = "loc";
402 		if (fprintf(fp, "\
403     {&%s_ca,%s&%s_cd,%s%2d, %s, %7s, %#4x, pv+%2d, %d, %s%d, %4d},\n",
404 		    attachment, strlen(attachment) < 6 ? "\t\t" : "\t",
405 		    basename, strlen(basename) < 3 ? "\t\t" : "\t", unit,
406 		    state, loc, i->i_cfflags, i->i_pvoff, i->i_locnami,
407 		    vs, v, unit) < 0)
408 			  return (1);
409 	}
410 	if (fprintf(fp, "    {0},\n    {0},\n    {0},\n    {0},\n") < 0)
411 		return (1);
412 	if (fprintf(fp, "    {0},\n    {0},\n    {0},\n    {0},\n") < 0)
413 		return (1);
414 	return (fputs("    {(struct cfattach *)-1}\n};\n", fp) < 0);
415 }
416 
417 /*
418  * Emit the table of potential roots.
419  */
420 static int
emitroots(FILE * fp)421 emitroots(FILE *fp)
422 {
423 	struct devi **p, *i;
424 	int cnt = 0;
425 
426 	if (fputs("\nshort cfroots[] = {\n", fp) < 0)
427 		return (1);
428 	for (p = packed; (i = *p) != NULL; p++) {
429 		if (i->i_at != NULL)
430 			continue;
431 		if (i->i_unit != 0 &&
432 		    (i->i_unit != STAR || i->i_base->d_umax != 0))
433 			(void)fprintf(stderr,
434 			    "config: warning: `%s at root' is not unit 0\n",
435 			    i->i_name);
436 		if (fprintf(fp, "\t%2d /* %s */,\n",
437 		    i->i_cfindex, i->i_name) < 0)
438 			return (1);
439 		cnt++;
440 	}
441 	if (fputs("\t-1\n};\n", fp) < 0)
442 		return (1);
443 
444 	return(fprintf(fp, "\nint cfroots_size = %d;\n", cnt+1) < 0);
445 }
446 
447 /*
448  * Emit pseudo-device initialization.
449  */
450 static int
emitpseudo(FILE * fp)451 emitpseudo(FILE *fp)
452 {
453 	struct devi *i;
454 	struct devbase *d;
455 	int cnt = 0;
456 
457 	if (fputs("\n/* pseudo-devices */\n", fp) < 0)
458 		return (1);
459 	for (i = allpseudo; i != NULL; i = i->i_next)
460 		if (fprintf(fp, "extern void %sattach(int);\n",
461 		    i->i_base->d_name) < 0)
462 			return (1);
463 	if (fputs("\nchar *pdevnames[] = {\n", fp) < 0)
464 		return (1);
465 	for (i = allpseudo; i != NULL; i = i->i_next) {
466 		d = i->i_base;
467 		if (fprintf(fp, "\t\"%s\",\n", d->d_name) < 0)
468 			return (1);
469 		cnt++;
470 	}
471 	if (fputs("};\n", fp) < 0)
472 		return (1);
473 	if (fprintf(fp, "\nint pdevnames_size = %d;\n", cnt) < 0)
474 		return (1);
475 	if (fputs("\nstruct pdevinit pdevinit[] = {\n", fp) < 0)
476 		return (1);
477 	for (i = allpseudo; i != NULL; i = i->i_next) {
478 		d = i->i_base;
479 		if (fprintf(fp, "\t{ %sattach, %d },\n",
480 		    d->d_name, d->d_umax) < 0)
481 			return (1);
482 	}
483 	return (fputs("\t{ NULL, 0 }\n};\n", fp) < 0);
484 }
485