xref: /openbsd/usr.sbin/config/mkioconf.c (revision b306148f)
1 /*	$OpenBSD: mkioconf.c,v 1.39 2022/04/07 10:11:27 tb 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 <err.h>
45 #include <errno.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 
50 #include "config.h"
51 
52 /*
53  * Make ioconf.c.
54  */
55 static int cforder(const void *, const void *);
56 static int emitcfdata(FILE *);
57 static int emitexterns(FILE *);
58 static int emithdr(FILE *);
59 static int emitloc(FILE *);
60 static int emitlocnames(FILE *);
61 static int emitpseudo(FILE *);
62 static int emitpv(FILE *);
63 static int emitroots(FILE *);
64 
65 #define	SEP(pos, max)	(((u_int)(pos) % (max)) == 0 ? "\n\t" : " ")
66 
67 /*
68  * NEWLINE can only be used in the emitXXX functions.
69  * In most cases it can be subsumed into an fprintf.
70  */
71 #define	NEWLINE		if (putc('\n', fp) == EOF) return (1)
72 
73 int
mkioconf(void)74 mkioconf(void)
75 {
76 	FILE *fp;
77 	int v;
78 
79 	qsort(packed, npacked, sizeof *packed, cforder);
80 	if ((fp = fopen("ioconf.c", "w")) == NULL) {
81 		warn("cannot write ioconf.c");
82 		return (1);
83 	}
84 	v = emithdr(fp);
85 	if (v != 0 || emitexterns(fp) || emitloc(fp) ||
86 	    emitlocnames(fp) || emitpv(fp) || emitcfdata(fp) ||
87 	    emitroots(fp) || emitpseudo(fp)) {
88 		if (v >= 0)
89 			warn("error writing ioconf.c");
90 		(void)fclose(fp);
91 		/* (void)unlink("ioconf.c"); */
92 		return (1);
93 	}
94 	(void)fclose(fp);
95 	return (0);
96 }
97 
98 static int
cforder(const void * a,const void * b)99 cforder(const void *a, const void *b)
100 {
101 	int n1, n2;
102 
103 	n1 = (*(struct devi **)a)->i_cfindex;
104 	n2 = (*(struct devi **)b)->i_cfindex;
105 	return (n1 - n2);
106 }
107 
108 static int
emithdr(FILE * ofp)109 emithdr(FILE *ofp)
110 {
111 	FILE *ifp;
112 	size_t n;
113 	char ifn[200], buf[BUFSIZ];
114 
115 	if (fprintf(ofp, "\
116 /*\n\
117  * MACHINE GENERATED: DO NOT EDIT\n\
118  *\n\
119  * ioconf.c, from \"%s\"\n\
120  */\n\n", conffile) < 0)
121 		return (1);
122 	(void)snprintf(ifn, sizeof ifn, "ioconf.incl.%s", machine);
123 	if ((ifp = fopen(ifn, "r")) != NULL) {
124 		while ((n = fread(buf, 1, sizeof(buf), ifp)) > 0)
125 			if (fwrite(buf, 1, n, ofp) != n)
126 				return (1);
127 		if (ferror(ifp)) {
128 			warn("error reading %s", ifn);
129 			(void)fclose(ifp);
130 			return (-1);
131 		}
132 		(void)fclose(ifp);
133 	} else {
134 		if (fputs("\
135 #include <sys/param.h>\n\
136 #include <sys/device.h>\n", ofp) == EOF)
137 			return (1);
138 	}
139 	return (0);
140 }
141 
142 static int
emitexterns(FILE * fp)143 emitexterns(FILE *fp)
144 {
145 	struct devbase *d;
146 	struct deva *da;
147 
148 	NEWLINE;
149 	for (d = allbases; d != NULL; d = d->d_next) {
150 		if (!devbase_has_instances(d, WILD))
151 			continue;
152 		if (fprintf(fp, "extern struct cfdriver %s_cd;\n",
153 			    d->d_name) < 0)
154 			return (1);
155 	}
156 	NEWLINE;
157 	for (da = alldevas; da != NULL; da = da->d_next) {
158 		if (!deva_has_instances(da, WILD))
159 			continue;
160 		if (fprintf(fp, "extern const struct cfattach %s_ca;\n",
161 			    da->d_name) < 0)
162 			return (1);
163 	}
164 	NEWLINE;
165 	return (0);
166 }
167 
168 static int
emitloc(FILE * fp)169 emitloc(FILE *fp)
170 {
171 	int i;
172 
173 	if (fprintf(fp, "\n/* locators */\n\
174 static long loc[%d] = {", locators.used) < 0)
175 		return (1);
176 	for (i = 0; i < locators.used; i++)
177 		if (fprintf(fp, "%s%s,", SEP(i, 8), locators.vec[i]) < 0)
178 			return (1);
179 	if (fprintf(fp, "\n};\n") < 0)
180 		return(1);
181 	return (fprintf(fp, "\n#ifndef MAXEXTRALOC\n\
182 #define MAXEXTRALOC 32\n\
183 #endif\n\
184 long extraloc[MAXEXTRALOC] = { -1 }; /* extra locator space */\n\
185 int rextraloc = MAXEXTRALOC; /* remaining extra locators */\n\
186 const int textraloc = MAXEXTRALOC; /* total extra relocators */\n") < 0);
187 }
188 
189 static int nlocnames, maxlocnames = 8;
190 static char **locnames;
191 
192 short
addlocname(const char * name)193 addlocname(const char *name)
194 {
195 	int i;
196 
197 	if (locnames == NULL || nlocnames+1 > maxlocnames) {
198 		maxlocnames *= 4;
199 		locnames = ereallocarray(locnames, maxlocnames, sizeof(char *));
200 	}
201 	for (i = 0; i < nlocnames; i++)
202 		if (strcmp(name, locnames[i]) == 0)
203 			return (i);
204 	/*printf("adding %s at %d\n", name, nlocnames);*/
205 	locnames[nlocnames++] = (char *)name;
206 	return (nlocnames - 1);
207 }
208 
209 static int nlocnami, maxlocnami = 8;
210 static short *locnami;
211 
212 void
addlocnami(short index)213 addlocnami(short index)
214 {
215 	if (locnami == NULL || nlocnami+1 > maxlocnami) {
216 		maxlocnami *= 4;
217 		locnami = ereallocarray(locnami, maxlocnami, sizeof(short));
218 	}
219 	locnami[nlocnami++] = index;
220 }
221 
222 
223 /*
224  * Emit locator names
225  * XXX the locnamp[] table is not compressed like it should be!
226  */
227 static int
emitlocnames(FILE * fp)228 emitlocnames(FILE *fp)
229 {
230 	struct devi **p, *i;
231 	struct nvlist *nv;
232 	struct attr *a;
233 	int added, start;
234 	int v, j, x;
235 
236 	addlocnami(-1);
237 	for (p = packed; (i = *p) != NULL; p++) {
238 		/*printf("child %s\n", i->i_name);*/
239 
240 		/* initialize all uninitialized parents */
241 		for (x = 0; x < i->i_pvlen; x++) {
242 			if (i->i_parents[x]->i_plocnami)
243 				continue;
244 			start = nlocnami;
245 
246 			/* add all the names */
247 			a = i->i_atattr;
248 			added = 0;
249 			for (nv = a->a_locs, v = 0; nv != NULL;
250 			    nv = nv->nv_next, v++) {
251 				addlocnami(addlocname(nv->nv_name));
252 				added = 1;
253 			}
254 			/* terminate list of names */
255 			if (added)
256 				addlocnami(-1);
257 			else
258 				start--;
259 
260 			/*printf("bus %s starts at %d\n", i->i_parents[x]->i_name,
261 			    start);*/
262 			i->i_parents[x]->i_plocnami = start;
263 
264 		}
265 	}
266 	for (p = packed; (i = *p) != NULL; p++)
267 		if (i->i_pvlen)
268 			i->i_locnami = i->i_parents[0]->i_plocnami;
269 	if (fprintf(fp, "\nchar *locnames[] = {\n") < 0)
270 		return (1);
271 	for (j = 0; j < nlocnames; j++)
272 		if (fprintf(fp, "\t\"%s\",\n", locnames[j]) < 0)
273 			return (1);
274 	if (fprintf(fp, "};\n\n") < 0)
275 		return (1);
276 
277 	if (fprintf(fp,
278 	    "/* each entry is an index into locnames[]; -1 terminates */\n") < 0)
279 		return (1);
280 	if (fprintf(fp, "short locnamp[] = {") < 0)
281 		return (1);
282 	for (j = 0; j < nlocnami; j++)
283 		if (fprintf(fp, "%s%d,", SEP(j, 8), locnami[j]) < 0)
284 			return (1);
285 	return (fprintf(fp, "\n};\n") < 0);
286 }
287 
288 
289 /*
290  * Emit global parents-vector.
291  */
292 static int
emitpv(FILE * fp)293 emitpv(FILE *fp)
294 {
295 	int i;
296 
297 	if (fprintf(fp, "\n/* size of parent vectors */\n\
298 int pv_size = %d;\n", parents.used) < 0)
299 		return (1);
300 	if (fprintf(fp, "\n/* parent vectors */\n\
301 short pv[%d] = {", parents.used) < 0)
302 		return (1);
303 	for (i = 0; i < parents.used; i++)
304 		if (fprintf(fp, "%s%d,", SEP(i, 16), parents.vec[i]) < 0)
305 			return (1);
306 	return (fprintf(fp, "\n};\n") < 0);
307 }
308 
309 /*
310  * Emit the cfdata array.
311  */
312 static int
emitcfdata(FILE * fp)313 emitcfdata(FILE *fp)
314 {
315 	struct devi **p, *i;
316 	int unit, v;
317 	const char *state, *basename, *attachment;
318 	struct nvlist *nv;
319 	struct attr *a;
320 	char *loc;
321 	char locbuf[20];
322 
323 	if (fprintf(fp, "\n\
324 #define NORM FSTATE_NOTFOUND\n\
325 #define STAR FSTATE_STAR\n\
326 #define DNRM FSTATE_DNOTFOUND\n\
327 #define DSTR FSTATE_DSTAR\n\
328 \n\
329 struct cfdata cfdata[] = {\n\
330     /* attachment       driver        unit  state loc     flags parents nm starunit1 */\n") < 0)
331 		return (1);
332 	for (p = packed; (i = *p) != NULL; p++) {
333 		/* the description */
334 		if (fprintf(fp, "/*%3d: %s at ", i->i_cfindex, i->i_name) < 0)
335 			return (1);
336 		for (v = 0; v < i->i_pvlen; v++)
337 			if (fprintf(fp, "%s%s", v == 0 ? "" : "|",
338 			    i->i_parents[v]->i_name) < 0)
339 				return (1);
340 		if (v == 0 && fputs("root", fp) == EOF)
341 			return (1);
342 		a = i->i_atattr;
343 		for (nv = a->a_locs, v = 0; nv != NULL; nv = nv->nv_next, v++)
344 			if (fprintf(fp, " %s %s",
345 			    nv->nv_name, i->i_locs[v]) < 0)
346 				return (1);
347 		if (fputs(" */\n", fp) == EOF)
348 			return (-1);
349 
350 		/* then the actual defining line */
351 		basename = i->i_base->d_name;
352 		attachment = i->i_atdeva->d_name;
353 		if (i->i_unit == STAR) {
354 			unit = i->i_base->d_umax;
355 			if (i->i_disable) {
356 				state = "DSTR";
357 			} else {
358 				state = "STAR";
359 			}
360 		} else {
361 			unit = i->i_unit;
362 			if (i->i_disable) {
363 				state = "DNRM";
364 			} else {
365 				state = "NORM";
366 			}
367 		}
368 		if (i->i_locoff >= 0) {
369 			(void)snprintf(locbuf, sizeof locbuf, "loc+%3d",
370 			    i->i_locoff);
371 			loc = locbuf;
372 		} else
373 			loc = "loc";
374 		if (fprintf(fp, "\
375     {&%s_ca,%s&%s_cd,%s%2d, %s, %7s, %#4x, pv+%2d, %d, %4d},\n",
376 		    attachment, strlen(attachment) < 6 ? "\t\t" : "\t",
377 		    basename, strlen(basename) < 3 ? "\t\t" : "\t", unit,
378 		    state, loc, i->i_cfflags, i->i_pvoff, i->i_locnami,
379 		    unit) < 0)
380 			  return (1);
381 	}
382 	if (fprintf(fp, "    {0},\n    {0},\n    {0},\n    {0},\n") < 0)
383 		return (1);
384 	if (fprintf(fp, "    {0},\n    {0},\n    {0},\n    {0},\n") < 0)
385 		return (1);
386 	return (fputs("    {(const struct cfattach *)-1}\n};\n", fp) == EOF);
387 }
388 
389 /*
390  * Emit the table of potential roots.
391  */
392 static int
emitroots(FILE * fp)393 emitroots(FILE *fp)
394 {
395 	struct devi **p, *i;
396 	int cnt = 0;
397 
398 	if (fputs("\nshort cfroots[] = {\n", fp) == EOF)
399 		return (1);
400 	for (p = packed; (i = *p) != NULL; p++) {
401 		if (i->i_at != NULL)
402 			continue;
403 		if (i->i_unit != 0 &&
404 		    (i->i_unit != STAR || i->i_base->d_umax != 0))
405 			warnx("warning: `%s at root' is not unit 0", i->i_name);
406 		if (fprintf(fp, "\t%2d /* %s */,\n",
407 		    i->i_cfindex, i->i_name) < 0)
408 			return (1);
409 		cnt++;
410 	}
411 	if (fputs("\t-1\n};\n", fp) == EOF)
412 		return (1);
413 
414 	return(fprintf(fp, "\nint cfroots_size = %d;\n", cnt+1) < 0);
415 }
416 
417 /*
418  * Emit pseudo-device initialization.
419  */
420 static int
emitpseudo(FILE * fp)421 emitpseudo(FILE *fp)
422 {
423 	struct devi *i;
424 	struct devbase *d;
425 	int cnt = 0, umax;
426 
427 	if (fputs("\n/* pseudo-devices */\n", fp) == EOF)
428 		return (1);
429 	for (i = allpseudo; i != NULL; i = i->i_next)
430 		if (fprintf(fp, "extern void %sattach(int);\n",
431 		    i->i_base->d_name) < 0)
432 			return (1);
433 	if (fputs("\nchar *pdevnames[] = {\n", fp) == EOF)
434 		return (1);
435 	for (i = allpseudo; i != NULL; i = i->i_next) {
436 		d = i->i_base;
437 		if (fprintf(fp, "\t\"%s\",\n", d->d_name) < 0)
438 			return (1);
439 		cnt++;
440 	}
441 	if (fputs("};\n", fp) == EOF)
442 		return (1);
443 	if (fprintf(fp, "\nint pdevnames_size = %d;\n", cnt) < 0)
444 		return (1);
445 	if (fputs("\nstruct pdevinit pdevinit[] = {\n", fp) == EOF)
446 		return (1);
447 	for (i = allpseudo; i != NULL; i = i->i_next) {
448 		d = i->i_base;
449 		umax = d->d_umax;
450 		if (i->i_disable)
451 		    umax*=-1;
452 		if (fprintf(fp, "\t{ %sattach, %d },\n",
453 		    d->d_name, umax) < 0)
454 			return (1);
455 	}
456 	return (fputs("\t{ NULL, 0 }\n};\n", fp) == EOF);
457 }
458