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