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