xref: /netbsd-src/usr.bin/config/mkdevsw.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
1 /*	$NetBSD: mkdevsw.c,v 1.15 2016/07/16 07:13:26 pgoyette 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@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.15 2016/07/16 07:13:26 pgoyette 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