xref: /original-bsd/usr.sbin/config/config.y (revision bdfadfff)
1 %union {
2 	char	*str;
3 	int	val;
4 	struct	file_list *file;
5 	struct	idlst *lst;
6 }
7 
8 %token	AND
9 %token	ANY
10 %token	ARGS
11 %token	AT
12 %token	BIO
13 %token	COMMA
14 %token	CONFIG
15 %token	CONTROLLER
16 %token	CPU
17 %token	CSR
18 %token	DEVICE
19 %token	DISK
20 %token	DRIVE
21 %token	DRQ
22 %token	DST
23 %token	DUMPS
24 %token	EQUALS
25 %token	FLAGS
26 %token	HZ
27 %token	IDENT
28 %token	IOMEM
29 %token	IOSIZ
30 %token	IRQ
31 %token	MACHINE
32 %token	MAJOR
33 %token	MASTER
34 %token	MAXUSERS
35 %token	MINOR
36 %token	MINUS
37 %token	NET
38 %token	NEXUS
39 %token	ON
40 %token	OPTIONS
41 %token	MAKEOPTIONS
42 %token	PORT
43 %token	PRIORITY
44 %token	PSEUDO_DEVICE
45 %token	ROOT
46 %token	SEMICOLON
47 %token	SIZE
48 %token	SLAVE
49 %token	SWAP
50 %token	TIMEZONE
51 %token	TTY
52 %token	TRACE
53 %token	VECTOR
54 
55 %token	<str>	ID
56 %token	<val>	NUMBER
57 %token	<val>	FPNUMBER
58 
59 %type	<str>	Save_id
60 %type	<str>	Opt_value
61 %type	<str>	Dev
62 %type	<lst>	Id_list
63 %type	<val>	optional_size
64 %type	<str>	device_name
65 %type	<val>	major_minor
66 %type	<val>	arg_device_spec
67 %type	<val>	root_device_spec
68 %type	<val>	dump_device_spec
69 %type	<file>	swap_device_spec
70 
71 %{
72 
73 /*
74  * Copyright (c) 1988 Regents of the University of California.
75  * All rights reserved.
76  *
77  * %sccs.include.redist.c%
78  *
79  *	@(#)config.y	5.17 (Berkeley) 06/25/92
80  */
81 
82 #include "config.h"
83 #include <ctype.h>
84 #include <stdio.h>
85 
86 struct	device cur;
87 struct	device *curp = 0;
88 char	*temp_id;
89 char	*val_id;
90 
91 %}
92 %%
93 Configuration:
94 	Many_specs
95 		= { verifysystemspecs(); }
96 		;
97 
98 Many_specs:
99 	Many_specs Spec
100 		|
101 	/* lambda */
102 		;
103 
104 Spec:
105 	Device_spec SEMICOLON
106 	      = { newdev(&cur); } |
107 	Config_spec SEMICOLON
108 		|
109 	TRACE SEMICOLON
110 	      = { do_trace = !do_trace; } |
111 	SEMICOLON
112 		|
113 	error SEMICOLON
114 		;
115 
116 Config_spec:
117 	MACHINE Save_id
118 	    = {
119 		if (!strcmp($2, "vax")) {
120 			machine = MACHINE_VAX;
121 			machinename = "vax";
122 		} else if (!strcmp($2, "tahoe")) {
123 			machine = MACHINE_TAHOE;
124 			machinename = "tahoe";
125 		} else if (!strcmp($2, "hp300")) {
126 			machine = MACHINE_HP300;
127 			machinename = "hp300";
128 		} else if (!strcmp($2, "i386")) {
129 			machine = MACHINE_I386;
130 			machinename = "i386";
131 		} else if (!strcmp($2, "mips")) {
132 			machine = MACHINE_MIPS;
133 			machinename = "mips";
134 		} else if (!strcmp($2, "pmax")) {
135 			machine = MACHINE_PMAX;
136 			machinename = "pmax";
137 		} else if (!strcmp($2, "luna68k")) {
138 			machine = MACHINE_LUNA68K;
139 			machinename = "luna68k";
140 		} else
141 			yyerror("Unknown machine type");
142 	      } |
143 	CPU Save_id
144 	      = {
145 		struct cputype *cp =
146 		    (struct cputype *)malloc(sizeof (struct cputype));
147 		cp->cpu_name = ns($2);
148 		cp->cpu_next = cputype;
149 		cputype = cp;
150 		free(temp_id);
151 	      } |
152 	OPTIONS Opt_list
153 		|
154 	MAKEOPTIONS Mkopt_list
155 		|
156 	IDENT ID
157 	      = { ident = ns($2); } |
158 	System_spec
159 		|
160 	HZ NUMBER
161 	      = { hz = $2; }|
162 	TIMEZONE NUMBER
163 	      = { zone = 60 * $2; check_tz(); } |
164 	TIMEZONE NUMBER DST NUMBER
165 	      = { zone = 60 * $2; dst = $4; check_tz(); } |
166 	TIMEZONE NUMBER DST
167 	      = { zone = 60 * $2; dst = 1; check_tz(); } |
168 	TIMEZONE FPNUMBER
169 	      = { zone = $2; check_tz(); } |
170 	TIMEZONE FPNUMBER DST NUMBER
171 	      = { zone = $2; dst = $4; check_tz(); } |
172 	TIMEZONE FPNUMBER DST
173 	      = { zone = $2; dst = 1; check_tz(); } |
174 	TIMEZONE MINUS NUMBER
175 	      = { zone = -60 * $3; check_tz(); } |
176 	TIMEZONE MINUS NUMBER DST NUMBER
177 	      = { zone = -60 * $3; dst = $5; check_tz(); } |
178 	TIMEZONE MINUS NUMBER DST
179 	      = { zone = -60 * $3; dst = 1; check_tz(); } |
180 	TIMEZONE MINUS FPNUMBER
181 	      = { zone = -$3; check_tz(); } |
182 	TIMEZONE MINUS FPNUMBER DST NUMBER
183 	      = { zone = -$3; dst = $5; check_tz(); } |
184 	TIMEZONE MINUS FPNUMBER DST
185 	      = { zone = -$3; dst = 1; check_tz(); } |
186 	MAXUSERS NUMBER
187 	      = { maxusers = $2; };
188 
189 System_spec:
190 	  System_id System_parameter_list
191 		= { checksystemspec(*confp); }
192 	;
193 
194 System_id:
195 	  CONFIG Save_id
196 		= { mkconf($2); }
197 	;
198 
199 System_parameter_list:
200 	  System_parameter_list System_parameter
201 	| System_parameter
202 	;
203 
204 System_parameter:
205 	  swap_spec
206 	| root_spec
207 	| dump_spec
208 	| arg_spec
209 	;
210 
211 swap_spec:
212 	  SWAP optional_on swap_device_list
213 	;
214 
215 swap_device_list:
216 	  swap_device_list AND swap_device
217 	| swap_device
218 	;
219 
220 swap_device:
221 	  swap_device_spec optional_size
222 	      = { mkswap(*confp, $1, $2); }
223 	;
224 
225 swap_device_spec:
226 	  device_name
227 		= {
228 			struct file_list *fl = newswap();
229 
230 			if (eq($1, "generic"))
231 				fl->f_fn = $1;
232 			else {
233 				fl->f_swapdev = nametodev($1, 0, 'b');
234 				fl->f_fn = devtoname(fl->f_swapdev);
235 			}
236 			$$ = fl;
237 		}
238 	| major_minor
239 		= {
240 			struct file_list *fl = newswap();
241 
242 			fl->f_swapdev = $1;
243 			fl->f_fn = devtoname($1);
244 			$$ = fl;
245 		}
246 	;
247 
248 root_spec:
249 	  ROOT optional_on root_device_spec
250 		= {
251 			struct file_list *fl = *confp;
252 
253 			if (fl && fl->f_rootdev != NODEV)
254 				yyerror("extraneous root device specification");
255 			else
256 				fl->f_rootdev = $3;
257 		}
258 	;
259 
260 root_device_spec:
261 	  device_name
262 		= { $$ = nametodev($1, 0, 'a'); }
263 	| major_minor
264 	;
265 
266 dump_spec:
267 	  DUMPS optional_on dump_device_spec
268 		= {
269 			struct file_list *fl = *confp;
270 
271 			if (fl && fl->f_dumpdev != NODEV)
272 				yyerror("extraneous dump device specification");
273 			else
274 				fl->f_dumpdev = $3;
275 		}
276 
277 	;
278 
279 dump_device_spec:
280 	  device_name
281 		= { $$ = nametodev($1, 0, 'b'); }
282 	| major_minor
283 	;
284 
285 arg_spec:
286 	  ARGS optional_on arg_device_spec
287 		= { yyerror("arg device specification obsolete, ignored"); }
288 	;
289 
290 arg_device_spec:
291 	  device_name
292 		= { $$ = nametodev($1, 0, 'b'); }
293 	| major_minor
294 	;
295 
296 major_minor:
297 	  MAJOR NUMBER MINOR NUMBER
298 		= { $$ = makedev($2, $4); }
299 	;
300 
301 optional_on:
302 	  ON
303 	| /* empty */
304 	;
305 
306 optional_size:
307 	  SIZE NUMBER
308 	      = { $$ = $2; }
309 	| /* empty */
310 	      = { $$ = 0; }
311 	;
312 
313 device_name:
314 	  Save_id
315 		= { $$ = $1; }
316 	| Save_id NUMBER
317 		= {
318 			char buf[80];
319 
320 			(void) sprintf(buf, "%s%d", $1, $2);
321 			$$ = ns(buf); free($1);
322 		}
323 	| Save_id NUMBER ID
324 		= {
325 			char buf[80];
326 
327 			(void) sprintf(buf, "%s%d%s", $1, $2, $3);
328 			$$ = ns(buf); free($1);
329 		}
330 	;
331 
332 Opt_list:
333 	Opt_list COMMA Option
334 		|
335 	Option
336 		;
337 
338 Option:
339 	Save_id
340 	      = {
341 		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
342 		op->op_name = ns($1);
343 		op->op_next = opt;
344 		op->op_value = 0;
345 		opt = op;
346 		free(temp_id);
347 	      } |
348 	Save_id EQUALS Opt_value
349 	      = {
350 		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
351 		op->op_name = ns($1);
352 		op->op_next = opt;
353 		op->op_value = ns($3);
354 		opt = op;
355 		free(temp_id);
356 		free(val_id);
357 	      } ;
358 
359 Opt_value:
360 	ID
361 	      = { $$ = val_id = ns($1); } |
362 	NUMBER
363 	      = {
364 		char nb[16];
365 	        (void) sprintf(nb, "%d", $1);
366 		$$ = val_id = ns(nb);
367 	      } ;
368 
369 
370 Save_id:
371 	ID
372 	      = { $$ = temp_id = ns($1); }
373 	;
374 
375 Mkopt_list:
376 	Mkopt_list COMMA Mkoption
377 		|
378 	Mkoption
379 		;
380 
381 Mkoption:
382 	Save_id EQUALS Opt_value
383 	      = {
384 		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
385 		op->op_name = ns($1);
386 		op->op_next = mkopt;
387 		op->op_value = ns($3);
388 		mkopt = op;
389 		free(temp_id);
390 		free(val_id);
391 	      } ;
392 
393 Dev:
394 	ID
395 	      = { $$ = ns($1); }
396 	;
397 
398 Device_spec:
399 	DEVICE Dev_name Dev_info Int_spec
400 	      = { cur.d_type = DEVICE; } |
401 	MASTER Dev_name Dev_info Int_spec
402 	      = { cur.d_type = MASTER; } |
403 	DISK Dev_name Dev_info Int_spec
404 	      = { cur.d_dk = 1; cur.d_type = DEVICE; } |
405 	CONTROLLER Dev_name Dev_info Int_spec
406 	      = { cur.d_type = CONTROLLER; } |
407 	PSEUDO_DEVICE Init_dev Dev
408 	      = {
409 		cur.d_name = $3;
410 		cur.d_type = PSEUDO_DEVICE;
411 		} |
412 	PSEUDO_DEVICE Init_dev Dev NUMBER
413 	      = {
414 		cur.d_name = $3;
415 		cur.d_type = PSEUDO_DEVICE;
416 		cur.d_slave = $4;
417 		};
418 
419 Dev_name:
420 	Init_dev Dev NUMBER
421 	      = {
422 		cur.d_name = $2;
423 		if (eq($2, "mba"))
424 			seen_mba = 1;
425 		else if (eq($2, "uba"))
426 			seen_uba = 1;
427 		else if (eq($2, "vba"))
428 			seen_vba = 1;
429 		else if (eq($2, "isa"))
430 			seen_isa = 1;
431 		cur.d_unit = $3;
432 		};
433 
434 Init_dev:
435 	/* lambda */
436 	      = { init_dev(&cur); };
437 
438 Dev_info:
439 	Con_info Info_list
440 		|
441 	/* lambda */
442 		;
443 
444 Con_info:
445 	AT Dev NUMBER
446 	      = {
447 		if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba")) {
448 			(void) sprintf(errbuf,
449 				"%s must be connected to a nexus", cur.d_name);
450 			yyerror(errbuf);
451 		}
452 		cur.d_conn = connect($2, $3);
453 		} |
454 	AT NEXUS NUMBER
455 	      = { check_nexus(&cur, $3); cur.d_conn = TO_NEXUS; };
456 
457 Info_list:
458 	Info_list Info
459 		|
460 	/* lambda */
461 		;
462 
463 Info:
464 	CSR NUMBER
465 	      = { cur.d_addr = $2; } |
466 	DRIVE NUMBER
467 	      = { cur.d_drive = $2; } |
468 	SLAVE NUMBER
469 	      = {
470 		if (cur.d_conn != 0 && cur.d_conn != TO_NEXUS &&
471 		    cur.d_conn->d_type == MASTER)
472 			cur.d_slave = $2;
473 		else
474 			yyerror("can't specify slave--not to master");
475 		} |
476 	IRQ NUMBER
477 	      = { cur.d_irq = $2; } |
478 	DRQ NUMBER
479 	      = { cur.d_drq = $2; } |
480 	IOMEM NUMBER
481 	      = { cur.d_maddr = $2; } |
482 	IOSIZ NUMBER
483 	      = { cur.d_msize = $2; } |
484 	PORT device_name
485 	      = { cur.d_port = ns($2); } |
486 	PORT NUMBER
487 	      = { cur.d_portn = $2; } |
488 	TTY
489 	      = { cur.d_mask = "tty"; } |
490 	BIO
491 	      = { cur.d_mask = "bio"; } |
492 	NET
493 	      = { cur.d_mask = "net"; } |
494 	FLAGS NUMBER
495 	      = { cur.d_flags = $2; };
496 
497 Int_spec:
498 	VECTOR Id_list
499 	      = { cur.d_vec = $2; } |
500 	PRIORITY NUMBER
501 	      = { cur.d_pri = $2; } |
502 	/* lambda */
503 		;
504 
505 Id_list:
506 	Save_id
507 	      = {
508 		struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
509 		a->id = $1; a->id_next = 0; $$ = a;
510 		} |
511 	Save_id Id_list =
512 		{
513 		struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
514 	        a->id = $1; a->id_next = $2; $$ = a;
515 		};
516 
517 %%
518 
519 yyerror(s)
520 	char *s;
521 {
522 
523 	fprintf(stderr, "config: line %d: %s\n", yyline + 1, s);
524 }
525 
526 /*
527  * return the passed string in a new space
528  */
529 char *
530 ns(str)
531 	register char *str;
532 {
533 	register char *cp;
534 
535 	cp = malloc((unsigned)(strlen(str)+1));
536 	(void) strcpy(cp, str);
537 	return (cp);
538 }
539 
540 /*
541  * add a device to the list of devices
542  */
543 newdev(dp)
544 	register struct device *dp;
545 {
546 	register struct device *np;
547 
548 	np = (struct device *) malloc(sizeof *np);
549 	*np = *dp;
550 	np->d_next = 0;
551 	if (curp == 0)
552 		dtab = np;
553 	else
554 		curp->d_next = np;
555 	curp = np;
556 }
557 
558 /*
559  * note that a configuration should be made
560  */
561 mkconf(sysname)
562 	char *sysname;
563 {
564 	register struct file_list *fl, **flp;
565 
566 	fl = (struct file_list *) malloc(sizeof *fl);
567 	fl->f_type = SYSTEMSPEC;
568 	fl->f_needs = sysname;
569 	fl->f_rootdev = NODEV;
570 	fl->f_dumpdev = NODEV;
571 	fl->f_fn = 0;
572 	fl->f_next = 0;
573 	for (flp = confp; *flp; flp = &(*flp)->f_next)
574 		;
575 	*flp = fl;
576 	confp = flp;
577 }
578 
579 struct file_list *
580 newswap()
581 {
582 	struct file_list *fl = (struct file_list *)malloc(sizeof (*fl));
583 
584 	fl->f_type = SWAPSPEC;
585 	fl->f_next = 0;
586 	fl->f_swapdev = NODEV;
587 	fl->f_swapsize = 0;
588 	fl->f_needs = 0;
589 	fl->f_fn = 0;
590 	return (fl);
591 }
592 
593 /*
594  * Add a swap device to the system's configuration
595  */
596 mkswap(system, fl, size)
597 	struct file_list *system, *fl;
598 	int size;
599 {
600 	register struct file_list **flp;
601 	char name[80];
602 
603 	if (system == 0 || system->f_type != SYSTEMSPEC) {
604 		yyerror("\"swap\" spec precedes \"config\" specification");
605 		return;
606 	}
607 	if (size < 0) {
608 		yyerror("illegal swap partition size");
609 		return;
610 	}
611 	/*
612 	 * Append swap description to the end of the list.
613 	 */
614 	flp = &system->f_next;
615 	for (; *flp && (*flp)->f_type == SWAPSPEC; flp = &(*flp)->f_next)
616 		;
617 	fl->f_next = *flp;
618 	*flp = fl;
619 	fl->f_swapsize = size;
620 	/*
621 	 * If first swap device for this system,
622 	 * set up f_fn field to insure swap
623 	 * files are created with unique names.
624 	 */
625 	if (system->f_fn)
626 		return;
627 	if (eq(fl->f_fn, "generic"))
628 		system->f_fn = ns(fl->f_fn);
629 	else
630 		system->f_fn = ns(system->f_needs);
631 }
632 
633 /*
634  * find the pointer to connect to the given device and number.
635  * returns 0 if no such device and prints an error message
636  */
637 struct device *
638 connect(dev, num)
639 	register char *dev;
640 	register int num;
641 {
642 	register struct device *dp;
643 	struct device *huhcon();
644 
645 	if (num == QUES)
646 		return (huhcon(dev));
647 	for (dp = dtab; dp != 0; dp = dp->d_next) {
648 		if ((num != dp->d_unit) || !eq(dev, dp->d_name))
649 			continue;
650 		if (dp->d_type != CONTROLLER && dp->d_type != MASTER) {
651 			(void) sprintf(errbuf,
652 			    "%s connected to non-controller", dev);
653 			yyerror(errbuf);
654 			return (0);
655 		}
656 		return (dp);
657 	}
658 	(void) sprintf(errbuf, "%s %d not defined", dev, num);
659 	yyerror(errbuf);
660 	return (0);
661 }
662 
663 /*
664  * connect to an unspecific thing
665  */
666 struct device *
667 huhcon(dev)
668 	register char *dev;
669 {
670 	register struct device *dp, *dcp;
671 	struct device rdev;
672 	int oldtype;
673 
674 	/*
675 	 * First make certain that there are some of these to wildcard on
676 	 */
677 	for (dp = dtab; dp != 0; dp = dp->d_next)
678 		if (eq(dp->d_name, dev))
679 			break;
680 	if (dp == 0) {
681 		(void) sprintf(errbuf, "no %s's to wildcard", dev);
682 		yyerror(errbuf);
683 		return (0);
684 	}
685 	oldtype = dp->d_type;
686 	dcp = dp->d_conn;
687 	/*
688 	 * Now see if there is already a wildcard entry for this device
689 	 * (e.g. Search for a "uba ?")
690 	 */
691 	for (; dp != 0; dp = dp->d_next)
692 		if (eq(dev, dp->d_name) && dp->d_unit == -1)
693 			break;
694 	/*
695 	 * If there isn't, make one because everything needs to be connected
696 	 * to something.
697 	 */
698 	if (dp == 0) {
699 		dp = &rdev;
700 		init_dev(dp);
701 		dp->d_unit = QUES;
702 		dp->d_name = ns(dev);
703 		dp->d_type = oldtype;
704 		newdev(dp);
705 		dp = curp;
706 		/*
707 		 * Connect it to the same thing that other similar things are
708 		 * connected to, but make sure it is a wildcard unit
709 		 * (e.g. up connected to sc ?, here we make connect sc? to a
710 		 * uba?).  If other things like this are on the NEXUS or
711 		 * if they aren't connected to anything, then make the same
712 		 * connection, else call ourself to connect to another
713 		 * unspecific device.
714 		 */
715 		if (dcp == TO_NEXUS || dcp == 0)
716 			dp->d_conn = dcp;
717 		else
718 			dp->d_conn = connect(dcp->d_name, QUES);
719 	}
720 	return (dp);
721 }
722 
723 init_dev(dp)
724 	register struct device *dp;
725 {
726 
727 	dp->d_name = "OHNO!!!";
728 	dp->d_type = DEVICE;
729 	dp->d_conn = 0;
730 	dp->d_vec = 0;
731 	dp->d_addr = dp->d_flags = dp->d_dk = 0;
732 	dp->d_pri = -1;
733 	dp->d_slave = dp->d_drive = dp->d_unit = UNKNOWN;
734 	dp->d_port = (char *)0;
735 	dp->d_portn = 0;
736 	dp->d_irq = -1;
737 	dp->d_drq = -1;
738 	dp->d_maddr = 0;
739 	dp->d_msize = 0;
740 	dp->d_mask = "null";
741 }
742 
743 /*
744  * make certain that this is a reasonable type of thing to connect to a nexus
745  */
746 check_nexus(dev, num)
747 	register struct device *dev;
748 	int num;
749 {
750 
751 	switch (machine) {
752 
753 	case MACHINE_VAX:
754 		if (!eq(dev->d_name, "uba") && !eq(dev->d_name, "mba") &&
755 		    !eq(dev->d_name, "bi"))
756 			yyerror("only uba's, mba's, and bi's should be connected to the nexus");
757 		if (num != QUES)
758 			yyerror("can't give specific nexus numbers");
759 		break;
760 
761 	case MACHINE_TAHOE:
762 		if (!eq(dev->d_name, "vba"))
763 			yyerror("only vba's should be connected to the nexus");
764 		break;
765 
766 	case MACHINE_HP300:
767 	case MACHINE_LUNA68K:
768 		if (num != QUES)
769 			dev->d_addr = num;
770 		break;
771 
772 	case MACHINE_I386:
773 		if (!eq(dev->d_name, "isa"))
774 			yyerror("only isa's should be connected to the nexus");
775 		break;
776 	}
777 }
778 
779 /*
780  * Check the timezone to make certain it is sensible
781  */
782 
783 check_tz()
784 {
785 	if (abs(zone) > 12 * 60)
786 		yyerror("timezone is unreasonable");
787 	else
788 		hadtz = 1;
789 }
790 
791 /*
792  * Check system specification and apply defaulting
793  * rules on root, argument, dump, and swap devices.
794  */
795 checksystemspec(fl)
796 	register struct file_list *fl;
797 {
798 	char buf[BUFSIZ];
799 	register struct file_list *swap;
800 	int generic;
801 
802 	if (fl == 0 || fl->f_type != SYSTEMSPEC) {
803 		yyerror("internal error, bad system specification");
804 		exit(1);
805 	}
806 	swap = fl->f_next;
807 	generic = swap && swap->f_type == SWAPSPEC && eq(swap->f_fn, "generic");
808 	if (fl->f_rootdev == NODEV && !generic) {
809 		yyerror("no root device specified");
810 		exit(1);
811 	}
812 	/*
813 	 * Default swap area to be in 'b' partition of root's
814 	 * device.  If root specified to be other than on 'a'
815 	 * partition, give warning, something probably amiss.
816 	 */
817 	if (swap == 0 || swap->f_type != SWAPSPEC) {
818 		dev_t dev;
819 
820 		swap = newswap();
821 		dev = fl->f_rootdev;
822 		if (minor(dev) & 07) {
823 			(void) sprintf(buf,
824 "Warning, swap defaulted to 'b' partition with root on '%c' partition",
825 				(minor(dev) & 07) + 'a');
826 			yyerror(buf);
827 		}
828 		swap->f_swapdev =
829 		   makedev(major(dev), (minor(dev) &~ 07) | ('b' - 'a'));
830 		swap->f_fn = devtoname(swap->f_swapdev);
831 		mkswap(fl, swap, 0);
832 	}
833 	/*
834 	 * Make sure a generic swap isn't specified, along with
835 	 * other stuff (user must really be confused).
836 	 */
837 	if (generic) {
838 		if (fl->f_rootdev != NODEV)
839 			yyerror("root device specified with generic swap");
840 		if (fl->f_dumpdev != NODEV)
841 			yyerror("dump device specified with generic swap");
842 		return;
843 	}
844 	/*
845 	 * Default dump device and warn if place is not a
846 	 * swap area.
847 	 */
848 	if (fl->f_dumpdev == NODEV)
849 		fl->f_dumpdev = swap->f_swapdev;
850 	if (fl->f_dumpdev != swap->f_swapdev) {
851 		struct file_list *p = swap->f_next;
852 
853 		for (; p && p->f_type == SWAPSPEC; p = p->f_next)
854 			if (fl->f_dumpdev == p->f_swapdev)
855 				return;
856 		(void) sprintf(buf,
857 		    "Warning: dump device is not a swap partition");
858 		yyerror(buf);
859 	}
860 }
861 
862 /*
863  * Verify all devices specified in the system specification
864  * are present in the device specifications.
865  */
866 verifysystemspecs()
867 {
868 	register struct file_list *fl;
869 	dev_t checked[50], *verifyswap();
870 	register dev_t *pchecked = checked;
871 
872 	for (fl = conf_list; fl; fl = fl->f_next) {
873 		if (fl->f_type != SYSTEMSPEC)
874 			continue;
875 		if (!finddev(fl->f_rootdev))
876 			deverror(fl->f_needs, "root");
877 		*pchecked++ = fl->f_rootdev;
878 		pchecked = verifyswap(fl->f_next, checked, pchecked);
879 #define	samedev(dev1, dev2) \
880 	((minor(dev1) &~ 07) != (minor(dev2) &~ 07))
881 		if (!alreadychecked(fl->f_dumpdev, checked, pchecked)) {
882 			if (!finddev(fl->f_dumpdev))
883 				deverror(fl->f_needs, "dump");
884 			*pchecked++ = fl->f_dumpdev;
885 		}
886 	}
887 }
888 
889 /*
890  * Do as above, but for swap devices.
891  */
892 dev_t *
893 verifyswap(fl, checked, pchecked)
894 	register struct file_list *fl;
895 	dev_t checked[];
896 	register dev_t *pchecked;
897 {
898 
899 	for (;fl && fl->f_type == SWAPSPEC; fl = fl->f_next) {
900 		if (eq(fl->f_fn, "generic"))
901 			continue;
902 		if (alreadychecked(fl->f_swapdev, checked, pchecked))
903 			continue;
904 		if (!finddev(fl->f_swapdev))
905 			fprintf(stderr,
906 			   "config: swap device %s not configured", fl->f_fn);
907 		*pchecked++ = fl->f_swapdev;
908 	}
909 	return (pchecked);
910 }
911 
912 /*
913  * Has a device already been checked
914  * for it's existence in the configuration?
915  */
916 alreadychecked(dev, list, last)
917 	dev_t dev, list[];
918 	register dev_t *last;
919 {
920 	register dev_t *p;
921 
922 	for (p = list; p < last; p++)
923 		if (samedev(*p, dev))
924 			return (1);
925 	return (0);
926 }
927 
928 deverror(systemname, devtype)
929 	char *systemname, *devtype;
930 {
931 
932 	fprintf(stderr, "config: %s: %s device not configured\n",
933 		systemname, devtype);
934 }
935 
936 /*
937  * Look for the device in the list of
938  * configured hardware devices.  Must
939  * take into account stuff wildcarded.
940  */
941 /*ARGSUSED*/
942 finddev(dev)
943 	dev_t dev;
944 {
945 
946 	/* punt on this right now */
947 	return (1);
948 }
949