xref: /netbsd-src/usr.bin/config/mkdevsw.c (revision 93b25323436f832f83862b693a2b44c057a19e45)
1*93b25323Sjoe /*	$NetBSD: mkdevsw.c,v 1.16 2025/01/07 14:21:11 joe Exp $	*/
25ecc953bSthorpej 
35ecc953bSthorpej /*
45ecc953bSthorpej  * Copyright (c) 2002 The NetBSD Foundation, Inc.
55ecc953bSthorpej  * All rights reserved.
65ecc953bSthorpej  *
75ecc953bSthorpej  * This code is derived from software contributed to The NetBSD Foundation
85ecc953bSthorpej  * by MAEKAWA Masahide (gehenna@NetBSD.org).
95ecc953bSthorpej  *
105ecc953bSthorpej  * Redistribution and use in source and binary forms, with or without
115ecc953bSthorpej  * modification, are permitted provided that the following conditions
125ecc953bSthorpej  * are met:
135ecc953bSthorpej  * 1. Redistributions of source code must retain the above copyright
145ecc953bSthorpej  *    notice, this list of conditions and the following disclaimer.
155ecc953bSthorpej  * 2. Redistributions in binary form must reproduce the above copyright
165ecc953bSthorpej  *    notice, this list of conditions and the following disclaimer in the
175ecc953bSthorpej  *    documentation and/or other materials provided with the distribution.
185ecc953bSthorpej  *
195ecc953bSthorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
205ecc953bSthorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
215ecc953bSthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
225ecc953bSthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
235ecc953bSthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
245ecc953bSthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
255ecc953bSthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
265ecc953bSthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
275ecc953bSthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
285ecc953bSthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
295ecc953bSthorpej  * POSSIBILITY OF SUCH DAMAGE.
305ecc953bSthorpej  */
315ecc953bSthorpej 
325ecc953bSthorpej #if HAVE_NBTOOL_CONFIG_H
335ecc953bSthorpej #include "nbtool_config.h"
345ecc953bSthorpej #endif
355ecc953bSthorpej 
36d12b0036Schristos #include <sys/cdefs.h>
37*93b25323Sjoe __RCSID("$NetBSD: mkdevsw.c,v 1.16 2025/01/07 14:21:11 joe Exp $");
38d12b0036Schristos 
395ecc953bSthorpej #include <stdio.h>
405ecc953bSthorpej #include <string.h>
415ecc953bSthorpej #include <errno.h>
42c7295a4cSchristos #include <err.h>
435ecc953bSthorpej 
445ecc953bSthorpej #include "defs.h"
455ecc953bSthorpej 
46342d3579Sdsl static void emitconv(FILE *);
47342d3579Sdsl static void emitdev(FILE *);
48342d3579Sdsl static void emitdevm(FILE *);
49342d3579Sdsl static void emitheader(FILE *);
505ecc953bSthorpej 
515ecc953bSthorpej int
525ecc953bSthorpej mkdevsw(void)
535ecc953bSthorpej {
545ecc953bSthorpej 	FILE *fp;
555ecc953bSthorpej 
565ecc953bSthorpej 	if ((fp = fopen("devsw.c.tmp", "w")) == NULL) {
57c7295a4cSchristos 		warn("cannot create devsw.c");
58b5b4952dSuebayasi 		return (1);
595ecc953bSthorpej 	}
605ecc953bSthorpej 
61342d3579Sdsl 	emitheader(fp);
62342d3579Sdsl 	emitdevm(fp);
63342d3579Sdsl 	emitconv(fp);
64342d3579Sdsl 	emitdev(fp);
65342d3579Sdsl 
66342d3579Sdsl 	fflush(fp);
67342d3579Sdsl 	if (ferror(fp)) {
68c7295a4cSchristos 		warn("error writing devsw.c");
69342d3579Sdsl 		fclose(fp);
70b5b4952dSuebayasi 		return 1;
715ecc953bSthorpej 	}
725ecc953bSthorpej 
735ecc953bSthorpej 	(void)fclose(fp);
745ecc953bSthorpej 
755ecc953bSthorpej 	if (moveifchanged("devsw.c.tmp", "devsw.c") != 0) {
76c7295a4cSchristos 		warn("error renaming devsw.c");
77dccd2cf5Suebayasi 		return (1);
785ecc953bSthorpej 	}
795ecc953bSthorpej 
80b5b4952dSuebayasi 	return (0);
81b5b4952dSuebayasi }
82b5b4952dSuebayasi 
83342d3579Sdsl static void
845ecc953bSthorpej emitheader(FILE *fp)
855ecc953bSthorpej {
8682d7cb83Slukem 	autogen_comment(fp, "devsw.c");
875ecc953bSthorpej 
88342d3579Sdsl 	fputs("#include <sys/param.h>\n"
893718acd4Spooka 		  "#include <sys/conf.h>\n", fp);
905ecc953bSthorpej }
915ecc953bSthorpej 
92b552d112Schristos static void
93b552d112Schristos dentry(FILE *fp, struct hashtab *t, devmajor_t i, char p)
94b552d112Schristos {
95b552d112Schristos 	const struct devm *dm;
96b552d112Schristos 	char mstr[16];
97b552d112Schristos 
98b552d112Schristos 	(void)snprintf(mstr, sizeof(mstr), "%d", i);
99b552d112Schristos 	if ((dm = ht_lookup(t, intern(mstr))) == NULL)
100b552d112Schristos 		return;
101b552d112Schristos 
102b552d112Schristos 	fprintf(fp, "extern const struct %cdevsw %s_%cdevsw;\n",
103b552d112Schristos 	    p, dm->dm_name, p);
104b552d112Schristos }
105b552d112Schristos 
106b552d112Schristos static void
107b552d112Schristos pentry(FILE *fp, struct hashtab *t, devmajor_t i, char p)
108b552d112Schristos {
109b552d112Schristos 	const struct devm *dm;
110b552d112Schristos 	char mstr[16];
111b552d112Schristos 
112b552d112Schristos 	(void)snprintf(mstr, sizeof(mstr), "%d", i);
113b552d112Schristos 	dm = ht_lookup(t, intern(mstr));
114b552d112Schristos 
115b552d112Schristos 	if (dm)
116b552d112Schristos 		fprintf(fp, "\t&%s_%cdevsw", dm->dm_name, p);
117b552d112Schristos 	else
118b552d112Schristos 		fputs("\tNULL", fp);
119b552d112Schristos 
120b552d112Schristos 	fprintf(fp, ",\t// %3d\n", i);
121b552d112Schristos }
122b552d112Schristos 
1235ecc953bSthorpej /*
1245ecc953bSthorpej  * Emit device switch table for character/block device.
1255ecc953bSthorpej  */
126342d3579Sdsl static void
1275ecc953bSthorpej emitdevm(FILE *fp)
1285ecc953bSthorpej {
129d767912bSdrochner 	devmajor_t i;
1305ecc953bSthorpej 
131342d3579Sdsl 	fputs("\n/* device switch table for block device */\n", fp);
1325ecc953bSthorpej 
133b552d112Schristos 	for (i = 0; i <= maxbdevm ; i++)
134e8f1cd85Spgoyette 		dentry(fp, bdevmtab, i, 'b');
1355ecc953bSthorpej 
136342d3579Sdsl 	fputs("\nconst struct bdevsw *bdevsw0[] = {\n", fp);
1375ecc953bSthorpej 
138b552d112Schristos 	for (i = 0; i <= maxbdevm; i++)
139b552d112Schristos 		pentry(fp, bdevmtab, i, 'b');
1405ecc953bSthorpej 
141342d3579Sdsl 	fputs("};\n\nconst struct bdevsw **bdevsw = bdevsw0;\n", fp);
1425ecc953bSthorpej 
1433718acd4Spooka 	fputs("const int sys_bdevsws = __arraycount(bdevsw0);\n"
1443718acd4Spooka 		  "int max_bdevsws = __arraycount(bdevsw0);\n", fp);
1455ecc953bSthorpej 
146342d3579Sdsl 	fputs("\n/* device switch table for character device */\n", fp);
1475ecc953bSthorpej 
148b552d112Schristos 	for (i = 0; i <= maxcdevm; i++)
149b552d112Schristos 		dentry(fp, cdevmtab, i, 'c');
1505ecc953bSthorpej 
151342d3579Sdsl 	fputs("\nconst struct cdevsw *cdevsw0[] = {\n", fp);
1525ecc953bSthorpej 
153b552d112Schristos 	for (i = 0; i <= maxcdevm; i++)
154b552d112Schristos 		pentry(fp, cdevmtab, i, 'c');
1555ecc953bSthorpej 
156342d3579Sdsl 	fputs("};\n\nconst struct cdevsw **cdevsw = cdevsw0;\n", fp);
1575ecc953bSthorpej 
1583718acd4Spooka 	fputs("const int sys_cdevsws = __arraycount(cdevsw0);\n"
1593718acd4Spooka 		  "int max_cdevsws = __arraycount(cdevsw0);\n", fp);
1605ecc953bSthorpej }
1615ecc953bSthorpej 
1625ecc953bSthorpej /*
1635ecc953bSthorpej  * Emit device major conversion table.
1645ecc953bSthorpej  */
165342d3579Sdsl static void
1665ecc953bSthorpej emitconv(FILE *fp)
1675ecc953bSthorpej {
1685ecc953bSthorpej 	struct devm *dm;
1695ecc953bSthorpej 
170342d3579Sdsl 	fputs("\n/* device conversion table */\n"
171342d3579Sdsl 		  "struct devsw_conv devsw_conv0[] = {\n", fp);
1725ecc953bSthorpej 	TAILQ_FOREACH(dm, &alldevms, dm_next) {
1733f1dd008Scube 		if (version < 20100430) {
1743f1dd008Scube 			/* Emit compatible structure */
1753f1dd008Scube 			fprintf(fp, "\t{ \"%s\", %d, %d },\n", dm->dm_name,
1763f1dd008Scube 			    dm->dm_bmajor, dm->dm_cmajor);
1773f1dd008Scube 			continue;
1783f1dd008Scube 		}
1793da3ab25Spooka 		struct nvlist *nv;
1803da3ab25Spooka 		const char *d_class, *d_flags = "0";
1813da3ab25Spooka 		int d_vec[2] = { 0, 0 };
1823da3ab25Spooka 		int i = 0;
1833da3ab25Spooka 
1843da3ab25Spooka 		/*
1853da3ab25Spooka 		 * "parse" info.  currently the rules are simple:
1863da3ab25Spooka 		 *  1) first entry defines class
1873da3ab25Spooka 		 *  2) next ones without n_str are d_vectdim
1883da3ab25Spooka 		 *  3) next one with n_str is d_flags
1893da3ab25Spooka 		 *  4) EOL
1903da3ab25Spooka 		 */
1913da3ab25Spooka 		nv = dm->dm_devnodes;
1923da3ab25Spooka 		d_class = nv->nv_str;
1933da3ab25Spooka 		while ((nv = nv->nv_next) != NULL) {
1943da3ab25Spooka 			if (i > 2)
1953da3ab25Spooka 				panic("invalid devnode definition");
1963da3ab25Spooka 			if (nv->nv_str) {
1973da3ab25Spooka 				d_flags = nv->nv_str;
1983da3ab25Spooka 				break;
1993da3ab25Spooka 			}
200d12b0036Schristos 			if (nv->nv_num > INT_MAX || nv->nv_num < INT_MIN)
201d12b0036Schristos 				panic("out of range devnode definition");
202d12b0036Schristos 			d_vec[i++] = (int)nv->nv_num;
2033da3ab25Spooka 		}
2043da3ab25Spooka 
2053da3ab25Spooka 		fprintf(fp, "\t{ \"%s\", %d, %d, %s, %s, { %d, %d }},\n",
2063da3ab25Spooka 			    dm->dm_name, dm->dm_bmajor, dm->dm_cmajor,
2073da3ab25Spooka 			    d_class, d_flags, d_vec[0], d_vec[1]);
2083da3ab25Spooka 
2095ecc953bSthorpej 	}
210342d3579Sdsl 	fputs("};\n\n"
2115ecc953bSthorpej 		  "struct devsw_conv *devsw_conv = devsw_conv0;\n"
2123718acd4Spooka 		  "int max_devsw_convs = __arraycount(devsw_conv0);\n",
213342d3579Sdsl 		  fp);
2145ecc953bSthorpej }
2155ecc953bSthorpej 
2165ecc953bSthorpej /*
2175ecc953bSthorpej  * Emit specific device major informations.
2185ecc953bSthorpej  */
219342d3579Sdsl static void
2205ecc953bSthorpej emitdev(FILE *fp)
2215ecc953bSthorpej {
2225ecc953bSthorpej 	struct devm *dm;
2235ecc953bSthorpej 	char mstr[16];
2245ecc953bSthorpej 
225342d3579Sdsl 	fputs("\n", fp);
2265ecc953bSthorpej 
2275ecc953bSthorpej 	(void)strlcpy(mstr, "swap", sizeof(mstr));
22819ff568bSyamt 	if ((dm = ht_lookup(bdevmtab, intern(mstr))) != NULL) {
229342d3579Sdsl 		fprintf(fp, "const dev_t swapdev = makedev(%d, 0);\n",
230342d3579Sdsl 			    dm->dm_bmajor);
23119ff568bSyamt 	}
2325ecc953bSthorpej 
2335ecc953bSthorpej 	(void)strlcpy(mstr, "mem", sizeof(mstr));
2345ecc953bSthorpej 	if ((dm = ht_lookup(cdevmtab, intern(mstr))) == NULL)
2355ecc953bSthorpej 		panic("memory device is not configured");
236342d3579Sdsl 	fprintf(fp, "const dev_t zerodev = makedev(%d, DEV_ZERO);\n",
237342d3579Sdsl 		    dm->dm_cmajor);
2385ecc953bSthorpej 
239342d3579Sdsl 	fputs("\n/* mem_no is only used in iskmemdev() */\n", fp);
240342d3579Sdsl 	fprintf(fp, "const int mem_no = %d;\n", dm->dm_cmajor);
2415ecc953bSthorpej }
242