1 1.37 martin /* $NetBSD: ofdev.c,v 1.37 2017/09/15 13:25:34 martin Exp $ */ 2 1.1 mrg 3 1.1 mrg /* 4 1.1 mrg * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 1.1 mrg * Copyright (C) 1995, 1996 TooLs GmbH. 6 1.1 mrg * All rights reserved. 7 1.1 mrg * 8 1.1 mrg * Redistribution and use in source and binary forms, with or without 9 1.1 mrg * modification, are permitted provided that the following conditions 10 1.1 mrg * are met: 11 1.1 mrg * 1. Redistributions of source code must retain the above copyright 12 1.1 mrg * notice, this list of conditions and the following disclaimer. 13 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 mrg * notice, this list of conditions and the following disclaimer in the 15 1.1 mrg * documentation and/or other materials provided with the distribution. 16 1.1 mrg * 3. All advertising materials mentioning features or use of this software 17 1.1 mrg * must display the following acknowledgement: 18 1.1 mrg * This product includes software developed by TooLs GmbH. 19 1.1 mrg * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 1.1 mrg * derived from this software without specific prior written permission. 21 1.1 mrg * 22 1.1 mrg * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 1.1 mrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 1.1 mrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 1.1 mrg * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 1.1 mrg * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 1.1 mrg * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 1.1 mrg * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 1.1 mrg * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 1.1 mrg * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 1.1 mrg * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 1.1 mrg */ 33 1.1 mrg /* 34 1.1 mrg * Device I/O routines using Open Firmware 35 1.1 mrg */ 36 1.1 mrg #include <sys/param.h> 37 1.1 mrg #include <sys/disklabel.h> 38 1.1 mrg #ifdef NETBOOT 39 1.1 mrg #include <netinet/in.h> 40 1.1 mrg #endif 41 1.1 mrg 42 1.1 mrg #include <lib/libsa/stand.h> 43 1.1 mrg #include <lib/libsa/ufs.h> 44 1.26 eeh #include <lib/libsa/lfs.h> 45 1.1 mrg #include <lib/libsa/cd9660.h> 46 1.1 mrg #ifdef NETBOOT 47 1.1 mrg #include <lib/libsa/nfs.h> 48 1.19 mlelstv #include <lib/libsa/tftp.h> 49 1.1 mrg #endif 50 1.1 mrg #include <lib/libkern/libkern.h> 51 1.1 mrg 52 1.1 mrg #include <dev/sun/disklabel.h> 53 1.5 martin #include <dev/raidframe/raidframevar.h> 54 1.5 martin 55 1.10 cdi #include <machine/promlib.h> 56 1.10 cdi 57 1.1 mrg #include "ofdev.h" 58 1.15 martin #include "boot.h" 59 1.30 tsutsui #include "net.h" 60 1.1 mrg 61 1.1 mrg extern char bootdev[]; 62 1.27 martin extern bool root_fs_quickseekable; 63 1.1 mrg 64 1.37 martin struct btinfo_bootdev_unit bi_unit; 65 1.37 martin bool bootinfo_pass_bootunit = false; 66 1.37 martin 67 1.1 mrg /* 68 1.1 mrg * This is ugly. A path on a sparc machine is something like this: 69 1.1 mrg * 70 1.1 mrg * [device] [-<options] [path] [-options] [otherstuff] [-<more options] 71 1.1 mrg * 72 1.1 mrg */ 73 1.1 mrg 74 1.15 martin char * 75 1.12 uwe filename(char *str, char *ppart) 76 1.1 mrg { 77 1.1 mrg char *cp, *lp; 78 1.1 mrg char savec; 79 1.1 mrg int dhandle; 80 1.1 mrg char devtype[16]; 81 1.7 junyoung 82 1.1 mrg lp = str; 83 1.1 mrg devtype[0] = 0; 84 1.17 martin *ppart = '\0'; 85 1.1 mrg for (cp = str; *cp; lp = cp) { 86 1.1 mrg /* For each component of the path name... */ 87 1.1 mrg while (*++cp && *cp != '/'); 88 1.1 mrg savec = *cp; 89 1.1 mrg *cp = 0; 90 1.1 mrg /* ...look whether there is a device with this name */ 91 1.10 cdi dhandle = prom_finddevice(str); 92 1.15 martin DPRINTF(("filename: prom_finddevice(%s) returned %x\n", 93 1.15 martin str, dhandle)); 94 1.1 mrg *cp = savec; 95 1.1 mrg if (dhandle == -1) { 96 1.4 mrg /* 97 1.4 mrg * if not, lp is the delimiter between device and 98 1.4 mrg * path. if the last component was a block device. 99 1.4 mrg */ 100 1.36 martin if (strcmp(devtype, "block") == 0 101 1.36 martin || strcmp(devtype, "scsi") == 0) { 102 1.1 mrg /* search for arguments */ 103 1.15 martin DPRINTF(("filename: hunting for arguments " 104 1.17 martin "in %s\n", lp)); 105 1.3 martin for (cp = lp; ; ) { 106 1.3 martin cp--; 107 1.4 mrg if (cp < str || 108 1.4 mrg cp[0] == '/' || 109 1.4 mrg (cp[0] == ' ' && (cp+1) != lp && 110 1.4 mrg cp[1] == '-')) 111 1.3 martin break; 112 1.3 martin } 113 1.5 martin if (cp >= str && *cp == '-') 114 1.17 martin /* found arguments, make firmware 115 1.17 martin ignore them */ 116 1.17 martin *cp = 0; 117 1.17 martin for (cp = lp; *--cp && *cp != ',' 118 1.17 martin && *cp != ':';) 119 1.17 martin ; 120 1.17 martin if (cp[0] == ':' && cp[1] >= 'a' && 121 1.17 martin cp[1] <= 'a' + MAXPARTITIONS) { 122 1.17 martin *ppart = cp[1]; 123 1.17 martin cp[0] = '\0'; 124 1.1 mrg } 125 1.1 mrg } 126 1.15 martin DPRINTF(("filename: found %s\n",lp)); 127 1.1 mrg return lp; 128 1.17 martin } else if (_prom_getprop(dhandle, "device_type", devtype, 129 1.17 martin sizeof devtype) < 0) 130 1.1 mrg devtype[0] = 0; 131 1.1 mrg } 132 1.31 nakayama DPRINTF(("filename: not found\n")); 133 1.1 mrg return 0; 134 1.1 mrg } 135 1.1 mrg 136 1.1 mrg static int 137 1.21 dsl strategy(void *devdata, int rw, daddr_t blk, size_t size, void *buf, size_t *rsize) 138 1.1 mrg { 139 1.1 mrg struct of_dev *dev = devdata; 140 1.1 mrg u_quad_t pos; 141 1.1 mrg int n; 142 1.7 junyoung 143 1.1 mrg if (rw != F_READ) 144 1.1 mrg return EPERM; 145 1.1 mrg if (dev->type != OFDEV_DISK) 146 1.1 mrg panic("strategy"); 147 1.7 junyoung 148 1.1 mrg #ifdef NON_DEBUG 149 1.7 junyoung printf("strategy: block %lx, partition offset %lx, blksz %lx\n", 150 1.1 mrg (long)blk, (long)dev->partoff, (long)dev->bsize); 151 1.7 junyoung printf("strategy: seek position should be: %lx\n", 152 1.1 mrg (long)((blk + dev->partoff) * dev->bsize)); 153 1.1 mrg #endif 154 1.1 mrg pos = (u_quad_t)(blk + dev->partoff) * dev->bsize; 155 1.7 junyoung 156 1.1 mrg for (;;) { 157 1.1 mrg #ifdef NON_DEBUG 158 1.1 mrg printf("strategy: seeking to %lx\n", (long)pos); 159 1.1 mrg #endif 160 1.10 cdi if (prom_seek(dev->handle, pos) < 0) 161 1.1 mrg break; 162 1.1 mrg #ifdef NON_DEBUG 163 1.1 mrg printf("strategy: reading %lx at %p\n", (long)size, buf); 164 1.1 mrg #endif 165 1.10 cdi n = prom_read(dev->handle, buf, size); 166 1.1 mrg if (n == -2) 167 1.1 mrg continue; 168 1.1 mrg if (n < 0) 169 1.1 mrg break; 170 1.1 mrg *rsize = n; 171 1.1 mrg return 0; 172 1.1 mrg } 173 1.1 mrg return EIO; 174 1.1 mrg } 175 1.1 mrg 176 1.1 mrg static int 177 1.12 uwe devclose(struct open_file *of) 178 1.1 mrg { 179 1.1 mrg struct of_dev *op = of->f_devdata; 180 1.1 mrg 181 1.7 junyoung #ifdef NETBOOT 182 1.1 mrg if (op->type == OFDEV_NET) 183 1.1 mrg net_close(op); 184 1.1 mrg #endif 185 1.10 cdi prom_close(op->handle); 186 1.1 mrg op->handle = -1; 187 1.30 tsutsui return 0; 188 1.1 mrg } 189 1.1 mrg 190 1.11 mrg static struct devsw ofdevsw[1] = { 191 1.30 tsutsui { 192 1.30 tsutsui "OpenFirmware", 193 1.30 tsutsui strategy, 194 1.30 tsutsui (int (*)(struct open_file *, ...))nodev, 195 1.30 tsutsui devclose, 196 1.30 tsutsui noioctl 197 1.30 tsutsui } 198 1.1 mrg }; 199 1.11 mrg int ndevs = sizeof ofdevsw / sizeof ofdevsw[0]; 200 1.1 mrg 201 1.26 eeh 202 1.1 mrg #ifdef SPARC_BOOT_UFS 203 1.26 eeh static struct fs_ops file_system_ufs[] = 204 1.26 eeh { FS_OPS(ufs), FS_OPS(ffsv2), FS_OPS(lfsv1), FS_OPS(lfsv2) }; 205 1.1 mrg #endif 206 1.14 martin #ifdef SPARC_BOOT_CD9660 207 1.8 junyoung static struct fs_ops file_system_cd9660 = FS_OPS(cd9660); 208 1.1 mrg #endif 209 1.1 mrg #ifdef NETBOOT 210 1.8 junyoung static struct fs_ops file_system_nfs = FS_OPS(nfs); 211 1.19 mlelstv static struct fs_ops file_system_tftp = FS_OPS(tftp); 212 1.1 mrg #endif 213 1.1 mrg 214 1.26 eeh struct fs_ops file_system[7]; 215 1.1 mrg int nfsys; 216 1.1 mrg 217 1.1 mrg static struct of_dev ofdev = { 218 1.1 mrg -1, 219 1.1 mrg }; 220 1.1 mrg 221 1.1 mrg char opened_name[256]; 222 1.1 mrg int floppyboot; 223 1.1 mrg 224 1.1 mrg /************************************************************************ 225 1.1 mrg * 226 1.1 mrg * The rest of this was taken from arch/sparc64/scsi/sun_disklabel.c 227 1.1 mrg * and then substantially rewritten by Gordon W. Ross 228 1.1 mrg * 229 1.1 mrg ************************************************************************/ 230 1.1 mrg 231 1.1 mrg /* What partition types to assume for Sun disklabels: */ 232 1.1 mrg static u_char 233 1.1 mrg sun_fstypes[8] = { 234 1.1 mrg FS_BSDFFS, /* a */ 235 1.1 mrg FS_SWAP, /* b */ 236 1.1 mrg FS_OTHER, /* c - whole disk */ 237 1.1 mrg FS_BSDFFS, /* d */ 238 1.1 mrg FS_BSDFFS, /* e */ 239 1.1 mrg FS_BSDFFS, /* f */ 240 1.1 mrg FS_BSDFFS, /* g */ 241 1.1 mrg FS_BSDFFS, /* h */ 242 1.1 mrg }; 243 1.1 mrg 244 1.1 mrg /* 245 1.1 mrg * Given a SunOS disk label, set lp to a BSD disk label. 246 1.1 mrg * Returns NULL on success, else an error string. 247 1.1 mrg * 248 1.1 mrg * The BSD label is cleared out before this is called. 249 1.1 mrg */ 250 1.1 mrg static char * 251 1.12 uwe disklabel_sun_to_bsd(char *cp, struct disklabel *lp) 252 1.1 mrg { 253 1.1 mrg struct sun_disklabel *sl; 254 1.1 mrg struct partition *npp; 255 1.1 mrg struct sun_dkpart *spp; 256 1.1 mrg int i, secpercyl; 257 1.1 mrg u_short cksum, *sp1, *sp2; 258 1.1 mrg 259 1.1 mrg sl = (struct sun_disklabel *)cp; 260 1.1 mrg 261 1.1 mrg /* Verify the XOR check. */ 262 1.1 mrg sp1 = (u_short *)sl; 263 1.1 mrg sp2 = (u_short *)(sl + 1); 264 1.1 mrg cksum = 0; 265 1.1 mrg while (sp1 < sp2) 266 1.1 mrg cksum ^= *sp1++; 267 1.1 mrg if (cksum != 0) 268 1.1 mrg return("SunOS disk label, bad checksum"); 269 1.1 mrg 270 1.1 mrg /* Format conversion. */ 271 1.1 mrg lp->d_magic = DISKMAGIC; 272 1.1 mrg lp->d_magic2 = DISKMAGIC; 273 1.1 mrg memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname)); 274 1.1 mrg 275 1.1 mrg lp->d_secsize = 512; 276 1.1 mrg lp->d_nsectors = sl->sl_nsectors; 277 1.1 mrg lp->d_ntracks = sl->sl_ntracks; 278 1.1 mrg lp->d_ncylinders = sl->sl_ncylinders; 279 1.1 mrg 280 1.1 mrg secpercyl = sl->sl_nsectors * sl->sl_ntracks; 281 1.1 mrg lp->d_secpercyl = secpercyl; 282 1.1 mrg lp->d_secperunit = secpercyl * sl->sl_ncylinders; 283 1.1 mrg 284 1.1 mrg lp->d_sparespercyl = sl->sl_sparespercyl; 285 1.1 mrg lp->d_acylinders = sl->sl_acylinders; 286 1.1 mrg lp->d_rpm = sl->sl_rpm; 287 1.1 mrg lp->d_interleave = sl->sl_interleave; 288 1.1 mrg 289 1.1 mrg lp->d_npartitions = 8; 290 1.1 mrg /* These are as defined in <ufs/ffs/fs.h> */ 291 1.1 mrg lp->d_bbsize = 8192; /* XXX */ 292 1.1 mrg lp->d_sbsize = 8192; /* XXX */ 293 1.1 mrg 294 1.1 mrg for (i = 0; i < 8; i++) { 295 1.1 mrg spp = &sl->sl_part[i]; 296 1.1 mrg npp = &lp->d_partitions[i]; 297 1.1 mrg npp->p_offset = spp->sdkp_cyloffset * secpercyl; 298 1.1 mrg npp->p_size = spp->sdkp_nsectors; 299 1.15 martin DPRINTF(("partition %d start %x size %x\n", i, (int)npp->p_offset, (int)npp->p_size)); 300 1.1 mrg if (npp->p_size == 0) { 301 1.1 mrg npp->p_fstype = FS_UNUSED; 302 1.1 mrg } else { 303 1.1 mrg npp->p_fstype = sun_fstypes[i]; 304 1.1 mrg if (npp->p_fstype == FS_BSDFFS) { 305 1.1 mrg /* 306 1.1 mrg * The sun label does not store the FFS fields, 307 1.1 mrg * so just set them with default values here. 308 1.1 mrg */ 309 1.1 mrg npp->p_fsize = 1024; 310 1.1 mrg npp->p_frag = 8; 311 1.1 mrg npp->p_cpg = 16; 312 1.1 mrg } 313 1.1 mrg } 314 1.1 mrg } 315 1.1 mrg 316 1.1 mrg lp->d_checksum = 0; 317 1.1 mrg lp->d_checksum = dkcksum(lp); 318 1.15 martin DPRINTF(("disklabel_sun_to_bsd: success!\n")); 319 1.1 mrg return (NULL); 320 1.1 mrg } 321 1.1 mrg 322 1.1 mrg /* 323 1.1 mrg * Find a valid disklabel. 324 1.1 mrg */ 325 1.1 mrg static char * 326 1.12 uwe search_label(struct of_dev *devp, u_long off, char *buf, 327 1.12 uwe struct disklabel *lp, u_long off0) 328 1.1 mrg { 329 1.30 tsutsui size_t readsize; 330 1.1 mrg struct disklabel *dlp; 331 1.1 mrg struct sun_disklabel *slp; 332 1.7 junyoung 333 1.1 mrg /* minimal requirements for archtypal disk label */ 334 1.1 mrg if (lp->d_secperunit == 0) 335 1.1 mrg lp->d_secperunit = 0x1fffffff; 336 1.1 mrg lp->d_npartitions = 1; 337 1.1 mrg if (lp->d_partitions[0].p_size == 0) 338 1.1 mrg lp->d_partitions[0].p_size = 0x1fffffff; 339 1.1 mrg lp->d_partitions[0].p_offset = 0; 340 1.1 mrg 341 1.30 tsutsui if (strategy(devp, F_READ, LABELSECTOR, DEV_BSIZE, buf, &readsize) 342 1.30 tsutsui || readsize != DEV_BSIZE) 343 1.1 mrg return ("Cannot read label"); 344 1.1 mrg /* Check for a NetBSD disk label. */ 345 1.1 mrg dlp = (struct disklabel *) (buf + LABELOFFSET); 346 1.1 mrg if (dlp->d_magic == DISKMAGIC) { 347 1.1 mrg if (dkcksum(dlp)) 348 1.1 mrg return ("NetBSD disk label corrupted"); 349 1.1 mrg *lp = *dlp; 350 1.15 martin DPRINTF(("search_label: found NetBSD label\n")); 351 1.1 mrg return (NULL); 352 1.1 mrg } 353 1.1 mrg 354 1.1 mrg /* Check for a Sun disk label (for PROM compatibility). */ 355 1.1 mrg slp = (struct sun_disklabel *) buf; 356 1.1 mrg if (slp->sl_magic == SUN_DKMAGIC) 357 1.1 mrg return (disklabel_sun_to_bsd(buf, lp)); 358 1.1 mrg 359 1.1 mrg 360 1.35 joerg memset(buf, 0, DEV_BSIZE); 361 1.1 mrg return ("no disk label"); 362 1.1 mrg } 363 1.1 mrg 364 1.37 martin static void 365 1.37 martin device_target_unit(const char *dev, int ihandle) 366 1.37 martin { 367 1.37 martin cell_t units[4], phandle, myself, depth = 0, odepth = 0, cnt; 368 1.37 martin char buf[256]; 369 1.37 martin 370 1.37 martin /* init the data passed to the kernel */ 371 1.37 martin bootinfo_pass_bootunit = false; 372 1.37 martin memset(&bi_unit, 0, sizeof(bi_unit)); 373 1.37 martin 374 1.37 martin /* save old my-self value */ 375 1.37 martin OF_interpret("my-self", 0, 1, &myself); 376 1.37 martin /* set our device as my-self */ 377 1.37 martin OF_interpret("to my-self", 1, 0, HDL2CELL(ihandle)); 378 1.37 martin 379 1.37 martin /* 380 1.37 martin * my-unit delivers a variable number of cells, we could 381 1.37 martin * walk up the path and find a #address-cells value that 382 1.37 martin * describes it, but it seems to just work this simple 383 1.37 martin * way. 384 1.37 martin */ 385 1.37 martin OF_interpret("depth", 0, 1, &odepth); 386 1.37 martin OF_interpret("my-unit depth", 0, 5, &depth, 387 1.37 martin &units[0], &units[1], &units[2], &units[3]); 388 1.37 martin cnt = depth-odepth; 389 1.37 martin 390 1.37 martin /* 391 1.37 martin * Old versions of QEMU's OpenBIOS have a bug in the 392 1.37 martin * CIF implementation for instance_to_package, test 393 1.37 martin * for that explicitly here and work around it if needed. 394 1.37 martin */ 395 1.37 martin phandle = OF_instance_to_package(ihandle); 396 1.37 martin OF_package_to_path(phandle, buf, sizeof(buf)); 397 1.37 martin buf[sizeof(buf)-1] = 0; 398 1.37 martin if (strlen(buf) > 2 && strlen(dev) > 2 && 399 1.37 martin strncmp(buf, dev, strlen(buf)) != 0) { 400 1.37 martin DPRINTF(("OpenBIOS workaround: phandle %" PRIx32 "is %s, " 401 1.37 martin "does not match %s\n", (uint32_t)phandle, buf, dev)); 402 1.37 martin OF_interpret("my-self ihandle>non-interposed-phandle", 403 1.37 martin 0, 1, &phandle); 404 1.37 martin OF_package_to_path(phandle, buf, sizeof(buf)); 405 1.37 martin DPRINTF(("new phandle %" PRIx32 " is %s\n", 406 1.37 martin (uint32_t)phandle, buf)); 407 1.37 martin } 408 1.37 martin 409 1.37 martin bi_unit.phandle = phandle; 410 1.37 martin bi_unit.parent = OF_parent(phandle); 411 1.37 martin bi_unit.lun = units[cnt > 2 ? 3 : 1]; 412 1.37 martin bi_unit.target = units[cnt > 2 ? 2 : 0]; 413 1.37 martin if (cnt >= 4) 414 1.37 martin bi_unit.wwn = (uint64_t)units[0] << 32 | (uint32_t)units[1]; 415 1.37 martin DPRINTF(("boot device package: %" PRIx32 ", parent: %" PRIx32 416 1.37 martin ", lun: %" PRIu32 ", target: %" PRIu32 ", wwn: %" PRIx64 "\n", 417 1.37 martin bi_unit.phandle, bi_unit.parent, bi_unit.lun, bi_unit.target, 418 1.37 martin bi_unit.wwn)); 419 1.37 martin 420 1.37 martin /* restore my-self */ 421 1.37 martin OF_interpret("to my-self", 1, 0, myself); 422 1.37 martin 423 1.37 martin /* now that we have gatherd all the details, pass them to the kernel */ 424 1.37 martin bootinfo_pass_bootunit = true; 425 1.37 martin } 426 1.37 martin 427 1.1 mrg int 428 1.12 uwe devopen(struct open_file *of, const char *name, char **file) 429 1.1 mrg { 430 1.1 mrg char *cp; 431 1.1 mrg char partition; 432 1.16 martin char fname[256], devname[256]; 433 1.13 martin union { 434 1.13 martin char buf[DEV_BSIZE]; 435 1.13 martin struct disklabel label; 436 1.13 martin } b; 437 1.1 mrg struct disklabel label; 438 1.15 martin int handle, part, try = 0; 439 1.30 tsutsui size_t readsize; 440 1.30 tsutsui char *errmsg = NULL, *pp = NULL, savedpart = 0; 441 1.1 mrg int error = 0; 442 1.37 martin bool get_target_unit = false; 443 1.1 mrg 444 1.1 mrg if (ofdev.handle != -1) 445 1.34 martin panic("devopen: ofdev already in use"); 446 1.1 mrg if (of->f_flags != F_READ) 447 1.1 mrg return EPERM; 448 1.15 martin DPRINTF(("devopen: you want %s\n", name)); 449 1.1 mrg strcpy(fname, name); 450 1.1 mrg cp = filename(fname, &partition); 451 1.1 mrg if (cp) { 452 1.13 martin strcpy(b.buf, cp); 453 1.1 mrg *cp = 0; 454 1.1 mrg } 455 1.13 martin if (!cp || !b.buf[0]) 456 1.13 martin strcpy(b.buf, DEFAULT_KERNEL); 457 1.1 mrg if (!*fname) 458 1.1 mrg strcpy(fname, bootdev); 459 1.1 mrg strcpy(opened_name, fname); 460 1.1 mrg if (partition) { 461 1.1 mrg cp = opened_name + strlen(opened_name); 462 1.1 mrg *cp++ = ':'; 463 1.1 mrg *cp++ = partition; 464 1.1 mrg *cp = 0; 465 1.1 mrg } 466 1.5 martin *file = opened_name + strlen(opened_name); 467 1.13 martin if (b.buf[0] != '/') 468 1.1 mrg strcat(opened_name, "/"); 469 1.13 martin strcat(opened_name, b.buf); 470 1.15 martin DPRINTF(("devopen: trying %s\n", fname)); 471 1.10 cdi if ((handle = prom_finddevice(fname)) == -1) 472 1.1 mrg return ENOENT; 473 1.15 martin DPRINTF(("devopen: found %s\n", fname)); 474 1.13 martin if (_prom_getprop(handle, "name", b.buf, sizeof b.buf) < 0) 475 1.1 mrg return ENXIO; 476 1.15 martin DPRINTF(("devopen: %s is called %s\n", fname, b.buf)); 477 1.13 martin floppyboot = !strcmp(b.buf, "floppy"); 478 1.13 martin if (_prom_getprop(handle, "device_type", b.buf, sizeof b.buf) < 0) 479 1.1 mrg return ENXIO; 480 1.15 martin DPRINTF(("devopen: %s is a %s device\n", fname, b.buf)); 481 1.36 martin if (strcmp(b.buf, "block") == 0 || strcmp(b.buf, "scsi") == 0) { 482 1.37 martin 483 1.37 martin get_target_unit = true; 484 1.37 martin 485 1.15 martin pp = strrchr(fname, ':'); 486 1.15 martin if (pp && pp[1] >= 'a' && pp[1] <= 'f' && pp[2] == 0) { 487 1.15 martin savedpart = pp[1]; 488 1.15 martin } else { 489 1.15 martin savedpart = 'a'; 490 1.16 martin handle = prom_open(fname); 491 1.16 martin if (handle != -1) { 492 1.16 martin OF_instance_to_path(handle, devname, 493 1.16 martin sizeof(devname)); 494 1.16 martin DPRINTF(("real path: %s\n", devname)); 495 1.16 martin prom_close(handle); 496 1.16 martin pp = devname + strlen(devname); 497 1.16 martin if (pp > devname + 3) pp -= 2; 498 1.16 martin if (pp[0] == ':') 499 1.16 martin savedpart = pp[1]; 500 1.16 martin } 501 1.15 martin pp = fname + strlen(fname); 502 1.15 martin pp[0] = ':'; 503 1.15 martin pp[2] = '\0'; 504 1.15 martin } 505 1.15 martin pp[1] = 'c'; 506 1.15 martin DPRINTF(("devopen: replacing by whole disk device %s\n", 507 1.15 martin fname)); 508 1.16 martin if (savedpart) 509 1.16 martin partition = savedpart; 510 1.15 martin } 511 1.15 martin 512 1.15 martin open_again: 513 1.15 martin DPRINTF(("devopen: opening %s\n", fname)); 514 1.10 cdi if ((handle = prom_open(fname)) == -1) { 515 1.15 martin DPRINTF(("devopen: open of %s failed\n", fname)); 516 1.15 martin if (pp && savedpart) { 517 1.15 martin if (try == 0) { 518 1.15 martin pp[0] = '\0'; 519 1.15 martin try = 1; 520 1.15 martin } else { 521 1.15 martin pp[0] = ':'; 522 1.15 martin pp[1] = savedpart; 523 1.15 martin pp = NULL; 524 1.15 martin savedpart = '\0'; 525 1.15 martin } 526 1.15 martin goto open_again; 527 1.15 martin } 528 1.1 mrg return ENXIO; 529 1.1 mrg } 530 1.15 martin DPRINTF(("devopen: %s is now open\n", fname)); 531 1.37 martin 532 1.37 martin if (get_target_unit) 533 1.37 martin device_target_unit(fname, handle); 534 1.37 martin 535 1.22 cegger memset(&ofdev, 0, sizeof ofdev); 536 1.1 mrg ofdev.handle = handle; 537 1.36 martin if (strcmp(b.buf, "block") == 0 || strcmp(b.buf, "scsi") == 0) { 538 1.1 mrg ofdev.type = OFDEV_DISK; 539 1.1 mrg ofdev.bsize = DEV_BSIZE; 540 1.1 mrg /* First try to find a disklabel without MBR partitions */ 541 1.15 martin DPRINTF(("devopen: trying to read disklabel\n")); 542 1.1 mrg if (strategy(&ofdev, F_READ, 543 1.30 tsutsui LABELSECTOR, DEV_BSIZE, b.buf, &readsize) != 0 544 1.30 tsutsui || readsize != DEV_BSIZE 545 1.13 martin || (errmsg = getdisklabel(b.buf, &label))) { 546 1.28 martin if (errmsg) { 547 1.28 martin DPRINTF(("devopen: getdisklabel returned %s\n", 548 1.28 martin errmsg)); 549 1.28 martin } 550 1.1 mrg /* Else try MBR partitions */ 551 1.13 martin errmsg = search_label(&ofdev, 0, b.buf, &label, 0); 552 1.7 junyoung if (errmsg) { 553 1.6 grant printf("devopen: search_label returned %s\n", errmsg); 554 1.1 mrg error = ERDLAB; 555 1.1 mrg } 556 1.1 mrg if (error && error != ERDLAB) 557 1.1 mrg goto bad; 558 1.1 mrg } 559 1.1 mrg 560 1.1 mrg if (error == ERDLAB) { 561 1.1 mrg /* No, label, just use complete disk */ 562 1.1 mrg ofdev.partoff = 0; 563 1.15 martin if (pp && savedpart) { 564 1.15 martin pp[1] = savedpart; 565 1.15 martin prom_close(handle); 566 1.15 martin if ((handle = prom_open(fname)) == -1) { 567 1.15 martin DPRINTF(("devopen: open of %s failed\n", 568 1.15 martin fname)); 569 1.15 martin return ENXIO; 570 1.15 martin } 571 1.15 martin ofdev.handle = handle; 572 1.15 martin DPRINTF(("devopen: back to original device %s\n", 573 1.15 martin fname)); 574 1.15 martin } 575 1.1 mrg } else { 576 1.1 mrg part = partition ? partition - 'a' : 0; 577 1.1 mrg ofdev.partoff = label.d_partitions[part].p_offset; 578 1.31 nakayama DPRINTF(("devopen: setting partition %d offset %lx\n", 579 1.15 martin part, ofdev.partoff)); 580 1.2 mrg if (label.d_partitions[part].p_fstype == FS_RAID) { 581 1.2 mrg ofdev.partoff += RF_PROTECTED_SECTORS; 582 1.15 martin DPRINTF(("devopen: found RAID partition, " 583 1.31 nakayama "adjusting offset to %lx\n", ofdev.partoff)); 584 1.2 mrg } 585 1.1 mrg } 586 1.7 junyoung 587 1.15 martin nfsys = 0; 588 1.11 mrg of->f_dev = ofdevsw; 589 1.1 mrg of->f_devdata = &ofdev; 590 1.1 mrg #ifdef SPARC_BOOT_UFS 591 1.26 eeh memcpy(&file_system[nfsys++], &file_system_ufs[0], sizeof file_system[0]); 592 1.26 eeh memcpy(&file_system[nfsys++], &file_system_ufs[1], sizeof file_system[0]); 593 1.26 eeh memcpy(&file_system[nfsys++], &file_system_ufs[2], sizeof file_system[0]); 594 1.26 eeh memcpy(&file_system[nfsys++], &file_system_ufs[3], sizeof file_system[0]); 595 1.1 mrg #endif 596 1.14 martin #ifdef SPARC_BOOT_CD9660 597 1.26 eeh memcpy(&file_system[nfsys++], &file_system_cd9660, sizeof file_system[0]); 598 1.1 mrg #endif 599 1.15 martin DPRINTF(("devopen: return 0\n")); 600 1.1 mrg return 0; 601 1.1 mrg } 602 1.1 mrg #ifdef NETBOOT 603 1.13 martin if (!strcmp(b.buf, "network")) { 604 1.30 tsutsui if ((error = net_open(&ofdev)) != 0) 605 1.19 mlelstv goto bad; 606 1.19 mlelstv 607 1.1 mrg ofdev.type = OFDEV_NET; 608 1.11 mrg of->f_dev = ofdevsw; 609 1.25 martin of->f_devdata = &ofdev; 610 1.19 mlelstv 611 1.19 mlelstv if (!strncmp(*file,"/tftp:",6)) { 612 1.19 mlelstv *file += 6; 613 1.24 cegger memcpy(&file_system[0], &file_system_tftp, sizeof file_system[0]); 614 1.33 tsutsui if (net_tftp_bootp((int **)&of->f_devdata)) { 615 1.19 mlelstv net_close(&ofdev); 616 1.19 mlelstv goto bad; 617 1.19 mlelstv } 618 1.27 martin root_fs_quickseekable = false; 619 1.19 mlelstv } else { 620 1.24 cegger memcpy(&file_system[0], &file_system_nfs, sizeof file_system[0]); 621 1.30 tsutsui if ((error = net_mountroot()) != 0) { 622 1.19 mlelstv net_close(&ofdev); 623 1.19 mlelstv goto bad; 624 1.19 mlelstv } 625 1.19 mlelstv } 626 1.1 mrg nfsys = 1; 627 1.1 mrg return 0; 628 1.1 mrg } 629 1.1 mrg #endif 630 1.1 mrg error = EFTYPE; 631 1.1 mrg bad: 632 1.15 martin DPRINTF(("devopen: error %d, cannot open device\n", error)); 633 1.10 cdi prom_close(handle); 634 1.1 mrg ofdev.handle = -1; 635 1.1 mrg return error; 636 1.1 mrg } 637