1 /* $NetBSD: devopen.c,v 1.12 2018/03/08 03:12:01 mrg 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/samachdep.h> 67 68 u_int opendev; 69 70 #define ispart(c) ((c) >= 'a' && (c) <= 'h') 71 72 static void usage(void); 73 static int devlookup(const char * ,int); 74 static int devparse(const char *, int *, int*, int*, int*, int*, char **); 75 76 void 77 usage(void) 78 { 79 80 printf("Usage: device(adaptor, controller, drive, partition)file\n" 81 " <device><unit><partitionletter>:file\n"); 82 } 83 84 static int 85 devlookup(const char *d, int len) 86 { 87 struct devsw *dp = devsw; 88 int i; 89 90 for (i = 0; i < ndevs; i++, dp++) { 91 if (dp->dv_name && strncmp(dp->dv_name, d, len) == 0) { 92 /* 93 * Set the filesystem and startup up according to 94 * the device being opened. 95 */ 96 switch (i) { 97 case 0: /* ct */ 98 memcpy(file_system, file_system_rawfs, 99 sizeof(struct fs_ops)); 100 break; 101 102 case 2: /* rd */ 103 case 4: /* sd */ 104 memcpy(file_system, file_system_ufs, 105 sizeof(struct fs_ops)); 106 break; 107 108 case 6: /* le */ 109 memcpy(file_system, file_system_nfs, 110 sizeof(struct fs_ops)); 111 break; 112 113 default: 114 /* Agh! What happened?! */ 115 goto bad; 116 } 117 return i; 118 } 119 } 120 121 bad: 122 printf("No such device - Configured devices are:\n"); 123 for (dp = devsw, i = 0; i < ndevs; i++, dp++) 124 if (dp->dv_name) 125 printf(" %s", dp->dv_name); 126 printf("\n"); 127 errno = ENODEV; 128 return -1; 129 } 130 131 /* 132 * Parse a device spec in one of two forms. 133 * 134 * dev(adapt, ctlr, unit, part)file 135 * [A-Za-z]*[0-9]*[A-Za-z]:file 136 * dev unit part 137 */ 138 static int 139 devparse(const char *fname, int *dev, int *adapt, int *ctlr, int *unit, 140 int *part, char **file) 141 { 142 int i; 143 char *s, *args[4]; 144 145 /* get device name */ 146 for (s = (char *)fname; *s && *s != '/' && *s != ':' && *s != '('; s++) 147 continue; 148 149 /* first form */ 150 if (*s == '(') { 151 /* lookup device and get index */ 152 if ((*dev = devlookup(fname, s - fname)) < 0) 153 goto baddev; 154 155 /* tokenize device ident */ 156 args[0] = ++s; 157 for (args[0] = s, i = 1; *s && *s != ')'; s++) { 158 if (*s == ',') 159 args[i++] = ++s; 160 } 161 switch(i) { 162 case 4: 163 *adapt = atoi(args[0]); 164 *ctlr = atoi(args[1]); 165 *unit = atoi(args[2]); 166 *part = atoi(args[3]); 167 break; 168 case 3: 169 *ctlr = atoi(args[0]); 170 *unit = atoi(args[1]); 171 *part = atoi(args[2]); 172 break; 173 case 2: 174 *unit = atoi(args[0]); 175 *part = atoi(args[1]); 176 break; 177 case 1: 178 *part = atoi(args[0]); 179 break; 180 case 0: 181 break; 182 } 183 *file = ++s; 184 } 185 186 /* second form */ 187 else if (*s == ':') { 188 int temp; 189 190 /* isolate device */ 191 for (s = (char *)fname; *s != ':' && !isdigit(*s); s++) 192 continue; 193 194 /* lookup device and get index */ 195 if ((*dev = devlookup(fname, s - fname)) < 0) 196 goto baddev; 197 198 /* isolate unit */ 199 if ((temp = atoi(s)) > 255) 200 goto bad; 201 *adapt = temp / 8; 202 *ctlr = temp % 8; 203 for (; isdigit(*s); s++) 204 continue; 205 206 /* translate partition */ 207 if (!ispart(*s)) 208 goto bad; 209 210 *part = *s++ - 'a'; 211 if (*s != ':') 212 goto bad; 213 *file = ++s; 214 } 215 216 /* no device present */ 217 else 218 *file = (char *)fname; 219 220 /* return the remaining unparsed part as the file to boot */ 221 return 0; 222 223 bad: 224 usage(); 225 226 baddev: 227 return -1; 228 } 229 230 231 int 232 devopen(struct open_file *f, const char *fname, char **file) 233 { 234 int error; 235 int dev, adapt, ctlr, unit, part; 236 struct devsw *dp = &devsw[0]; 237 238 dev = B_TYPE(bootdev); 239 adapt = B_ADAPTOR(bootdev); 240 ctlr = B_CONTROLLER(bootdev); 241 unit = B_UNIT(bootdev); 242 part = B_PARTITION(bootdev); 243 244 if ((error = devparse(fname, &dev, &adapt, &ctlr, &unit, &part, file)) 245 != 0) 246 return error; 247 248 /* 249 * Set up filesystem type based on what device we're opening. 250 */ 251 switch (dev) { 252 case 0: /* ct */ 253 memcpy(file_system, file_system_rawfs, sizeof(struct fs_ops)); 254 break; 255 256 case 2: /* rd */ 257 case 4: /* sd */ 258 memcpy(file_system, file_system_ufs, sizeof(struct fs_ops)); 259 break; 260 261 case 6: /* le */ 262 memcpy(file_system, file_system_nfs, sizeof(struct fs_ops)); 263 break; 264 265 default: 266 /* XXX what else should we do here? */ 267 printf("WARNING: BOGUS BOOT DEV TYPE 0x%x!\n", dev); 268 return EIO; 269 } 270 271 dp = &devsw[dev]; 272 273 if (!dp->dv_open) 274 return ENODEV; 275 276 f->f_dev = dp; 277 278 if ((error = (*dp->dv_open)(f, adapt, ctlr, part)) == 0) { 279 if ((error = 280 (*punitsw[dev].p_punit)(adapt, ctlr, &unit)) != 0) { 281 goto bad; 282 } 283 opendev = MAKEBOOTDEV(dev, adapt, ctlr, unit, part); 284 return 0; 285 } 286 287 bad: 288 printf("%s(%d,%d,%d,%d): %s\n", devsw[dev].dv_name, 289 adapt, ctlr, unit, part, strerror(error)); 290 291 return error; 292 } 293