Home | History | Annotate | Line # | Download | only in config
      1 /*	$NetBSD: mkdevsw.c,v 1.16 2025/01/07 14:21:11 joe Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by MAEKAWA Masahide (gehenna (at) NetBSD.org).
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #if HAVE_NBTOOL_CONFIG_H
     33 #include "nbtool_config.h"
     34 #endif
     35 
     36 #include <sys/cdefs.h>
     37 __RCSID("$NetBSD: mkdevsw.c,v 1.16 2025/01/07 14:21:11 joe Exp $");
     38 
     39 #include <stdio.h>
     40 #include <string.h>
     41 #include <errno.h>
     42 #include <err.h>
     43 
     44 #include "defs.h"
     45 
     46 static void emitconv(FILE *);
     47 static void emitdev(FILE *);
     48 static void emitdevm(FILE *);
     49 static void emitheader(FILE *);
     50 
     51 int
     52 mkdevsw(void)
     53 {
     54 	FILE *fp;
     55 
     56 	if ((fp = fopen("devsw.c.tmp", "w")) == NULL) {
     57 		warn("cannot create devsw.c");
     58 		return (1);
     59 	}
     60 
     61 	emitheader(fp);
     62 	emitdevm(fp);
     63 	emitconv(fp);
     64 	emitdev(fp);
     65 
     66 	fflush(fp);
     67 	if (ferror(fp)) {
     68 		warn("error writing devsw.c");
     69 		fclose(fp);
     70 		return 1;
     71 	}
     72 
     73 	(void)fclose(fp);
     74 
     75 	if (moveifchanged("devsw.c.tmp", "devsw.c") != 0) {
     76 		warn("error renaming devsw.c");
     77 		return (1);
     78 	}
     79 
     80 	return (0);
     81 }
     82 
     83 static void
     84 emitheader(FILE *fp)
     85 {
     86 	autogen_comment(fp, "devsw.c");
     87 
     88 	fputs("#include <sys/param.h>\n"
     89 		  "#include <sys/conf.h>\n", fp);
     90 }
     91 
     92 static void
     93 dentry(FILE *fp, struct hashtab *t, devmajor_t i, char p)
     94 {
     95 	const struct devm *dm;
     96 	char mstr[16];
     97 
     98 	(void)snprintf(mstr, sizeof(mstr), "%d", i);
     99 	if ((dm = ht_lookup(t, intern(mstr))) == NULL)
    100 		return;
    101 
    102 	fprintf(fp, "extern const struct %cdevsw %s_%cdevsw;\n",
    103 	    p, dm->dm_name, p);
    104 }
    105 
    106 static void
    107 pentry(FILE *fp, struct hashtab *t, devmajor_t i, char p)
    108 {
    109 	const struct devm *dm;
    110 	char mstr[16];
    111 
    112 	(void)snprintf(mstr, sizeof(mstr), "%d", i);
    113 	dm = ht_lookup(t, intern(mstr));
    114 
    115 	if (dm)
    116 		fprintf(fp, "\t&%s_%cdevsw", dm->dm_name, p);
    117 	else
    118 		fputs("\tNULL", fp);
    119 
    120 	fprintf(fp, ",\t// %3d\n", i);
    121 }
    122 
    123 /*
    124  * Emit device switch table for character/block device.
    125  */
    126 static void
    127 emitdevm(FILE *fp)
    128 {
    129 	devmajor_t i;
    130 
    131 	fputs("\n/* device switch table for block device */\n", fp);
    132 
    133 	for (i = 0; i <= maxbdevm ; i++)
    134 		dentry(fp, bdevmtab, i, 'b');
    135 
    136 	fputs("\nconst struct bdevsw *bdevsw0[] = {\n", fp);
    137 
    138 	for (i = 0; i <= maxbdevm; i++)
    139 		pentry(fp, bdevmtab, i, 'b');
    140 
    141 	fputs("};\n\nconst struct bdevsw **bdevsw = bdevsw0;\n", fp);
    142 
    143 	fputs("const int sys_bdevsws = __arraycount(bdevsw0);\n"
    144 		  "int max_bdevsws = __arraycount(bdevsw0);\n", fp);
    145 
    146 	fputs("\n/* device switch table for character device */\n", fp);
    147 
    148 	for (i = 0; i <= maxcdevm; i++)
    149 		dentry(fp, cdevmtab, i, 'c');
    150 
    151 	fputs("\nconst struct cdevsw *cdevsw0[] = {\n", fp);
    152 
    153 	for (i = 0; i <= maxcdevm; i++)
    154 		pentry(fp, cdevmtab, i, 'c');
    155 
    156 	fputs("};\n\nconst struct cdevsw **cdevsw = cdevsw0;\n", fp);
    157 
    158 	fputs("const int sys_cdevsws = __arraycount(cdevsw0);\n"
    159 		  "int max_cdevsws = __arraycount(cdevsw0);\n", fp);
    160 }
    161 
    162 /*
    163  * Emit device major conversion table.
    164  */
    165 static void
    166 emitconv(FILE *fp)
    167 {
    168 	struct devm *dm;
    169 
    170 	fputs("\n/* device conversion table */\n"
    171 		  "struct devsw_conv devsw_conv0[] = {\n", fp);
    172 	TAILQ_FOREACH(dm, &alldevms, dm_next) {
    173 		if (version < 20100430) {
    174 			/* Emit compatible structure */
    175 			fprintf(fp, "\t{ \"%s\", %d, %d },\n", dm->dm_name,
    176 			    dm->dm_bmajor, dm->dm_cmajor);
    177 			continue;
    178 		}
    179 		struct nvlist *nv;
    180 		const char *d_class, *d_flags = "0";
    181 		int d_vec[2] = { 0, 0 };
    182 		int i = 0;
    183 
    184 		/*
    185 		 * "parse" info.  currently the rules are simple:
    186 		 *  1) first entry defines class
    187 		 *  2) next ones without n_str are d_vectdim
    188 		 *  3) next one with n_str is d_flags
    189 		 *  4) EOL
    190 		 */
    191 		nv = dm->dm_devnodes;
    192 		d_class = nv->nv_str;
    193 		while ((nv = nv->nv_next) != NULL) {
    194 			if (i > 2)
    195 				panic("invalid devnode definition");
    196 			if (nv->nv_str) {
    197 				d_flags = nv->nv_str;
    198 				break;
    199 			}
    200 			if (nv->nv_num > INT_MAX || nv->nv_num < INT_MIN)
    201 				panic("out of range devnode definition");
    202 			d_vec[i++] = (int)nv->nv_num;
    203 		}
    204 
    205 		fprintf(fp, "\t{ \"%s\", %d, %d, %s, %s, { %d, %d }},\n",
    206 			    dm->dm_name, dm->dm_bmajor, dm->dm_cmajor,
    207 			    d_class, d_flags, d_vec[0], d_vec[1]);
    208 
    209 	}
    210 	fputs("};\n\n"
    211 		  "struct devsw_conv *devsw_conv = devsw_conv0;\n"
    212 		  "int max_devsw_convs = __arraycount(devsw_conv0);\n",
    213 		  fp);
    214 }
    215 
    216 /*
    217  * Emit specific device major informations.
    218  */
    219 static void
    220 emitdev(FILE *fp)
    221 {
    222 	struct devm *dm;
    223 	char mstr[16];
    224 
    225 	fputs("\n", fp);
    226 
    227 	(void)strlcpy(mstr, "swap", sizeof(mstr));
    228 	if ((dm = ht_lookup(bdevmtab, intern(mstr))) != NULL) {
    229 		fprintf(fp, "const dev_t swapdev = makedev(%d, 0);\n",
    230 			    dm->dm_bmajor);
    231 	}
    232 
    233 	(void)strlcpy(mstr, "mem", sizeof(mstr));
    234 	if ((dm = ht_lookup(cdevmtab, intern(mstr))) == NULL)
    235 		panic("memory device is not configured");
    236 	fprintf(fp, "const dev_t zerodev = makedev(%d, DEV_ZERO);\n",
    237 		    dm->dm_cmajor);
    238 
    239 	fputs("\n/* mem_no is only used in iskmemdev() */\n", fp);
    240 	fprintf(fp, "const int mem_no = %d;\n", dm->dm_cmajor);
    241 }
    242