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