1 /* $NetBSD: devopen.c,v 1.11 2014/08/10 07:40:49 isaki 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 ; 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 193 /* lookup device and get index */ 194 if ((*dev = devlookup(fname, s - fname)) < 0) 195 goto baddev; 196 197 /* isolate unit */ 198 if ((temp = atoi(s)) > 255) 199 goto bad; 200 *adapt = temp / 8; 201 *ctlr = temp % 8; 202 for (; isdigit(*s); s++) 203 ; 204 205 /* translate partition */ 206 if (!ispart(*s)) 207 goto bad; 208 209 *part = *s++ - 'a'; 210 if (*s != ':') 211 goto bad; 212 *file = ++s; 213 } 214 215 /* no device present */ 216 else 217 *file = (char *)fname; 218 219 /* return the remaining unparsed part as the file to boot */ 220 return 0; 221 222 bad: 223 usage(); 224 225 baddev: 226 return -1; 227 } 228 229 230 int 231 devopen(struct open_file *f, const char *fname, char **file) 232 { 233 int error; 234 int dev, adapt, ctlr, unit, part; 235 struct devsw *dp = &devsw[0]; 236 237 dev = B_TYPE(bootdev); 238 adapt = B_ADAPTOR(bootdev); 239 ctlr = B_CONTROLLER(bootdev); 240 unit = B_UNIT(bootdev); 241 part = B_PARTITION(bootdev); 242 243 if ((error = devparse(fname, &dev, &adapt, &ctlr, &unit, &part, file)) 244 != 0) 245 return error; 246 247 /* 248 * Set up filesystem type based on what device we're opening. 249 */ 250 switch (dev) { 251 case 0: /* ct */ 252 memcpy(file_system, file_system_rawfs, sizeof(struct fs_ops)); 253 break; 254 255 case 2: /* rd */ 256 case 4: /* sd */ 257 memcpy(file_system, file_system_ufs, sizeof(struct fs_ops)); 258 break; 259 260 case 6: /* le */ 261 memcpy(file_system, file_system_nfs, sizeof(struct fs_ops)); 262 break; 263 264 default: 265 /* XXX what else should we do here? */ 266 printf("WARNING: BOGUS BOOT DEV TYPE 0x%x!\n", dev); 267 return EIO; 268 } 269 270 dp = &devsw[dev]; 271 272 if (!dp->dv_open) 273 return ENODEV; 274 275 f->f_dev = dp; 276 277 if ((error = (*dp->dv_open)(f, adapt, ctlr, part)) == 0) { 278 if ((error = 279 (*punitsw[dev].p_punit)(adapt, ctlr, &unit)) != 0) { 280 goto bad; 281 } 282 opendev = MAKEBOOTDEV(dev, adapt, ctlr, unit, part); 283 return 0; 284 } 285 286 bad: 287 printf("%s(%d,%d,%d,%d): %s\n", devsw[dev].dv_name, 288 adapt, ctlr, unit, part, strerror(error)); 289 290 return error; 291 } 292