xref: /freebsd/usr.sbin/config/config.y (revision 7f9d26bd9d1b2754da8429257edbde0a8237f84f)
1 %union {
2 	char	*str;
3 	int	val;
4 	struct	file_list *file;
5 }
6 
7 %token	ANY
8 %token	ARCH
9 %token	AT
10 %token	BUS
11 %token	COMMA
12 %token	CONFIG
13 %token	CONFLICTS
14 %token	CONTROLLER
15 %token	CPU
16 %token	DEVICE
17 %token	DISABLE
18 %token	DISK
19 %token	DRIVE
20 %token	DRQ
21 %token	EQUALS
22 %token	FLAGS
23 %token	IDENT
24 %token	IOMEM
25 %token	IOSIZ
26 %token	IRQ
27 %token	MAXUSERS
28 %token	MINUS
29 %token	NEXUS
30 %token	OPTIONS
31 %token	MAKEOPTIONS
32 %token	PORT
33 %token	PSEUDO_DEVICE
34 %token	SEMICOLON
35 %token	TARGET
36 %token	TTY
37 %token	UNIT
38 %token	VECTOR
39 
40 %token	<str>	ID
41 %token	<val>	NUMBER
42 %token	<val>	FPNUMBER
43 
44 %type	<str>	Save_id
45 %type	<str>	Opt_value
46 %type	<str>	Dev
47 %type	<str>	device_name
48 
49 %{
50 
51 /*
52  * Copyright (c) 1988, 1993
53  *	The Regents of the University of California.  All rights reserved.
54  *
55  * Redistribution and use in source and binary forms, with or without
56  * modification, are permitted provided that the following conditions
57  * are met:
58  * 1. Redistributions of source code must retain the above copyright
59  *    notice, this list of conditions and the following disclaimer.
60  * 2. Redistributions in binary form must reproduce the above copyright
61  *    notice, this list of conditions and the following disclaimer in the
62  *    documentation and/or other materials provided with the distribution.
63  * 3. All advertising materials mentioning features or use of this software
64  *    must display the following acknowledgement:
65  *	This product includes software developed by the University of
66  *	California, Berkeley and its contributors.
67  * 4. Neither the name of the University nor the names of its contributors
68  *    may be used to endorse or promote products derived from this software
69  *    without specific prior written permission.
70  *
71  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
72  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
74  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
75  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
76  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
77  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
78  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
79  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
80  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
81  * SUCH DAMAGE.
82  *
83  *	@(#)config.y	8.1 (Berkeley) 6/6/93
84  * $FreeBSD$
85  */
86 
87 #include <ctype.h>
88 #include <err.h>
89 #include <stdio.h>
90 #include <string.h>
91 
92 #include "config.h"
93 
94 static struct	device cur;
95 static struct	device *curp = 0;
96 
97 struct  device *dtab;
98 char	*ident;
99 int	yyline;
100 struct  file_list *ftab;
101 char	errbuf[80];
102 int	maxusers;
103 
104 int	seen_scbus;
105 
106 #define ns(s)	strdup(s)
107 
108 static struct device *connect __P((char *, int));
109 static struct device *huhcon __P((char *));
110 static void yyerror __P((char *s));
111 
112 
113 %}
114 %%
115 Configuration:
116 	Many_specs
117 		;
118 
119 Many_specs:
120 	Many_specs Spec
121 		|
122 	/* lambda */
123 		;
124 
125 Spec:
126 	Device_spec SEMICOLON
127 	      = { newdev(&cur); } |
128 	Config_spec SEMICOLON
129 		|
130 	SEMICOLON
131 		|
132 	error SEMICOLON
133 		;
134 
135 Config_spec:
136 	ARCH Save_id
137 	    = {
138 		if (!strcmp($2, "i386")) {
139 			machine = MACHINE_I386;
140 			machinename = "i386";
141 		} else if (!strcmp($2, "pc98")) {
142 			machine = MACHINE_PC98;
143 			machinename = "pc98";
144 		} else if (!strcmp($2, "alpha")) {
145 			machine = MACHINE_ALPHA;
146 			machinename = "alpha";
147 		} else
148 			yyerror("Unknown machine type");
149 	      } |
150 	CPU Save_id
151 	      = {
152 		struct cputype *cp =
153 		    (struct cputype *)malloc(sizeof (struct cputype));
154 		memset(cp, 0, sizeof(*cp));
155 		cp->cpu_name = $2;
156 		cp->cpu_next = cputype;
157 		cputype = cp;
158 	      } |
159 	OPTIONS Opt_list
160 		|
161 	MAKEOPTIONS Mkopt_list
162 		|
163 	IDENT ID
164 	      = { ident = $2; } |
165 	System_spec
166 		|
167 	MAXUSERS NUMBER
168 	      = { maxusers = $2; };
169 
170 System_spec:
171 	CONFIG System_id System_parameter_list
172 	  = { warnx("line %d: root/dump/swap specifications obsolete", yyline);}
173 	  |
174 	CONFIG System_id
175 	  ;
176 
177 System_id:
178 	Save_id
179 	      = {
180 		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
181 		memset(op, 0, sizeof(*op));
182 		op->op_name = ns("KERNEL");
183 		op->op_ownfile = 0;
184 		op->op_next = mkopt;
185 		op->op_value = $1;
186 		op->op_line = yyline + 1;
187 		mkopt = op;
188 	      };
189 
190 System_parameter_list:
191 	  System_parameter_list ID
192 	| ID
193 	;
194 
195 device_name:
196 	  Save_id
197 		= { $$ = $1; }
198 	| Save_id NUMBER
199 		= {
200 			char buf[80];
201 
202 			(void) snprintf(buf, sizeof(buf), "%s%d", $1, $2);
203 			$$ = ns(buf); free($1);
204 		}
205 	| Save_id NUMBER ID
206 		= {
207 			char buf[80];
208 
209 			(void) snprintf(buf, sizeof(buf), "%s%d%s", $1, $2, $3);
210 			$$ = ns(buf); free($1);
211 		}
212 	| Save_id NUMBER ID NUMBER
213 		= {
214 			char buf[80];
215 
216 			(void) snprintf(buf, sizeof(buf), "%s%d%s%d",
217 			     $1, $2, $3, $4);
218 			$$ = ns(buf); free($1);
219 		}
220 	| Save_id NUMBER ID NUMBER ID
221 		= {
222 			char buf[80];
223 
224 			(void) snprintf(buf, sizeof(buf), "%s%d%s%d%s",
225 			     $1, $2, $3, $4, $5);
226 			$$ = ns(buf); free($1);
227 		}
228 	;
229 
230 Opt_list:
231 	Opt_list COMMA Option
232 		|
233 	Option
234 		;
235 
236 Option:
237 	Save_id
238 	      = {
239 		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
240 		char *s;
241 		memset(op, 0, sizeof(*op));
242 		op->op_name = $1;
243 		op->op_next = opt;
244 		op->op_value = 0;
245 		/*
246 		 * op->op_line is 1-based; yyline is 0-based but is now 1
247 		 * larger than when `Save_id' was lexed.
248 		 */
249 		op->op_line = yyline;
250 		opt = op;
251 		if ((s = strchr(op->op_name, '='))) {
252 			warnx("line %d: The `=' in options should not be quoted", yyline);
253 			*s = '\0';
254 			op->op_value = ns(s + 1);
255 		}
256 	      } |
257 	Save_id EQUALS Opt_value
258 	      = {
259 		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
260 		memset(op, 0, sizeof(*op));
261 		op->op_name = $1;
262 		op->op_next = opt;
263 		op->op_value = $3;
264 		op->op_line = yyline + 1;
265 		opt = op;
266 	      } ;
267 
268 Opt_value:
269 	ID
270 		= { $$ = $1; } |
271 	NUMBER
272 		= {
273 			char buf[80];
274 
275 			(void) snprintf(buf, sizeof(buf), "%d", $1);
276 			$$ = ns(buf);
277 		} ;
278 
279 Save_id:
280 	ID
281 	      = { $$ = $1; }
282 	;
283 
284 Mkopt_list:
285 	Mkopt_list COMMA Mkoption
286 		|
287 	Mkoption
288 		;
289 
290 Mkoption:
291 	Save_id EQUALS Opt_value
292 	      = {
293 		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
294 		memset(op, 0, sizeof(*op));
295 		op->op_name = $1;
296 		op->op_ownfile = 0;	/* for now */
297 		op->op_next = mkopt;
298 		op->op_value = $3;
299 		op->op_line = yyline + 1;
300 		mkopt = op;
301 	      } ;
302 
303 Dev:
304 	ID
305 	      = { $$ = $1; }
306 	;
307 
308 Device_spec:
309 	DEVICE Dev_name Dev_info
310 	      = { cur.d_type = DEVICE; } |
311 	DISK Dev_name Dev_info
312 	      = { cur.d_dk = 1; cur.d_type = DEVICE; } |
313 	CONTROLLER Dev_name Dev_info
314 	      = { cur.d_type = CONTROLLER; } |
315 	PSEUDO_DEVICE Init_dev Dev
316 	      = {
317 		cur.d_name = $3;
318 		cur.d_type = PSEUDO_DEVICE;
319 		} |
320 	PSEUDO_DEVICE Init_dev Dev NUMBER
321 	      = {
322 		cur.d_name = $3;
323 		cur.d_type = PSEUDO_DEVICE;
324 		cur.d_count = $4;
325 		} ;
326 
327 Dev_name:
328 	Init_dev Dev NUMBER
329 	      = {
330 		cur.d_name = $2;
331 		if (eq($2, "scbus"))
332 			seen_scbus = 1;
333 		cur.d_unit = $3;
334 		};
335 
336 Init_dev:
337 	/* lambda */
338 	      = { init_dev(&cur); };
339 
340 Dev_info:
341 	Con_info Info_list
342 		|
343 	/* lambda */
344 		;
345 
346 Con_info:
347 	AT Dev NUMBER
348 	      = {
349 		if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba")) {
350 			(void) snprintf(errbuf, sizeof(errbuf),
351 				"%s must be connected to a nexus", cur.d_name);
352 			yyerror(errbuf);
353 		}
354 		cur.d_conn = connect($2, $3);
355 		} |
356 	AT NEXUS NUMBER
357 	      = { cur.d_conn = TO_NEXUS; };
358 
359 Info_list:
360 	Info_list Info
361 		|
362 	/* lambda */
363 		;
364 
365 Info:
366 	BUS NUMBER	/* controller scbus1 at ahc0 bus 1 - twin channel */
367 	      = {
368 		if (cur.d_conn != 0 && cur.d_conn->d_type == CONTROLLER)
369 			cur.d_slave = $2;
370 		else
371 			yyerror("can't specify a bus to something "
372 				 "other than a controller");
373 		} |
374 	TARGET NUMBER
375 	      = { cur.d_target = $2; } |
376 	UNIT NUMBER
377 	      = { cur.d_lun = $2; } |
378 	DRIVE NUMBER
379 	      = { cur.d_drive = $2; } |
380 	IRQ NUMBER
381 	      = { cur.d_irq = $2; } |
382 	DRQ NUMBER
383 	      = { cur.d_drq = $2; } |
384 	IOMEM NUMBER
385 	      = { cur.d_maddr = $2; } |
386 	IOSIZ NUMBER
387 	      = { cur.d_msize = $2; } |
388 	PORT device_name
389 	      = { cur.d_port = $2; } |
390 	PORT NUMBER
391 	      = { cur.d_portn = $2; } |
392 	FLAGS NUMBER
393 	      = { cur.d_flags = $2; } |
394 	DISABLE
395 	      = { cur.d_disabled = 1; } |
396 	CONFLICTS
397 	      = { cur.d_conflicts = 1; };
398 
399 %%
400 
401 static void
402 yyerror(s)
403 	char *s;
404 {
405 
406 	warnx("line %d: %s", yyline + 1, s);
407 }
408 
409 /*
410  * add a device to the list of devices
411  */
412 static void
413 newdev(dp)
414 	register struct device *dp;
415 {
416 	register struct device *np, *xp;
417 
418 	if (dp->d_unit >= 0) {
419 		for (xp = dtab; xp != 0; xp = xp->d_next) {
420 			if ((xp->d_unit == dp->d_unit) &&
421 			    eq(xp->d_name, dp->d_name)) {
422 				warnx("line %d: already seen device %s%d",
423 				    yyline, xp->d_name, xp->d_unit);
424 			}
425 		}
426 	}
427 	np = (struct device *) malloc(sizeof *np);
428 	memset(np, 0, sizeof(*np));
429 	*np = *dp;
430 	np->d_next = 0;
431 	if (curp == 0)
432 		dtab = np;
433 	else
434 		curp->d_next = np;
435 	curp = np;
436 }
437 
438 
439 /*
440  * find the pointer to connect to the given device and number.
441  * returns 0 if no such device and prints an error message
442  */
443 static struct device *
444 connect(dev, num)
445 	register char *dev;
446 	register int num;
447 {
448 	register struct device *dp;
449 
450 	if (num == QUES)
451 		return (huhcon(dev));
452 	for (dp = dtab; dp != 0; dp = dp->d_next) {
453 		if ((num != dp->d_unit) || !eq(dev, dp->d_name))
454 			continue;
455 		if (dp->d_type != CONTROLLER) {
456 			(void) snprintf(errbuf, sizeof(errbuf),
457 			    "%s connected to non-controller", dev);
458 			yyerror(errbuf);
459 			return (0);
460 		}
461 		return (dp);
462 	}
463 	(void) snprintf(errbuf, sizeof(errbuf), "%s %d not defined", dev, num);
464 	yyerror(errbuf);
465 	return (0);
466 }
467 
468 /*
469  * connect to an unspecific thing
470  */
471 static struct device *
472 huhcon(dev)
473 	register char *dev;
474 {
475 	register struct device *dp, *dcp;
476 	struct device rdev;
477 	int oldtype;
478 
479 	/*
480 	 * First make certain that there are some of these to wildcard on
481 	 */
482 	for (dp = dtab; dp != 0; dp = dp->d_next)
483 		if (eq(dp->d_name, dev))
484 			break;
485 	if (dp == 0) {
486 		(void) snprintf(errbuf, sizeof(errbuf), "no %s's to wildcard",
487 		   dev);
488 		yyerror(errbuf);
489 		return (0);
490 	}
491 	oldtype = dp->d_type;
492 	dcp = dp->d_conn;
493 	/*
494 	 * Now see if there is already a wildcard entry for this device
495 	 * (e.g. Search for a "uba ?")
496 	 */
497 	for (; dp != 0; dp = dp->d_next)
498 		if (eq(dev, dp->d_name) && dp->d_unit == -1)
499 			break;
500 	/*
501 	 * If there isn't, make one because everything needs to be connected
502 	 * to something.
503 	 */
504 	if (dp == 0) {
505 		dp = &rdev;
506 		init_dev(dp);
507 		dp->d_unit = QUES;
508 		dp->d_name = ns(dev);
509 		dp->d_type = oldtype;
510 		newdev(dp);
511 		dp = curp;
512 		/*
513 		 * Connect it to the same thing that other similar things are
514 		 * connected to, but make sure it is a wildcard unit
515 		 * (e.g. up connected to sc ?, here we make connect sc? to a
516 		 * uba?).  If other things like this are on the NEXUS or
517 		 * if they aren't connected to anything, then make the same
518 		 * connection, else call ourself to connect to another
519 		 * unspecific device.
520 		 */
521 		if (dcp == TO_NEXUS || dcp == 0)
522 			dp->d_conn = dcp;
523 		else
524 			dp->d_conn = connect(dcp->d_name, QUES);
525 	}
526 	return (dp);
527 }
528 
529 void
530 init_dev(dp)
531 	register struct device *dp;
532 {
533 
534 	dp->d_name = "OHNO!!!";
535 	dp->d_type = DEVICE;
536 	dp->d_conn = 0;
537 	dp->d_conflicts = 0;
538 	dp->d_disabled = 0;
539 	dp->d_flags = dp->d_dk = 0;
540 	dp->d_slave = dp->d_lun = dp->d_target = dp->d_drive = dp->d_unit = \
541 		dp->d_count = UNKNOWN;
542 	dp->d_port = (char *)0;
543 	dp->d_portn = -1;
544 	dp->d_irq = -1;
545 	dp->d_drq = -1;
546 	dp->d_maddr = 0;
547 	dp->d_msize = 0;
548 }
549