Annotation of sys/arch/sparc64/stand/ofwboot/ofdev.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ofdev.c,v 1.9 2007/05/29 06:28:15 otto Exp $ */
! 2: /* $NetBSD: ofdev.c,v 1.1 2000/08/20 14:58:41 mrg Exp $ */
! 3:
! 4: /*
! 5: * Copyright (C) 1995, 1996 Wolfgang Solfrank.
! 6: * Copyright (C) 1995, 1996 TooLs GmbH.
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. All advertising materials mentioning features or use of this software
! 18: * must display the following acknowledgement:
! 19: * This product includes software developed by TooLs GmbH.
! 20: * 4. The name of TooLs GmbH may not be used to endorse or promote products
! 21: * derived from this software without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 26: * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
! 27: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 28: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! 29: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 30: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! 31: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! 32: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 33: */
! 34: /*
! 35: * Device I/O routines using Open Firmware
! 36: */
! 37: #include <sys/param.h>
! 38: #include <sys/disklabel.h>
! 39: #ifdef NETBOOT
! 40: #include <netinet/in.h>
! 41: #endif
! 42:
! 43: #include <lib/libsa/stand.h>
! 44: #include <lib/libsa/ufs.h>
! 45: #include <lib/libsa/cd9660.h>
! 46: #ifdef NETBOOT
! 47: #include <lib/libsa/nfs.h>
! 48: #endif
! 49:
! 50: #include <dev/sun/disklabel.h>
! 51: #include "ofdev.h"
! 52:
! 53: extern char bootdev[];
! 54:
! 55: /*
! 56: * This is ugly. A path on a sparc machine is something like this:
! 57: *
! 58: * [device] [-<options] [path] [-options] [otherstuff] [-<more options]
! 59: *
! 60: */
! 61:
! 62: static char *
! 63: filename(str, ppart)
! 64: char *str;
! 65: char *ppart;
! 66: {
! 67: char *cp, *lp;
! 68: char savec;
! 69: int dhandle;
! 70: char devtype[16];
! 71:
! 72: lp = str;
! 73: devtype[0] = 0;
! 74: *ppart = 0;
! 75: for (cp = str; *cp; lp = cp) {
! 76: /* For each component of the path name... */
! 77: while (*++cp && *cp != '/');
! 78: savec = *cp;
! 79: *cp = 0;
! 80: /* ...look whether there is a device with this name */
! 81: dhandle = OF_finddevice(str);
! 82: #ifdef NOTDEF_DEBUG
! 83: printf("filename: OF_finddevice(%s) says %x\n",
! 84: str, dhandle);
! 85: #endif
! 86: *cp = savec;
! 87: if (dhandle == -1) {
! 88: /* if not, lp is the delimiter between device and path */
! 89: /* if the last component was a block device... */
! 90: if (!strcmp(devtype, "block")) {
! 91: /* search for arguments */
! 92: #ifdef NOTDEF_DEBUG
! 93: printf("filename: hunting for arguments in %s\n", str);
! 94: #endif
! 95: for (cp = lp;
! 96: --cp >= str && *cp != '/' && *cp != '-';);
! 97: if (cp >= str && *cp == '-') {
! 98: /* found arguments, make firmware ignore them */
! 99: *cp = 0;
! 100: for (cp = lp; *--cp && *cp != ',';);
! 101: if (*++cp >= 'a' && *cp <= 'a' + MAXPARTITIONS)
! 102: *ppart = *cp;
! 103: }
! 104: }
! 105: #ifdef NOTDEF_DEBUG
! 106: printf("filename: found %s\n",lp);
! 107: #endif
! 108: return lp;
! 109: } else if (OF_getprop(dhandle, "device_type", devtype, sizeof devtype) < 0)
! 110: devtype[0] = 0;
! 111: }
! 112: #ifdef NOTDEF_DEBUG
! 113: printf("filename: not found\n",lp);
! 114: #endif
! 115: return 0;
! 116: }
! 117:
! 118: static int
! 119: strategy(devdata, rw, blk, size, buf, rsize)
! 120: void *devdata;
! 121: int rw;
! 122: daddr_t blk;
! 123: size_t size;
! 124: void *buf;
! 125: size_t *rsize;
! 126: {
! 127: struct of_dev *dev = devdata;
! 128: u_quad_t pos;
! 129: int n;
! 130:
! 131: if (rw != F_READ)
! 132: return EPERM;
! 133: if (dev->type != OFDEV_DISK)
! 134: panic("strategy");
! 135:
! 136: #ifdef NON_DEBUG
! 137: printf("strategy: block %lx, partition offset %lx, blksz %lx\n",
! 138: (long)blk, (long)dev->partoff, (long)dev->bsize);
! 139: printf("strategy: seek position should be: %lx\n",
! 140: (long)((blk + dev->partoff) * dev->bsize));
! 141: #endif
! 142: pos = (u_quad_t)(blk + dev->partoff) * dev->bsize;
! 143:
! 144: for (;;) {
! 145: #ifdef NON_DEBUG
! 146: printf("strategy: seeking to %lx\n", (long)pos);
! 147: #endif
! 148: if (OF_seek(dev->handle, pos) < 0)
! 149: break;
! 150: #ifdef NON_DEBUG
! 151: printf("strategy: reading %lx at %p\n", (long)size, buf);
! 152: #endif
! 153: n = OF_read(dev->handle, buf, size);
! 154: if (n == -2)
! 155: continue;
! 156: if (n < 0)
! 157: break;
! 158: *rsize = n;
! 159: return 0;
! 160: }
! 161: return EIO;
! 162: }
! 163:
! 164: static int
! 165: devclose(of)
! 166: struct open_file *of;
! 167: {
! 168: struct of_dev *op = of->f_devdata;
! 169:
! 170: #ifdef NETBOOT
! 171: if (op->type == OFDEV_NET)
! 172: net_close(op);
! 173: #endif
! 174: OF_close(op->handle);
! 175: op->handle = -1;
! 176: }
! 177:
! 178: static struct devsw devsw[1] = {
! 179: "OpenFirmware",
! 180: strategy,
! 181: (int (*)(struct open_file *, ...))nodev,
! 182: devclose,
! 183: noioctl
! 184: };
! 185: int ndevs = sizeof devsw / sizeof devsw[0];
! 186:
! 187: #ifdef SPARC_BOOT_UFS
! 188: static struct fs_ops file_system_ufs = {
! 189: ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat
! 190: };
! 191: #endif
! 192: #ifdef SPARC_BOOT_HSFS
! 193: static struct fs_ops file_system_cd9660 = {
! 194: cd9660_open, cd9660_close, cd9660_read, cd9660_write, cd9660_seek,
! 195: cd9660_stat
! 196: };
! 197: #endif
! 198: #ifdef NETBOOT
! 199: static struct fs_ops file_system_nfs = {
! 200: nfs_open, nfs_close, nfs_read, nfs_write, nfs_seek, nfs_stat
! 201: };
! 202: #endif
! 203:
! 204: struct fs_ops file_system[3];
! 205: int nfsys;
! 206:
! 207: static struct of_dev ofdev = {
! 208: -1,
! 209: };
! 210:
! 211: char opened_name[256];
! 212:
! 213: static u_long
! 214: get_long(p)
! 215: const void *p;
! 216: {
! 217: const unsigned char *cp = p;
! 218:
! 219: return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24);
! 220: }
! 221: /************************************************************************
! 222: *
! 223: * The rest of this was taken from arch/sparc64/scsi/sun_disklabel.c
! 224: * and then substantially rewritten by Gordon W. Ross
! 225: *
! 226: ************************************************************************/
! 227:
! 228: /* What partition types to assume for Sun disklabels: */
! 229: static u_char
! 230: sun_fstypes[8] = {
! 231: FS_BSDFFS, /* a */
! 232: FS_SWAP, /* b */
! 233: FS_OTHER, /* c - whole disk */
! 234: FS_BSDFFS, /* d */
! 235: FS_BSDFFS, /* e */
! 236: FS_BSDFFS, /* f */
! 237: FS_BSDFFS, /* g */
! 238: FS_BSDFFS, /* h */
! 239: };
! 240:
! 241: /*
! 242: * Given a SunOS disk label, set lp to a BSD disk label.
! 243: * Returns NULL on success, else an error string.
! 244: *
! 245: * The BSD label is cleared out before this is called.
! 246: */
! 247: static char *
! 248: disklabel_sun_to_bsd(cp, lp)
! 249: char *cp;
! 250: struct disklabel *lp;
! 251: {
! 252: struct sun_disklabel *sl;
! 253: struct partition *npp;
! 254: struct sun_dkpart *spp;
! 255: int i, secpercyl;
! 256: u_short cksum, *sp1, *sp2;
! 257:
! 258: sl = (struct sun_disklabel *)cp;
! 259:
! 260: /* Verify the XOR check. */
! 261: sp1 = (u_short *)sl;
! 262: sp2 = (u_short *)(sl + 1);
! 263: cksum = 0;
! 264: while (sp1 < sp2)
! 265: cksum ^= *sp1++;
! 266: if (cksum != 0)
! 267: return("SunOS disk label, bad checksum");
! 268:
! 269: /* Format conversion. */
! 270: lp->d_magic = DISKMAGIC;
! 271: lp->d_magic2 = DISKMAGIC;
! 272: memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname));
! 273:
! 274: lp->d_secsize = 512;
! 275: lp->d_nsectors = sl->sl_nsectors;
! 276: lp->d_ntracks = sl->sl_ntracks;
! 277: lp->d_ncylinders = sl->sl_ncylinders;
! 278:
! 279: secpercyl = sl->sl_nsectors * sl->sl_ntracks;
! 280: lp->d_secpercyl = secpercyl;
! 281: lp->d_secperunit = secpercyl * sl->sl_ncylinders;
! 282:
! 283: lp->d_sparespercyl = sl->sl_sparespercyl;
! 284: lp->d_acylinders = sl->sl_acylinders;
! 285: lp->d_rpm = sl->sl_rpm;
! 286: lp->d_interleave = sl->sl_interleave;
! 287:
! 288: lp->d_npartitions = 8;
! 289: /* These are as defined in <ufs/ffs/fs.h> */
! 290: lp->d_bbsize = 8192; /* XXX */
! 291: lp->d_sbsize = 8192; /* XXX */
! 292:
! 293: for (i = 0; i < 8; i++) {
! 294: spp = &sl->sl_part[i];
! 295: npp = &lp->d_partitions[i];
! 296: npp->p_offset = spp->sdkp_cyloffset * secpercyl;
! 297: npp->p_size = spp->sdkp_nsectors;
! 298: #ifdef NOTDEF_DEBUG
! 299: printf("partition %d start %x size %x\n", i, (int)npp->p_offset, (int)npp->p_size);
! 300: #endif
! 301: if (npp->p_size == 0) {
! 302: npp->p_fstype = FS_UNUSED;
! 303: } else {
! 304: npp->p_fstype = sun_fstypes[i];
! 305: if (npp->p_fstype == FS_BSDFFS) {
! 306: /*
! 307: * The sun label does not store the FFS fields,
! 308: * so just set them with default values here.
! 309: */
! 310: npp->p_fragblock =
! 311: DISKLABELV1_FFS_FRAGBLOCK(1024, 8);
! 312: npp->p_cpg = 16;
! 313: }
! 314: }
! 315: }
! 316:
! 317: lp->d_checksum = 0;
! 318: lp->d_checksum = dkcksum(lp);
! 319: #ifdef NOTDEF_DEBUG
! 320: printf("disklabel_sun_to_bsd: success!\n");
! 321: #endif
! 322: return (NULL);
! 323: }
! 324:
! 325: /*
! 326: * Find a valid disklabel.
! 327: */
! 328: static char *
! 329: search_label(devp, off, buf, lp, off0)
! 330: struct of_dev *devp;
! 331: u_long off;
! 332: char *buf;
! 333: struct disklabel *lp;
! 334: u_long off0;
! 335: {
! 336: size_t read;
! 337: struct mbr_partition *p;
! 338: int i;
! 339: u_long poff;
! 340: static int recursion;
! 341:
! 342: struct disklabel *dlp;
! 343: struct sun_disklabel *slp;
! 344: int error;
! 345:
! 346: /* minimal requirements for archetypal disk label */
! 347: if (lp->d_secperunit == 0)
! 348: lp->d_secperunit = 0x1fffffff;
! 349: lp->d_npartitions = 1;
! 350: if (lp->d_partitions[0].p_size == 0)
! 351: lp->d_partitions[0].p_size = 0x1fffffff;
! 352: lp->d_partitions[0].p_offset = 0;
! 353:
! 354: if (strategy(devp, F_READ, LABELSECTOR, DEV_BSIZE, buf, &read)
! 355: || read != DEV_BSIZE)
! 356: return ("Cannot read label");
! 357: /* Check for a NetBSD disk label. */
! 358: dlp = (struct disklabel *) (buf + LABELOFFSET);
! 359: if (dlp->d_magic == DISKMAGIC) {
! 360: if (dkcksum(dlp))
! 361: return ("NetBSD disk label corrupted");
! 362: *lp = *dlp;
! 363: #ifdef NOTDEF_DEBUG
! 364: printf("search_label: found NetBSD label\n");
! 365: #endif
! 366: return (NULL);
! 367: }
! 368:
! 369: /* Check for a Sun disk label (for PROM compatibility). */
! 370: slp = (struct sun_disklabel *) buf;
! 371: if (slp->sl_magic == SUN_DKMAGIC)
! 372: return (disklabel_sun_to_bsd(buf, lp));
! 373:
! 374:
! 375: bzero(buf, sizeof(buf));
! 376: return ("no disk label");
! 377: }
! 378:
! 379: int
! 380: devopen(of, name, file)
! 381: struct open_file *of;
! 382: const char *name;
! 383: char **file;
! 384: {
! 385: char *cp;
! 386: char partition;
! 387: char fname[256];
! 388: char buf[DEV_BSIZE];
! 389: struct disklabel label;
! 390: int handle, part;
! 391: size_t read;
! 392: char *errmsg = NULL;
! 393: int error = 0;
! 394:
! 395: if (ofdev.handle != -1)
! 396: panic("devopen");
! 397: if (of->f_flags != F_READ)
! 398: return EPERM;
! 399: #ifdef NOTDEF_DEBUG
! 400: printf("devopen: you want %s\n", name);
! 401: #endif
! 402: strlcpy(fname, name, sizeof fname);
! 403: cp = filename(fname, &partition);
! 404: if (cp) {
! 405: strlcpy(buf, cp, sizeof buf);
! 406: *cp = 0;
! 407: }
! 408: if (!cp || !*buf)
! 409: strlcpy(buf, DEFAULT_KERNEL, sizeof buf);
! 410: if (!*fname)
! 411: strlcpy(fname, bootdev, sizeof fname);
! 412: strlcpy(opened_name, fname, sizeof opened_name);
! 413: if (partition) {
! 414: cp = opened_name + strlen(opened_name);
! 415: *cp++ = ':';
! 416: *cp++ = partition;
! 417: *cp = 0;
! 418: }
! 419: if (*buf != '/')
! 420: strlcat(opened_name, "/", sizeof opened_name);
! 421: strlcat(opened_name, buf, sizeof opened_name);
! 422: *file = opened_name + strlen(fname) + 1;
! 423: #ifdef NOTDEF_DEBUG
! 424: printf("devopen: trying %s\n", fname);
! 425: #endif
! 426: if ((handle = OF_finddevice(fname)) == -1)
! 427: return ENOENT;
! 428: #ifdef NOTDEF_DEBUG
! 429: printf("devopen: found %s\n", fname);
! 430: #endif
! 431: if (OF_getprop(handle, "name", buf, sizeof buf) < 0)
! 432: return ENXIO;
! 433: #ifdef NOTDEF_DEBUG
! 434: printf("devopen: %s is called %s\n", fname, buf);
! 435: #endif
! 436: if (OF_getprop(handle, "device_type", buf, sizeof buf) < 0)
! 437: return ENXIO;
! 438: #ifdef NOTDEF_DEBUG
! 439: printf("devopen: %s is a %s device\n", fname, buf);
! 440: #endif
! 441: #ifdef NOTDEF_DEBUG
! 442: printf("devopen: opening %s\n", fname);
! 443: #endif
! 444: if ((handle = OF_open(fname)) == -1) {
! 445: #ifdef NOTDEF_DEBUG
! 446: printf("devopen: open of %s failed\n", fname);
! 447: #endif
! 448: return ENXIO;
! 449: }
! 450: #ifdef NOTDEF_DEBUG
! 451: printf("devopen: %s is now open\n", fname);
! 452: #endif
! 453: bzero(&ofdev, sizeof ofdev);
! 454: ofdev.handle = handle;
! 455: if (!strcmp(buf, "block")) {
! 456: ofdev.type = OFDEV_DISK;
! 457: ofdev.bsize = DEV_BSIZE;
! 458: /* First try to find a disklabel without MBR partitions */
! 459: #ifdef NOTDEF_DEBUG
! 460: printf("devopen: trying to read disklabel\n");
! 461: #endif
! 462: if (strategy(&ofdev, F_READ,
! 463: LABELSECTOR, DEV_BSIZE, buf, &read) != 0
! 464: || read != DEV_BSIZE
! 465: || (errmsg = getdisklabel(buf, &label))) {
! 466: #ifdef NOTDEF_DEBUG
! 467: if (errmsg) printf("devopen: getdisklabel says %s\n", errmsg);
! 468: #endif
! 469: /* Else try MBR partitions */
! 470: errmsg = search_label(&ofdev, 0, buf, &label, 0);
! 471: if (errmsg) {
! 472: printf("devopen: search_label says %s\n", errmsg);
! 473: error = ERDLAB;
! 474: }
! 475: if (error && error != ERDLAB)
! 476: goto bad;
! 477: }
! 478:
! 479: if (error == ERDLAB) {
! 480: if (partition)
! 481: /* User specified a parititon, but there is none */
! 482: goto bad;
! 483: /* No, label, just use complete disk */
! 484: ofdev.partoff = 0;
! 485: } else {
! 486: part = partition ? partition - 'a' : 0;
! 487: ofdev.partoff = label.d_partitions[part].p_offset;
! 488: #ifdef NOTDEF_DEBUG
! 489: printf("devopen: setting partition %d offset %x\n",
! 490: part, ofdev.partoff);
! 491: #endif
! 492: }
! 493:
! 494: of->f_dev = devsw;
! 495: of->f_devdata = &ofdev;
! 496: #ifdef SPARC_BOOT_UFS
! 497: bcopy(&file_system_ufs, &file_system[nfsys++], sizeof file_system[0]);
! 498: #endif
! 499: #ifdef SPARC_BOOT_HSFS
! 500: bcopy(&file_system_cd9660, &file_system[nfsys++],
! 501: sizeof file_system[0]);
! 502: #endif
! 503: #ifdef NOTDEF_DEBUG
! 504: printf("devopen: return 0\n");
! 505: #endif
! 506: return 0;
! 507: }
! 508: #ifdef NETBOOT
! 509: if (!strcmp(buf, "network")) {
! 510: ofdev.type = OFDEV_NET;
! 511: of->f_dev = devsw;
! 512: of->f_devdata = &ofdev;
! 513: bcopy(&file_system_nfs, file_system, sizeof file_system[0]);
! 514: nfsys = 1;
! 515: if (error = net_open(&ofdev))
! 516: goto bad;
! 517: return 0;
! 518: }
! 519: #endif
! 520: error = EFTYPE;
! 521: bad:
! 522: #ifdef NOTDEF_DEBUG
! 523: printf("devopen: error %d, cannot open device\n", error);
! 524: #endif
! 525: OF_close(handle);
! 526: ofdev.handle = -1;
! 527: return error;
! 528: }
CVSweb