1 /* $OpenBSD: mkioconf.c,v 1.38 2019/06/28 13:33:55 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 <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 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 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 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 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 struct cfattach %s_ca;\n", 161 da->d_name) < 0) 162 return (1); 163 } 164 NEWLINE; 165 return (0); 166 } 167 168 static int 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 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 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 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 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 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(" {(struct cfattach *)-1}\n};\n", fp) == EOF); 387 } 388 389 /* 390 * Emit the table of potential roots. 391 */ 392 static int 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 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