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 
69 u_int opendev;
70 
71 #define ispart(c)   ((c) >= 'a' && (c) <= 'h')
72 
73 static void usage(void);
74 static int devlookup(const char * ,int);
75 static int devparse(const char *, int *, int*, int*, int*, int*, char **);
76 
77 void
usage(void)78 usage(void)
79 {
80 
81           printf("Usage: device(adaptor, controller, drive, partition)file\n"
82               "       <device><unit><partitionletter>:file\n");
83 }
84 
85 static int
devlookup(const char * d,int len)86 devlookup(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  */
142 static int
devparse(const char * fname,int * dev,int * adapt,int * ctlr,int * unit,int * part,char ** file)143 devparse(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 
235 int
devopen(struct open_file * f,const char * fname,char ** file)236 devopen(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