mkioconf.c revision 1.22 1 /* $NetBSD: mkioconf.c,v 1.22 2014/10/29 17:14:50 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.22 2014/10/29 17:14:50 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 emithdr(fp);
96 emitcfdrivers(fp);
97 emitexterns(fp);
98 emitloc(fp);
99 emitparents(fp);
100 emitcfdata(fp);
101 emitcfattachinit(fp);
102
103 if (ioconfname == NULL) {
104 emitroots(fp);
105 emitpseudo(fp);
106 if (!do_devsw)
107 emitname2blk(fp);
108 }
109
110 fflush(fp);
111 if (ferror(fp)) {
112 warn("error writing ioconf.c");
113 (void)fclose(fp);
114 #if 0
115 (void)unlink("ioconf.c.tmp");
116 #endif
117 return (1);
118 }
119
120 (void)fclose(fp);
121 if (moveifchanged("ioconf.c.tmp", "ioconf.c") != 0) {
122 warn("error renaming ioconf.c");
123 return (1);
124 }
125 return (0);
126 }
127
128 static int
129 cforder(const void *a, const void *b)
130 {
131 int n1, n2;
132
133 n1 = (*(const struct devi * const *)a)->i_cfindex;
134 n2 = (*(const struct devi * const *)b)->i_cfindex;
135 return (n1 - n2);
136 }
137
138 static void
139 emithdr(FILE *ofp)
140 {
141 FILE *ifp;
142 size_t n;
143 char ifnbuf[200], buf[BUFSIZ];
144 char *ifn;
145
146 autogen_comment(ofp, "ioconf.c");
147
148 (void)snprintf(ifnbuf, sizeof(ifnbuf), "arch/%s/conf/ioconf.incl.%s",
149 machine ? machine : "(null)", machine ? machine : "(null)");
150 ifn = sourcepath(ifnbuf);
151 if ((ifp = fopen(ifn, "r")) != NULL) {
152 while ((n = fread(buf, 1, sizeof(buf), ifp)) > 0)
153 (void)fwrite(buf, 1, n, ofp);
154 if (ferror(ifp))
155 err(EXIT_FAILURE, "error reading %s", ifn);
156 (void)fclose(ifp);
157 } else {
158 fputs("#include <sys/param.h>\n"
159 "#include <sys/conf.h>\n"
160 "#include <sys/device.h>\n"
161 "#include <sys/mount.h>\n", ofp);
162 }
163 free(ifn);
164 }
165
166 /*
167 * Emit an initialized array of character strings describing this
168 * attribute's locators.
169 */
170 static int
171 cf_locators_print(const char *name, void *value, void *arg)
172 {
173 struct attr *a;
174 struct loclist *ll;
175 FILE *fp = arg;
176
177 a = value;
178 if (!a->a_iattr)
179 return (0);
180
181 if (a->a_locs) {
182 fprintf(fp,
183 "static const struct cfiattrdata %scf_iattrdata = {\n",
184 name);
185 fprintf(fp, "\t\"%s\", %d,\n\t{\n", name, a->a_loclen);
186 for (ll = a->a_locs; ll; ll = ll->ll_next)
187 fprintf(fp, "\t\t{ \"%s\", \"%s\", %s },\n",
188 ll->ll_name,
189 (ll->ll_string ? ll->ll_string : "NULL"),
190 (ll->ll_string ? ll->ll_string : "0"));
191 fprintf(fp, "\t}\n};\n");
192 } else {
193 fprintf(fp,
194 "static const struct cfiattrdata %scf_iattrdata = {\n"
195 "\t\"%s\", 0, {\n\t\t{ NULL, NULL, 0 },\n\t}\n};\n",
196 name, name);
197 }
198
199 return 0;
200 }
201
202 static void
203 emitcfdrivers(FILE *fp)
204 {
205 struct devbase *d;
206 struct attrlist *al;
207 struct attr *a;
208 int has_iattrs;
209
210 NEWLINE;
211 ht_enumerate(attrtab, cf_locators_print, fp);
212
213 NEWLINE;
214 TAILQ_FOREACH(d, &allbases, d_next) {
215 if (!devbase_has_instances(d, WILD))
216 continue;
217 has_iattrs = 0;
218 for (al = d->d_attrs; al != NULL; al = al->al_next) {
219 a = al->al_this;
220 if (a->a_iattr == 0)
221 continue;
222 if (has_iattrs == 0)
223 fprintf(fp,
224 "static const struct cfiattrdata * const %s_attrs[] = { ",
225 d->d_name);
226 has_iattrs = 1;
227 fprintf(fp, "&%scf_iattrdata, ", a->a_name);
228 }
229 if (has_iattrs)
230 fprintf(fp, "NULL };\n");
231 fprintf(fp, "CFDRIVER_DECL(%s, %s, ", d->d_name, /* ) */
232 d->d_classattr != NULL ? d->d_classattr->a_devclass
233 : "DV_DULL");
234 if (has_iattrs)
235 fprintf(fp, "%s_attrs", d->d_name);
236 else
237 fprintf(fp, "NULL");
238 fprintf(fp, /* ( */ ");\n\n");
239 }
240
241 NEWLINE;
242
243 fprintf(fp,
244 "%sstruct cfdriver * const cfdriver_%s_%s[] = {\n",
245 ioconfname ? "static " : "",
246 ioconfname ? "ioconf" : "list",
247 ioconfname ? ioconfname : "initial");
248
249 TAILQ_FOREACH(d, &allbases, d_next) {
250 if (!devbase_has_instances(d, WILD))
251 continue;
252 fprintf(fp, "\t&%s_cd,\n", d->d_name);
253 }
254 fprintf(fp, "\tNULL\n};\n");
255 }
256
257 static void
258 emitexterns(FILE *fp)
259 {
260 struct deva *da;
261
262 NEWLINE;
263 TAILQ_FOREACH(da, &alldevas, d_next) {
264 if (!deva_has_instances(da, WILD))
265 continue;
266 fprintf(fp, "extern struct cfattach %s_ca;\n",
267 da->d_name);
268 }
269 }
270
271 static void
272 emitcfattachinit(FILE *fp)
273 {
274 struct devbase *d;
275 struct deva *da;
276
277 NEWLINE;
278 TAILQ_FOREACH(d, &allbases, d_next) {
279 if (!devbase_has_instances(d, WILD))
280 continue;
281 if (d->d_ahead == NULL)
282 continue;
283
284 fprintf(fp,
285 "static struct cfattach * const %s_cfattachinit[] = {\n\t",
286 d->d_name);
287 for (da = d->d_ahead; da != NULL; da = da->d_bsame) {
288 if (!deva_has_instances(da, WILD))
289 continue;
290 fprintf(fp, "&%s_ca, ", da->d_name);
291 }
292 fprintf(fp, "NULL\n};\n");
293 }
294
295 NEWLINE;
296 fprintf(fp, "%sconst struct cfattachinit cfattach%s%s[] = {\n",
297 ioconfname ? "static " : "",
298 ioconfname ? "_ioconf_" : "init",
299 ioconfname ? ioconfname : "");
300
301 TAILQ_FOREACH(d, &allbases, d_next) {
302 if (!devbase_has_instances(d, WILD))
303 continue;
304 if (d->d_ahead == NULL)
305 continue;
306
307 fprintf(fp, "\t{ \"%s\", %s_cfattachinit },\n",
308 d->d_name, d->d_name);
309 }
310
311 fprintf(fp, "\t{ NULL, NULL }\n};\n");
312 }
313
314 static void
315 emitloc(FILE *fp)
316 {
317 int i;
318
319 if (locators.used != 0) {
320 fprintf(fp, "\n/* locators */\n"
321 "static int loc[%d] = {", locators.used);
322 for (i = 0; i < locators.used; i++)
323 fprintf(fp, "%s%s,", SEP(i, 8), locators.vec[i]);
324 fprintf(fp, "\n};\n");
325 } else if (*packed != NULL) {
326 /* We need to have *something*. */
327 fprintf(fp, "\n/* locators */\n"
328 "static int loc[1] = { -1 };\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 = "loc";
435 fprintf(fp, " { \"%s\",%s\"%s\",%s%2d, %s, %7s, %#6x, ",
436 basename, strlen(basename) < 8 ? "\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 TAILQ_FOREACH(i, &allpseudo, i_next) {
482 fprintf(fp, "void %sattach(int);\n",
483 i->i_base->d_name);
484 }
485 fputs("\nstruct pdevinit pdevinit[] = {\n", fp);
486 TAILQ_FOREACH(i, &allpseudo, i_next) {
487 d = i->i_base;
488 fprintf(fp, "\t{ %sattach, %d },\n",
489 d->d_name, d->d_umax);
490 }
491 fputs("\t{ 0, 0 }\n};\n", fp);
492 }
493
494 /*
495 * Emit name to major block number table.
496 */
497 void
498 emitname2blk(FILE *fp)
499 {
500 struct devbase *dev;
501
502 fputs("\n/* device name to major block number */\n", fp);
503
504 fprintf(fp, "struct devnametobdevmaj dev_name2blk[] = {\n");
505
506 TAILQ_FOREACH(dev, &allbases, d_next) {
507 if (dev->d_major == NODEVMAJOR)
508 continue;
509
510 fprintf(fp, "\t{ \"%s\", %d },\n",
511 dev->d_name, dev->d_major);
512 }
513 fprintf(fp, "\t{ NULL, 0 }\n};\n");
514 }
515