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