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