devopen.c revision 1.9
1/*	$NetBSD: devopen.c,v 1.9 2005/12/11 12:17:19 christos Exp $	*/
2
3/*-
4 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
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 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the NetBSD
21 *	Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 *    contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39/*-
40 *  Copyright (c) 1993 John Brezak
41 *  All rights reserved.
42 *
43 *  Redistribution and use in source and binary forms, with or without
44 *  modification, are permitted provided that the following conditions
45 *  are met:
46 *  1. Redistributions of source code must retain the above copyright
47 *     notice, this list of conditions and the following disclaimer.
48 *  2. Redistributions in binary form must reproduce the above copyright
49 *     notice, this list of conditions and the following disclaimer in the
50 *     documentation and/or other materials provided with the distribution.
51 *  3. The name of the author may not be used to endorse or promote products
52 *     derived from this software without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
55 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
56 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
57 * DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
58 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
59 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
60 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
62 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
63 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 * POSSIBILITY OF SUCH DAMAGE.
65 */
66
67#include <sys/param.h>
68#include <sys/reboot.h>
69
70#include <lib/libkern/libkern.h>
71
72#include <lib/libsa/stand.h>
73#include <hp300/stand/common/samachdep.h>
74
75u_int opendev;
76
77#define ispart(c)	((c) >= 'a' && (c) <= 'h')
78
79static void usage(void);
80static int devlookup(const char * ,int);
81static int devparse(const char *, int *, int*, int*, int*, int*, char **);
82
83int
84atoi(char *cp)
85{
86	int val = 0;
87
88	while (isdigit((unsigned char)*cp))
89		val = val * 10 + (*cp++ - '0');
90	return val;
91}
92
93void
94usage(void)
95{
96
97	printf("Usage: device(adaptor, controller, drive, partition)file\n"
98	    "       <device><unit><partitionletter>:file\n");
99}
100
101static int
102devlookup(const char *d, int len)
103{
104	struct devsw *dp = devsw;
105	int i;
106
107	for (i = 0; i < ndevs; i++, dp++) {
108		if (dp->dv_name && strncmp(dp->dv_name, d, len) == 0) {
109			/*
110			 * Set the filesystem and startup up according to
111			 * the device being opened.
112			 */
113			switch (i) {
114			case 0:	/* ct */
115				memcpy(file_system, file_system_rawfs,
116				    sizeof(struct fs_ops));
117				break;
118
119			case 2:	/* rd */
120			case 4:	/* sd */
121				memcpy(file_system, file_system_ufs,
122				    sizeof(struct fs_ops));
123				break;
124
125			case 6:	/* le */
126				memcpy(file_system, file_system_nfs,
127				    sizeof(struct fs_ops));
128				break;
129
130			default:
131				/* Agh!  What happened?! */
132				goto bad;
133			}
134		return i;
135		}
136	}
137
138 bad:
139	printf("No such device - Configured devices are:\n");
140	for (dp = devsw, i = 0; i < ndevs; i++, dp++)
141		if (dp->dv_name)
142			printf(" %s", dp->dv_name);
143	printf("\n");
144	errno = ENODEV;
145	return -1;
146}
147
148/*
149 * Parse a device spec in one of two forms.
150 *
151 * dev(adapt, ctlr, unit, part)file
152 * [A-Za-z]*[0-9]*[A-Za-z]:file
153 *    dev   unit  part
154 */
155static int
156devparse(const char *fname, int *dev, int *adapt, int *ctlr, int *unit,
157    int *part, char **file)
158{
159	int i;
160	char *s, *args[4];
161
162	/* get device name */
163	for (s = (char *)fname; *s && *s != '/' && *s != ':' && *s != '('; s++)
164		;
165
166	/* first form */
167	if (*s == '(') {
168		/* lookup device and get index */
169		if ((*dev = devlookup(fname, s - fname)) < 0)
170			goto baddev;
171
172		/* tokenize device ident */
173		args[0] = ++s;
174		for (args[0] = s, i = 1; *s && *s != ')'; s++) {
175			if (*s == ',')
176				args[i++] = ++s;
177		}
178		switch(i) {
179		case 4:
180			*adapt = atoi(args[0]);
181			*ctlr  = atoi(args[1]);
182			*unit  = atoi(args[2]);
183			*part  = atoi(args[3]);
184			break;
185		case 3:
186			*ctlr  = atoi(args[0]);
187			*unit  = atoi(args[1]);
188			*part  = atoi(args[2]);
189			break;
190		case 2:
191			*unit  = atoi(args[0]);
192			*part  = atoi(args[1]);
193			break;
194		case 1:
195			*part  = atoi(args[0]);
196			break;
197		case 0:
198			break;
199		}
200		*file = ++s;
201	}
202
203	/* second form */
204	else if (*s == ':') {
205		int temp;
206
207		/* isolate device */
208		for (s = (char *)fname; *s != ':' && !isdigit(*s); s++);
209
210			/* lookup device and get index */
211			if ((*dev = devlookup(fname, s - fname)) < 0)
212				goto baddev;
213
214		/* isolate unit */
215		if ((temp = atoi(s)) > 255)
216			goto bad;
217		*adapt = temp / 8;
218		*ctlr = temp % 8;
219		for (; isdigit(*s); s++)
220			;
221
222		/* translate partition */
223		if (!ispart(*s))
224			goto bad;
225
226		*part = *s++ - 'a';
227		if (*s != ':')
228			goto bad;
229		*file = ++s;
230	}
231
232	/* no device present */
233	else
234		*file = (char *)fname;
235
236	/* return the remaining unparsed part as the file to boot */
237	return 0;
238
239 bad:
240	usage();
241
242 baddev:
243	return -1;
244}
245
246
247int
248devopen(struct open_file *f, const char *fname, char **file)
249{
250	int error;
251	int dev, adapt, ctlr, unit, part;
252	struct devsw *dp = &devsw[0];
253
254	dev   = B_TYPE(bootdev);
255	adapt = B_ADAPTOR(bootdev);
256	ctlr  = B_CONTROLLER(bootdev);
257	unit  = B_UNIT(bootdev);
258	part  = B_PARTITION(bootdev);
259
260	if ((error = devparse(fname, &dev, &adapt, &ctlr, &unit, &part, file))
261	    != 0)
262		return error;
263
264	/*
265	 * Set up filesystem type based on what device we're opening.
266	 */
267	switch (dev) {
268	case 0:		/* ct */
269		memcpy(file_system, file_system_rawfs, sizeof(struct fs_ops));
270		break;
271
272	case 2:		/* rd */
273	case 4:		/* sd */
274		memcpy(file_system, file_system_ufs, sizeof(struct fs_ops));
275		break;
276
277	case 6:		/* le */
278		memcpy(file_system, file_system_nfs, sizeof(struct fs_ops));
279		break;
280
281	default:
282		/* XXX what else should we do here? */
283		printf("WARNING: BOGUS BOOT DEV TYPE 0x%x!\n", dev);
284		return EIO;
285	}
286
287	dp = &devsw[dev];
288
289	if (!dp->dv_open)
290		return ENODEV;
291
292	f->f_dev = dp;
293
294	if ((error = (*dp->dv_open)(f, adapt, ctlr, part)) == 0) {
295		if ((error =
296		    (*punitsw[dev].p_punit)(adapt, ctlr, &unit)) != 0) {
297			goto bad;
298		}
299		opendev = MAKEBOOTDEV(dev, adapt, ctlr, unit, part);
300		return 0;
301	}
302
303 bad:
304	printf("%s(%d,%d,%d,%d): %s\n", devsw[dev].dv_name,
305	    adapt, ctlr, unit, part, strerror(error));
306
307	return error;
308}
309