Annotation of sys/kern/subr_disk.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: subr_disk.c,v 1.64 2007/08/05 04:26:21 krw Exp $ */
! 2: /* $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995 Jason R. Thorpe. All rights reserved.
! 6: * Copyright (c) 1982, 1986, 1988, 1993
! 7: * The Regents of the University of California. All rights reserved.
! 8: * (c) UNIX System Laboratories, Inc.
! 9: * All or some portions of this file are derived from material licensed
! 10: * to the University of California by American Telephone and Telegraph
! 11: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
! 12: * the permission of UNIX System Laboratories, Inc.
! 13: *
! 14: * Redistribution and use in source and binary forms, with or without
! 15: * modification, are permitted provided that the following conditions
! 16: * are met:
! 17: * 1. Redistributions of source code must retain the above copyright
! 18: * notice, this list of conditions and the following disclaimer.
! 19: * 2. Redistributions in binary form must reproduce the above copyright
! 20: * notice, this list of conditions and the following disclaimer in the
! 21: * documentation and/or other materials provided with the distribution.
! 22: * 3. Neither the name of the University nor the names of its contributors
! 23: * may be used to endorse or promote products derived from this software
! 24: * without specific prior written permission.
! 25: *
! 26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 36: * SUCH DAMAGE.
! 37: *
! 38: * @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
! 39: */
! 40:
! 41: #include <sys/param.h>
! 42: #include <sys/systm.h>
! 43: #include <sys/kernel.h>
! 44: #include <sys/malloc.h>
! 45: #include <sys/fcntl.h>
! 46: #include <sys/buf.h>
! 47: #include <sys/stat.h>
! 48: #include <sys/syslog.h>
! 49: #include <sys/device.h>
! 50: #include <sys/time.h>
! 51: #include <sys/disklabel.h>
! 52: #include <sys/conf.h>
! 53: #include <sys/lock.h>
! 54: #include <sys/disk.h>
! 55: #include <sys/reboot.h>
! 56: #include <sys/dkio.h>
! 57: #include <sys/dkstat.h> /* XXX */
! 58: #include <sys/proc.h>
! 59: #include <uvm/uvm_extern.h>
! 60:
! 61: #include <dev/rndvar.h>
! 62: #include <dev/cons.h>
! 63:
! 64: /*
! 65: * A global list of all disks attached to the system. May grow or
! 66: * shrink over time.
! 67: */
! 68: struct disklist_head disklist; /* TAILQ_HEAD */
! 69: int disk_count; /* number of drives in global disklist */
! 70: int disk_change; /* set if a disk has been attached/detached
! 71: * since last we looked at this variable. This
! 72: * is reset by hw_sysctl()
! 73: */
! 74:
! 75: /*
! 76: * Seek sort for disks. We depend on the driver which calls us using b_resid
! 77: * as the current cylinder number.
! 78: *
! 79: * The argument ap structure holds a b_actf activity chain pointer on which we
! 80: * keep two queues, sorted in ascending cylinder order. The first queue holds
! 81: * those requests which are positioned after the current cylinder (in the first
! 82: * request); the second holds requests which came in after their cylinder number
! 83: * was passed. Thus we implement a one way scan, retracting after reaching the
! 84: * end of the drive to the first request on the second queue, at which time it
! 85: * becomes the first queue.
! 86: *
! 87: * A one-way scan is natural because of the way UNIX read-ahead blocks are
! 88: * allocated.
! 89: */
! 90:
! 91: void
! 92: disksort(struct buf *ap, struct buf *bp)
! 93: {
! 94: struct buf *bq;
! 95:
! 96: /* If the queue is empty, then it's easy. */
! 97: if (ap->b_actf == NULL) {
! 98: bp->b_actf = NULL;
! 99: ap->b_actf = bp;
! 100: return;
! 101: }
! 102:
! 103: /*
! 104: * If we lie after the first (currently active) request, then we
! 105: * must locate the second request list and add ourselves to it.
! 106: */
! 107: bq = ap->b_actf;
! 108: if (bp->b_cylinder < bq->b_cylinder) {
! 109: while (bq->b_actf) {
! 110: /*
! 111: * Check for an ``inversion'' in the normally ascending
! 112: * cylinder numbers, indicating the start of the second
! 113: * request list.
! 114: */
! 115: if (bq->b_actf->b_cylinder < bq->b_cylinder) {
! 116: /*
! 117: * Search the second request list for the first
! 118: * request at a larger cylinder number. We go
! 119: * before that; if there is no such request, we
! 120: * go at end.
! 121: */
! 122: do {
! 123: if (bp->b_cylinder <
! 124: bq->b_actf->b_cylinder)
! 125: goto insert;
! 126: if (bp->b_cylinder ==
! 127: bq->b_actf->b_cylinder &&
! 128: bp->b_blkno < bq->b_actf->b_blkno)
! 129: goto insert;
! 130: bq = bq->b_actf;
! 131: } while (bq->b_actf);
! 132: goto insert; /* after last */
! 133: }
! 134: bq = bq->b_actf;
! 135: }
! 136: /*
! 137: * No inversions... we will go after the last, and
! 138: * be the first request in the second request list.
! 139: */
! 140: goto insert;
! 141: }
! 142: /*
! 143: * Request is at/after the current request...
! 144: * sort in the first request list.
! 145: */
! 146: while (bq->b_actf) {
! 147: /*
! 148: * We want to go after the current request if there is an
! 149: * inversion after it (i.e. it is the end of the first
! 150: * request list), or if the next request is a larger cylinder
! 151: * than our request.
! 152: */
! 153: if (bq->b_actf->b_cylinder < bq->b_cylinder ||
! 154: bp->b_cylinder < bq->b_actf->b_cylinder ||
! 155: (bp->b_cylinder == bq->b_actf->b_cylinder &&
! 156: bp->b_blkno < bq->b_actf->b_blkno))
! 157: goto insert;
! 158: bq = bq->b_actf;
! 159: }
! 160: /*
! 161: * Neither a second list nor a larger request... we go at the end of
! 162: * the first list, which is the same as the end of the whole schebang.
! 163: */
! 164: insert: bp->b_actf = bq->b_actf;
! 165: bq->b_actf = bp;
! 166: }
! 167:
! 168: /*
! 169: * Compute checksum for disk label.
! 170: */
! 171: u_int
! 172: dkcksum(struct disklabel *lp)
! 173: {
! 174: u_int16_t *start, *end;
! 175: u_int16_t sum = 0;
! 176:
! 177: start = (u_int16_t *)lp;
! 178: end = (u_int16_t *)&lp->d_partitions[lp->d_npartitions];
! 179: while (start < end)
! 180: sum ^= *start++;
! 181: return (sum);
! 182: }
! 183:
! 184: char *
! 185: initdisklabel(struct disklabel *lp)
! 186: {
! 187: int i;
! 188:
! 189: /* minimal requirements for archetypal disk label */
! 190: if (lp->d_secsize < DEV_BSIZE)
! 191: lp->d_secsize = DEV_BSIZE;
! 192: if (DL_GETDSIZE(lp) == 0)
! 193: DL_SETDSIZE(lp, MAXDISKSIZE);
! 194: if (lp->d_secpercyl == 0)
! 195: return ("invalid geometry");
! 196: lp->d_npartitions = RAW_PART + 1;
! 197: for (i = 0; i < RAW_PART; i++) {
! 198: DL_SETPSIZE(&lp->d_partitions[i], 0);
! 199: DL_SETPOFFSET(&lp->d_partitions[i], 0);
! 200: }
! 201: if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) == 0)
! 202: DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
! 203: DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
! 204: lp->d_version = 1;
! 205: lp->d_bbsize = 8192;
! 206: lp->d_sbsize = 64*1024; /* XXX ? */
! 207: return (NULL);
! 208: }
! 209:
! 210: /*
! 211: * Check an incoming block to make sure it is a disklabel, convert it to
! 212: * a newer version if needed, etc etc.
! 213: */
! 214: char *
! 215: checkdisklabel(void *rlp, struct disklabel *lp)
! 216: {
! 217: struct disklabel *dlp = rlp;
! 218: struct __partitionv0 *v0pp;
! 219: struct partition *pp;
! 220: daddr64_t disksize;
! 221: char *msg = NULL;
! 222: int i;
! 223:
! 224: if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC)
! 225: msg = "no disk label";
! 226: else if (dlp->d_npartitions > MAXPARTITIONS)
! 227: msg = "unreasonable partition count";
! 228: else if (dkcksum(dlp) != 0)
! 229: msg = "disk label corrupted";
! 230:
! 231: if (msg) {
! 232: u_int16_t *start, *end, sum = 0;
! 233:
! 234: /* If it is byte-swapped, attempt to convert it */
! 235: if (swap32(dlp->d_magic) != DISKMAGIC ||
! 236: swap32(dlp->d_magic2) != DISKMAGIC ||
! 237: swap16(dlp->d_npartitions) > MAXPARTITIONS)
! 238: return (msg);
! 239:
! 240: /*
! 241: * Need a byte-swap aware dkcksum varient
! 242: * inlined, because dkcksum uses a sub-field
! 243: */
! 244: start = (u_int16_t *)dlp;
! 245: end = (u_int16_t *)&dlp->d_partitions[
! 246: swap16(dlp->d_npartitions)];
! 247: while (start < end)
! 248: sum ^= *start++;
! 249: if (sum != 0)
! 250: return (msg);
! 251:
! 252: dlp->d_magic = swap32(dlp->d_magic);
! 253: dlp->d_type = swap16(dlp->d_type);
! 254: dlp->d_subtype = swap16(dlp->d_subtype);
! 255:
! 256: /* d_typename and d_packname are strings */
! 257:
! 258: dlp->d_secsize = swap32(dlp->d_secsize);
! 259: dlp->d_nsectors = swap32(dlp->d_nsectors);
! 260: dlp->d_ntracks = swap32(dlp->d_ntracks);
! 261: dlp->d_ncylinders = swap32(dlp->d_ncylinders);
! 262: dlp->d_secpercyl = swap32(dlp->d_secpercyl);
! 263: dlp->d_secperunit = swap32(dlp->d_secperunit);
! 264:
! 265: dlp->d_sparespertrack = swap16(dlp->d_sparespertrack);
! 266: dlp->d_sparespercyl = swap16(dlp->d_sparespercyl);
! 267:
! 268: dlp->d_acylinders = swap32(dlp->d_acylinders);
! 269:
! 270: dlp->d_rpm = swap16(dlp->d_rpm);
! 271: dlp->d_interleave = swap16(dlp->d_interleave);
! 272: dlp->d_trackskew = swap16(dlp->d_trackskew);
! 273: dlp->d_cylskew = swap16(dlp->d_cylskew);
! 274: dlp->d_headswitch = swap32(dlp->d_headswitch);
! 275: dlp->d_trkseek = swap32(dlp->d_trkseek);
! 276: dlp->d_flags = swap32(dlp->d_flags);
! 277:
! 278: for (i = 0; i < NDDATA; i++)
! 279: dlp->d_drivedata[i] = swap32(dlp->d_drivedata[i]);
! 280:
! 281: dlp->d_secperunith = swap16(dlp->d_secperunith);
! 282: dlp->d_version = swap16(dlp->d_version);
! 283:
! 284: for (i = 0; i < NSPARE; i++)
! 285: dlp->d_spare[i] = swap32(dlp->d_spare[i]);
! 286:
! 287: dlp->d_magic2 = swap32(dlp->d_magic2);
! 288: dlp->d_checksum = swap16(dlp->d_checksum);
! 289:
! 290: dlp->d_npartitions = swap16(dlp->d_npartitions);
! 291: dlp->d_bbsize = swap32(dlp->d_bbsize);
! 292: dlp->d_sbsize = swap32(dlp->d_sbsize);
! 293:
! 294: for (i = 0; i < MAXPARTITIONS; i++) {
! 295: pp = &dlp->d_partitions[i];
! 296: pp->p_size = swap32(pp->p_size);
! 297: pp->p_offset = swap32(pp->p_offset);
! 298: if (dlp->d_version == 0) {
! 299: v0pp = (struct __partitionv0 *)pp;
! 300: v0pp->p_fsize = swap32(v0pp->p_fsize);
! 301: } else {
! 302: pp->p_offseth = swap16(pp->p_offseth);
! 303: pp->p_sizeh = swap16(pp->p_sizeh);
! 304: }
! 305: pp->p_cpg = swap16(pp->p_cpg);
! 306: }
! 307:
! 308: dlp->d_checksum = 0;
! 309: dlp->d_checksum = dkcksum(dlp);
! 310: msg = NULL;
! 311: }
! 312:
! 313: /* XXX should verify lots of other fields and whine a lot */
! 314:
! 315: if (msg)
! 316: return (msg);
! 317:
! 318: /* Initial passed in lp contains the real disk size. */
! 319: disksize = DL_GETDSIZE(lp);
! 320:
! 321: if (lp != dlp)
! 322: *lp = *dlp;
! 323:
! 324: if (lp->d_version == 0) {
! 325: lp->d_version = 1;
! 326: lp->d_secperunith = 0;
! 327:
! 328: v0pp = (struct __partitionv0 *)lp->d_partitions;
! 329: pp = lp->d_partitions;
! 330: for (i = 0; i < lp->d_npartitions; i++, pp++, v0pp++) {
! 331: pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(v0pp->
! 332: p_fsize, v0pp->p_frag);
! 333: pp->p_offseth = 0;
! 334: pp->p_sizeh = 0;
! 335: }
! 336: }
! 337:
! 338: #ifdef DEBUG
! 339: if (DL_GETDSIZE(lp) != disksize)
! 340: printf("on-disk disklabel has incorrect disksize (%lld)\n",
! 341: DL_GETDSIZE(lp));
! 342: if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) != disksize)
! 343: printf("on-disk disklabel RAW_PART has incorrect size (%lld)\n",
! 344: DL_GETPSIZE(&lp->d_partitions[RAW_PART]));
! 345: if (DL_GETPOFFSET(&lp->d_partitions[RAW_PART]) != 0)
! 346: printf("on-disk disklabel RAW_PART offset != 0 (%lld)\n",
! 347: DL_GETPOFFSET(&lp->d_partitions[RAW_PART]));
! 348: #endif
! 349: DL_SETDSIZE(lp, disksize);
! 350: DL_SETPSIZE(&lp->d_partitions[RAW_PART], disksize);
! 351: DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
! 352:
! 353: lp->d_checksum = 0;
! 354: lp->d_checksum = dkcksum(lp);
! 355: return (msg);
! 356: }
! 357:
! 358: /*
! 359: * If dos partition table requested, attempt to load it and
! 360: * find disklabel inside a DOS partition. Return buffer
! 361: * for use in signalling errors if requested.
! 362: *
! 363: * We would like to check if each MBR has a valid BOOT_MAGIC, but
! 364: * we cannot because it doesn't always exist. So.. we assume the
! 365: * MBR is valid.
! 366: */
! 367: char *
! 368: readdoslabel(struct buf *bp, void (*strat)(struct buf *),
! 369: struct disklabel *lp, int *partoffp, int spoofonly)
! 370: {
! 371: struct dos_partition dp[NDOSPART], *dp2;
! 372: u_int32_t extoff = 0;
! 373: daddr64_t part_blkno = DOSBBSECTOR;
! 374: int dospartoff = 0, i, ourpart = -1;
! 375: int wander = 1, n = 0, loop = 0;
! 376:
! 377: if (lp->d_secpercyl == 0)
! 378: return ("invalid label, d_secpercyl == 0");
! 379: if (lp->d_secsize == 0)
! 380: return ("invalid label, d_secsize == 0");
! 381:
! 382: /* do DOS partitions in the process of getting disklabel? */
! 383:
! 384: /*
! 385: * Read dos partition table, follow extended partitions.
! 386: * Map the partitions to disklabel entries i-p
! 387: */
! 388: while (wander && n < 8 && loop < 8) {
! 389: loop++;
! 390: wander = 0;
! 391: if (part_blkno < extoff)
! 392: part_blkno = extoff;
! 393:
! 394: /* read boot record */
! 395: bp->b_blkno = part_blkno;
! 396: bp->b_bcount = lp->d_secsize;
! 397: bp->b_flags = B_BUSY | B_READ;
! 398: (*strat)(bp);
! 399: if (biowait(bp)) {
! 400: /*wrong*/ if (partoffp)
! 401: /*wrong*/ *partoffp = -1;
! 402: return ("dos partition I/O error");
! 403: }
! 404:
! 405: bcopy(bp->b_data + DOSPARTOFF, dp, sizeof(dp));
! 406:
! 407: if (ourpart == -1 && part_blkno == DOSBBSECTOR) {
! 408: /* Search for our MBR partition */
! 409: for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
! 410: i++, dp2++)
! 411: if (letoh32(dp2->dp_size) &&
! 412: dp2->dp_typ == DOSPTYP_OPENBSD)
! 413: ourpart = i;
! 414: if (ourpart == -1)
! 415: goto donot;
! 416: /*
! 417: * This is our MBR partition. need sector
! 418: * address for SCSI/IDE, cylinder for
! 419: * ESDI/ST506/RLL
! 420: */
! 421: dp2 = &dp[ourpart];
! 422: dospartoff = letoh32(dp2->dp_start) + part_blkno;
! 423:
! 424: /* found our OpenBSD partition, finish up */
! 425: if (partoffp)
! 426: goto notfat;
! 427:
! 428: if (lp->d_ntracks == 0)
! 429: lp->d_ntracks = dp2->dp_ehd + 1;
! 430: if (lp->d_nsectors == 0)
! 431: lp->d_nsectors = DPSECT(dp2->dp_esect);
! 432: if (lp->d_secpercyl == 0)
! 433: lp->d_secpercyl = lp->d_ntracks *
! 434: lp->d_nsectors;
! 435: }
! 436: donot:
! 437: /*
! 438: * In case the disklabel read below fails, we want to
! 439: * provide a fake label in i-p.
! 440: */
! 441: for (dp2=dp, i=0; i < NDOSPART && n < 8; i++, dp2++) {
! 442: struct partition *pp = &lp->d_partitions[8+n];
! 443:
! 444: if (dp2->dp_typ == DOSPTYP_OPENBSD)
! 445: continue;
! 446: if (letoh32(dp2->dp_size) > DL_GETDSIZE(lp))
! 447: continue;
! 448: if (letoh32(dp2->dp_start) > DL_GETDSIZE(lp))
! 449: continue;
! 450: if (letoh32(dp2->dp_size) == 0)
! 451: continue;
! 452: if (letoh32(dp2->dp_start))
! 453: DL_SETPOFFSET(pp,
! 454: letoh32(dp2->dp_start) + part_blkno);
! 455:
! 456: DL_SETPSIZE(pp, letoh32(dp2->dp_size));
! 457:
! 458: switch (dp2->dp_typ) {
! 459: case DOSPTYP_UNUSED:
! 460: pp->p_fstype = FS_UNUSED;
! 461: n++;
! 462: break;
! 463:
! 464: case DOSPTYP_LINUX:
! 465: pp->p_fstype = FS_EXT2FS;
! 466: n++;
! 467: break;
! 468:
! 469: case DOSPTYP_FAT12:
! 470: case DOSPTYP_FAT16S:
! 471: case DOSPTYP_FAT16B:
! 472: case DOSPTYP_FAT16L:
! 473: case DOSPTYP_FAT32:
! 474: case DOSPTYP_FAT32L:
! 475: pp->p_fstype = FS_MSDOS;
! 476: n++;
! 477: break;
! 478: case DOSPTYP_EXTEND:
! 479: case DOSPTYP_EXTENDL:
! 480: part_blkno = letoh32(dp2->dp_start) + extoff;
! 481: if (!extoff) {
! 482: extoff = letoh32(dp2->dp_start);
! 483: part_blkno = 0;
! 484: }
! 485: wander = 1;
! 486: break;
! 487: default:
! 488: pp->p_fstype = FS_OTHER;
! 489: n++;
! 490: break;
! 491: }
! 492: }
! 493: }
! 494: lp->d_npartitions = MAXPARTITIONS;
! 495:
! 496: if (n == 0 && part_blkno == DOSBBSECTOR) {
! 497: u_int16_t fattest;
! 498:
! 499: /* Check for a short jump instruction. */
! 500: fattest = ((bp->b_data[0] << 8) & 0xff00) |
! 501: (bp->b_data[2] & 0xff);
! 502: if (fattest != 0xeb90 && fattest != 0xe900)
! 503: goto notfat;
! 504:
! 505: /* Check for a valid bytes per sector value. */
! 506: fattest = ((bp->b_data[12] << 8) & 0xff00) |
! 507: (bp->b_data[11] & 0xff);
! 508: if (fattest < 512 || fattest > 4096 || (fattest % 512 != 0))
! 509: goto notfat;
! 510:
! 511: /* Check the end of sector marker. */
! 512: fattest = ((bp->b_data[510] << 8) & 0xff00) |
! 513: (bp->b_data[511] & 0xff);
! 514: if (fattest != 0x55aa)
! 515: goto notfat;
! 516:
! 517: /* Looks like a FAT filesystem. Spoof 'i'. */
! 518: DL_SETPSIZE(&lp->d_partitions['i' - 'a'],
! 519: DL_GETPSIZE(&lp->d_partitions[RAW_PART]));
! 520: DL_SETPOFFSET(&lp->d_partitions['i' - 'a'], 0);
! 521: lp->d_partitions['i' - 'a'].p_fstype = FS_MSDOS;
! 522: }
! 523: notfat:
! 524:
! 525: /* record the OpenBSD partition's placement for the caller */
! 526: if (partoffp)
! 527: *partoffp = dospartoff;
! 528:
! 529: /* don't read the on-disk label if we are in spoofed-only mode */
! 530: if (spoofonly)
! 531: return (NULL);
! 532:
! 533: bp->b_blkno = dospartoff + DOS_LABELSECTOR;
! 534: bp->b_bcount = lp->d_secsize;
! 535: bp->b_flags = B_BUSY | B_READ;
! 536: (*strat)(bp);
! 537: if (biowait(bp))
! 538: return ("disk label I/O error");
! 539:
! 540: /* sub-MBR disklabels are always at a LABELOFFSET of 0 */
! 541: return checkdisklabel(bp->b_data, lp);
! 542: }
! 543:
! 544: /*
! 545: * Check new disk label for sensibility
! 546: * before setting it.
! 547: */
! 548: int
! 549: setdisklabel(struct disklabel *olp, struct disklabel *nlp, u_int openmask)
! 550: {
! 551: int i;
! 552: struct partition *opp, *npp;
! 553:
! 554: /* sanity clause */
! 555: if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 ||
! 556: (nlp->d_secsize % DEV_BSIZE) != 0)
! 557: return (EINVAL);
! 558:
! 559: /* special case to allow disklabel to be invalidated */
! 560: if (nlp->d_magic == 0xffffffff) {
! 561: *olp = *nlp;
! 562: return (0);
! 563: }
! 564:
! 565: if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
! 566: dkcksum(nlp) != 0)
! 567: return (EINVAL);
! 568:
! 569: /* XXX missing check if other dos partitions will be overwritten */
! 570:
! 571: while (openmask != 0) {
! 572: i = ffs(openmask) - 1;
! 573: openmask &= ~(1 << i);
! 574: if (nlp->d_npartitions <= i)
! 575: return (EBUSY);
! 576: opp = &olp->d_partitions[i];
! 577: npp = &nlp->d_partitions[i];
! 578: if (DL_GETPOFFSET(npp) != DL_GETPOFFSET(opp) ||
! 579: DL_GETPSIZE(npp) < DL_GETPSIZE(opp))
! 580: return (EBUSY);
! 581: /*
! 582: * Copy internally-set partition information
! 583: * if new label doesn't include it. XXX
! 584: */
! 585: if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
! 586: npp->p_fstype = opp->p_fstype;
! 587: npp->p_fragblock = opp->p_fragblock;
! 588: npp->p_cpg = opp->p_cpg;
! 589: }
! 590: }
! 591: nlp->d_checksum = 0;
! 592: nlp->d_checksum = dkcksum(nlp);
! 593: *olp = *nlp;
! 594: return (0);
! 595: }
! 596:
! 597: /*
! 598: * Determine the size of the transfer, and make sure it is within the
! 599: * boundaries of the partition. Adjust transfer if needed, and signal errors or
! 600: * early completion.
! 601: */
! 602: int
! 603: bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel)
! 604: {
! 605: #define blockpersec(count, lp) ((count) * (((lp)->d_secsize) / DEV_BSIZE))
! 606: struct partition *p = &lp->d_partitions[DISKPART(bp->b_dev)];
! 607: daddr64_t sz = howmany(bp->b_bcount, DEV_BSIZE);
! 608:
! 609: /* avoid division by zero */
! 610: if (lp->d_secpercyl == 0)
! 611: goto bad;
! 612:
! 613: /* beyond partition? */
! 614: if (bp->b_blkno + sz > blockpersec(DL_GETPSIZE(p), lp)) {
! 615: sz = blockpersec(DL_GETPSIZE(p), lp) - bp->b_blkno;
! 616: if (sz == 0) {
! 617: /* If exactly at end of disk, return EOF. */
! 618: bp->b_resid = bp->b_bcount;
! 619: return (-1);
! 620: }
! 621: if (sz < 0)
! 622: /* If past end of disk, return EINVAL. */
! 623: goto bad;
! 624:
! 625: /* Otherwise, truncate request. */
! 626: bp->b_bcount = sz << DEV_BSHIFT;
! 627: }
! 628:
! 629: /* calculate cylinder for disksort to order transfers with */
! 630: bp->b_cylinder = (bp->b_blkno + blockpersec(DL_GETPOFFSET(p), lp)) /
! 631: blockpersec(lp->d_secpercyl, lp);
! 632: return (1);
! 633:
! 634: bad:
! 635: bp->b_error = EINVAL;
! 636: bp->b_flags |= B_ERROR;
! 637: return (-1);
! 638: }
! 639:
! 640: /*
! 641: * Disk error is the preface to plaintive error messages
! 642: * about failing disk transfers. It prints messages of the form
! 643:
! 644: hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d)
! 645:
! 646: * if the offset of the error in the transfer and a disk label
! 647: * are both available. blkdone should be -1 if the position of the error
! 648: * is unknown; the disklabel pointer may be null from drivers that have not
! 649: * been converted to use them. The message is printed with printf
! 650: * if pri is LOG_PRINTF, otherwise it uses log at the specified priority.
! 651: * The message should be completed (with at least a newline) with printf
! 652: * or addlog, respectively. There is no trailing space.
! 653: */
! 654: void
! 655: diskerr(struct buf *bp, char *dname, char *what, int pri, int blkdone,
! 656: struct disklabel *lp)
! 657: {
! 658: int unit = DISKUNIT(bp->b_dev), part = DISKPART(bp->b_dev);
! 659: int (*pr)(const char *, ...);
! 660: char partname = 'a' + part;
! 661: daddr64_t sn;
! 662:
! 663: if (pri != LOG_PRINTF) {
! 664: static const char fmt[] = "";
! 665: log(pri, fmt);
! 666: pr = addlog;
! 667: } else
! 668: pr = printf;
! 669: (*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what,
! 670: bp->b_flags & B_READ ? "read" : "writ");
! 671: sn = bp->b_blkno;
! 672: if (bp->b_bcount <= DEV_BSIZE)
! 673: (*pr)("%lld", sn);
! 674: else {
! 675: if (blkdone >= 0) {
! 676: sn += blkdone;
! 677: (*pr)("%lld of ", sn);
! 678: }
! 679: (*pr)("%lld-%lld", bp->b_blkno,
! 680: bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE);
! 681: }
! 682: if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) {
! 683: sn += DL_GETPOFFSET(&lp->d_partitions[part]);
! 684: (*pr)(" (%s%d bn %lld; cn %lld", dname, unit, sn,
! 685: sn / lp->d_secpercyl);
! 686: sn %= lp->d_secpercyl;
! 687: (*pr)(" tn %lld sn %lld)", sn / lp->d_nsectors,
! 688: sn % lp->d_nsectors);
! 689: }
! 690: }
! 691:
! 692: /*
! 693: * Initialize the disklist. Called by main() before autoconfiguration.
! 694: */
! 695: void
! 696: disk_init(void)
! 697: {
! 698:
! 699: TAILQ_INIT(&disklist);
! 700: disk_count = disk_change = 0;
! 701: }
! 702:
! 703: int
! 704: disk_construct(struct disk *diskp, char *lockname)
! 705: {
! 706: rw_init(&diskp->dk_lock, lockname);
! 707:
! 708: diskp->dk_flags |= DKF_CONSTRUCTED;
! 709:
! 710: return (0);
! 711: }
! 712:
! 713: /*
! 714: * Attach a disk.
! 715: */
! 716: void
! 717: disk_attach(struct disk *diskp)
! 718: {
! 719:
! 720: if (!ISSET(diskp->dk_flags, DKF_CONSTRUCTED))
! 721: disk_construct(diskp, diskp->dk_name);
! 722:
! 723: /*
! 724: * Allocate and initialize the disklabel structures. Note that
! 725: * it's not safe to sleep here, since we're probably going to be
! 726: * called during autoconfiguration.
! 727: */
! 728: diskp->dk_label = malloc(sizeof(struct disklabel), M_DEVBUF, M_NOWAIT);
! 729: if (diskp->dk_label == NULL)
! 730: panic("disk_attach: can't allocate storage for disklabel");
! 731:
! 732: bzero(diskp->dk_label, sizeof(struct disklabel));
! 733:
! 734: /*
! 735: * Set the attached timestamp.
! 736: */
! 737: microuptime(&diskp->dk_attachtime);
! 738:
! 739: /*
! 740: * Link into the disklist.
! 741: */
! 742: TAILQ_INSERT_TAIL(&disklist, diskp, dk_link);
! 743: ++disk_count;
! 744: disk_change = 1;
! 745: }
! 746:
! 747: /*
! 748: * Detach a disk.
! 749: */
! 750: void
! 751: disk_detach(struct disk *diskp)
! 752: {
! 753:
! 754: /*
! 755: * Free the space used by the disklabel structures.
! 756: */
! 757: free(diskp->dk_label, M_DEVBUF);
! 758:
! 759: /*
! 760: * Remove from the disklist.
! 761: */
! 762: TAILQ_REMOVE(&disklist, diskp, dk_link);
! 763: disk_change = 1;
! 764: if (--disk_count < 0)
! 765: panic("disk_detach: disk_count < 0");
! 766: }
! 767:
! 768: /*
! 769: * Increment a disk's busy counter. If the counter is going from
! 770: * 0 to 1, set the timestamp.
! 771: */
! 772: void
! 773: disk_busy(struct disk *diskp)
! 774: {
! 775:
! 776: /*
! 777: * XXX We'd like to use something as accurate as microtime(),
! 778: * but that doesn't depend on the system TOD clock.
! 779: */
! 780: if (diskp->dk_busy++ == 0) {
! 781: microuptime(&diskp->dk_timestamp);
! 782: }
! 783: }
! 784:
! 785: /*
! 786: * Decrement a disk's busy counter, increment the byte count, total busy
! 787: * time, and reset the timestamp.
! 788: */
! 789: void
! 790: disk_unbusy(struct disk *diskp, long bcount, int read)
! 791: {
! 792: struct timeval dv_time, diff_time;
! 793:
! 794: if (diskp->dk_busy-- == 0)
! 795: printf("disk_unbusy: %s: dk_busy < 0\n", diskp->dk_name);
! 796:
! 797: microuptime(&dv_time);
! 798:
! 799: timersub(&dv_time, &diskp->dk_timestamp, &diff_time);
! 800: timeradd(&diskp->dk_time, &diff_time, &diskp->dk_time);
! 801:
! 802: diskp->dk_timestamp = dv_time;
! 803: if (bcount > 0) {
! 804: if (read) {
! 805: diskp->dk_rbytes += bcount;
! 806: diskp->dk_rxfer++;
! 807: } else {
! 808: diskp->dk_wbytes += bcount;
! 809: diskp->dk_wxfer++;
! 810: }
! 811: } else
! 812: diskp->dk_seek++;
! 813:
! 814: add_disk_randomness(bcount ^ diff_time.tv_usec);
! 815: }
! 816:
! 817: int
! 818: disk_lock(struct disk *dk)
! 819: {
! 820: int error;
! 821:
! 822: error = rw_enter(&dk->dk_lock, RW_WRITE|RW_INTR);
! 823:
! 824: return (error);
! 825: }
! 826:
! 827: void
! 828: disk_unlock(struct disk *dk)
! 829: {
! 830: rw_exit(&dk->dk_lock);
! 831: }
! 832:
! 833: int
! 834: dk_mountroot(void)
! 835: {
! 836: dev_t rawdev, rrootdev;
! 837: int part = DISKPART(rootdev);
! 838: int (*mountrootfn)(void);
! 839: struct disklabel dl;
! 840: int error;
! 841:
! 842: rrootdev = blktochr(rootdev);
! 843: rawdev = MAKEDISKDEV(major(rrootdev), DISKUNIT(rootdev), RAW_PART);
! 844: #ifdef DEBUG
! 845: printf("rootdev=0x%x rrootdev=0x%x rawdev=0x%x\n", rootdev,
! 846: rrootdev, rawdev);
! 847: #endif
! 848:
! 849: /*
! 850: * open device, ioctl for the disklabel, and close it.
! 851: */
! 852: error = (cdevsw[major(rrootdev)].d_open)(rawdev, FREAD,
! 853: S_IFCHR, curproc);
! 854: if (error)
! 855: panic("cannot open disk, 0x%x/0x%x, error %d",
! 856: rootdev, rrootdev, error);
! 857: error = (cdevsw[major(rrootdev)].d_ioctl)(rawdev, DIOCGDINFO,
! 858: (caddr_t)&dl, FREAD, curproc);
! 859: if (error)
! 860: panic("cannot read disk label, 0x%x/0x%x, error %d",
! 861: rootdev, rrootdev, error);
! 862: (void) (cdevsw[major(rrootdev)].d_close)(rawdev, FREAD,
! 863: S_IFCHR, curproc);
! 864:
! 865: if (DL_GETPSIZE(&dl.d_partitions[part]) == 0)
! 866: panic("root filesystem has size 0");
! 867: switch (dl.d_partitions[part].p_fstype) {
! 868: #ifdef EXT2FS
! 869: case FS_EXT2FS:
! 870: {
! 871: extern int ext2fs_mountroot(void);
! 872: mountrootfn = ext2fs_mountroot;
! 873: }
! 874: break;
! 875: #endif
! 876: #ifdef FFS
! 877: case FS_BSDFFS:
! 878: {
! 879: extern int ffs_mountroot(void);
! 880: mountrootfn = ffs_mountroot;
! 881: }
! 882: break;
! 883: #endif
! 884: #ifdef CD9660
! 885: case FS_ISO9660:
! 886: {
! 887: extern int cd9660_mountroot(void);
! 888: mountrootfn = cd9660_mountroot;
! 889: }
! 890: break;
! 891: #endif
! 892: default:
! 893: #ifdef FFS
! 894: {
! 895: extern int ffs_mountroot(void);
! 896:
! 897: printf("filesystem type %d not known.. assuming ffs\n",
! 898: dl.d_partitions[part].p_fstype);
! 899: mountrootfn = ffs_mountroot;
! 900: }
! 901: #else
! 902: panic("disk 0x%x/0x%x filesystem type %d not known",
! 903: rootdev, rrootdev, dl.d_partitions[part].p_fstype);
! 904: #endif
! 905: }
! 906: return (*mountrootfn)();
! 907: }
! 908:
! 909: struct bufq *
! 910: bufq_default_alloc(void)
! 911: {
! 912: struct bufq_default *bq;
! 913:
! 914: bq = malloc(sizeof(*bq), M_DEVBUF, M_NOWAIT);
! 915: if (bq == NULL)
! 916: panic("bufq_default_alloc: no memory");
! 917:
! 918: memset(bq, 0, sizeof(*bq));
! 919: bq->bufq.bufq_free = bufq_default_free;
! 920: bq->bufq.bufq_add = bufq_default_add;
! 921: bq->bufq.bufq_get = bufq_default_get;
! 922:
! 923: return ((struct bufq *)bq);
! 924: }
! 925:
! 926: void
! 927: bufq_default_free(struct bufq *bq)
! 928: {
! 929: free(bq, M_DEVBUF);
! 930: }
! 931:
! 932: void
! 933: bufq_default_add(struct bufq *bq, struct buf *bp)
! 934: {
! 935: struct bufq_default *bufq = (struct bufq_default *)bq;
! 936: struct proc *p = bp->b_proc;
! 937: struct buf *head;
! 938:
! 939: if (p == NULL || p->p_nice < NZERO)
! 940: head = &bufq->bufq_head[0];
! 941: else if (p->p_nice == NZERO)
! 942: head = &bufq->bufq_head[1];
! 943: else
! 944: head = &bufq->bufq_head[2];
! 945:
! 946: disksort(head, bp);
! 947: }
! 948:
! 949: struct buf *
! 950: bufq_default_get(struct bufq *bq)
! 951: {
! 952: struct bufq_default *bufq = (struct bufq_default *)bq;
! 953: struct buf *bp, *head;
! 954: int i;
! 955:
! 956: for (i = 0; i < 3; i++) {
! 957: head = &bufq->bufq_head[i];
! 958: if ((bp = head->b_actf))
! 959: break;
! 960: }
! 961: if (bp == NULL)
! 962: return (NULL);
! 963: head->b_actf = bp->b_actf;
! 964: return (bp);
! 965: }
! 966:
! 967: #ifdef RAMDISK_HOOKS
! 968: static struct device fakerdrootdev = { DV_DISK, {}, NULL, 0, "rd0", NULL };
! 969: #endif
! 970:
! 971: struct device *
! 972: getdisk(char *str, int len, int defpart, dev_t *devp)
! 973: {
! 974: struct device *dv;
! 975:
! 976: if ((dv = parsedisk(str, len, defpart, devp)) == NULL) {
! 977: printf("use one of: exit");
! 978: #ifdef RAMDISK_HOOKS
! 979: printf(" %s[a-p]", fakerdrootdev.dv_xname);
! 980: #endif
! 981: TAILQ_FOREACH(dv, &alldevs, dv_list) {
! 982: if (dv->dv_class == DV_DISK)
! 983: printf(" %s[a-p]", dv->dv_xname);
! 984: #if defined(NFSCLIENT)
! 985: if (dv->dv_class == DV_IFNET)
! 986: printf(" %s", dv->dv_xname);
! 987: #endif
! 988: }
! 989: printf("\n");
! 990: }
! 991: return (dv);
! 992: }
! 993:
! 994: struct device *
! 995: parsedisk(char *str, int len, int defpart, dev_t *devp)
! 996: {
! 997: struct device *dv;
! 998: char c;
! 999: int majdev, part;
! 1000:
! 1001: if (len == 0)
! 1002: return (NULL);
! 1003: c = str[len-1];
! 1004: if (c >= 'a' && (c - 'a') < MAXPARTITIONS) {
! 1005: part = c - 'a';
! 1006: len -= 1;
! 1007: } else
! 1008: part = defpart;
! 1009:
! 1010: #ifdef RAMDISK_HOOKS
! 1011: if (strcmp(str, fakerdrootdev.dv_xname) == 0) {
! 1012: dv = &fakerdrootdev;
! 1013: goto gotdisk;
! 1014: }
! 1015: #endif
! 1016:
! 1017: TAILQ_FOREACH(dv, &alldevs, dv_list) {
! 1018: if (dv->dv_class == DV_DISK &&
! 1019: strncmp(str, dv->dv_xname, len) == 0 &&
! 1020: dv->dv_xname[len] == '\0') {
! 1021: #ifdef RAMDISK_HOOKS
! 1022: gotdisk:
! 1023: #endif
! 1024: majdev = findblkmajor(dv);
! 1025: if (majdev < 0)
! 1026: panic("parsedisk");
! 1027: *devp = MAKEDISKDEV(majdev, dv->dv_unit, part);
! 1028: break;
! 1029: }
! 1030: #if defined(NFSCLIENT)
! 1031: if (dv->dv_class == DV_IFNET &&
! 1032: strncmp(str, dv->dv_xname, len) == 0 &&
! 1033: dv->dv_xname[len] == '\0') {
! 1034: *devp = NODEV;
! 1035: break;
! 1036: }
! 1037: #endif
! 1038: }
! 1039:
! 1040: return (dv);
! 1041: }
! 1042:
! 1043: void
! 1044: setroot(struct device *bootdv, int part, int exitflags)
! 1045: {
! 1046: int majdev, unit, len, s;
! 1047: struct swdevt *swp;
! 1048: struct device *rootdv, *dv;
! 1049: dev_t nrootdev, nswapdev = NODEV, temp = NODEV;
! 1050: char buf[128];
! 1051: #if defined(NFSCLIENT)
! 1052: extern char *nfsbootdevname;
! 1053: #endif
! 1054:
! 1055: if (boothowto & RB_DFLTROOT)
! 1056: return;
! 1057:
! 1058: #ifdef RAMDISK_HOOKS
! 1059: bootdv = &fakerdrootdev;
! 1060: mountroot = NULL;
! 1061: part = 0;
! 1062: #endif
! 1063:
! 1064: /*
! 1065: * If `swap generic' and we couldn't determine boot device,
! 1066: * ask the user.
! 1067: */
! 1068: if (mountroot == NULL && bootdv == NULL)
! 1069: boothowto |= RB_ASKNAME;
! 1070: if (boothowto & RB_ASKNAME) {
! 1071: while (1) {
! 1072: printf("root device");
! 1073: if (bootdv != NULL) {
! 1074: printf(" (default %s", bootdv->dv_xname);
! 1075: if (bootdv->dv_class == DV_DISK)
! 1076: printf("%c", 'a' + part);
! 1077: printf(")");
! 1078: }
! 1079: printf(": ");
! 1080: s = splhigh();
! 1081: cnpollc(TRUE);
! 1082: len = getsn(buf, sizeof(buf));
! 1083: cnpollc(FALSE);
! 1084: splx(s);
! 1085: if (strcmp(buf, "exit") == 0)
! 1086: boot(exitflags);
! 1087: if (len == 0 && bootdv != NULL) {
! 1088: strlcpy(buf, bootdv->dv_xname, sizeof buf);
! 1089: len = strlen(buf);
! 1090: }
! 1091: if (len > 0 && buf[len - 1] == '*') {
! 1092: buf[--len] = '\0';
! 1093: dv = getdisk(buf, len, part, &nrootdev);
! 1094: if (dv != NULL) {
! 1095: rootdv = dv;
! 1096: nswapdev = nrootdev;
! 1097: goto gotswap;
! 1098: }
! 1099: }
! 1100: dv = getdisk(buf, len, part, &nrootdev);
! 1101: if (dv != NULL) {
! 1102: rootdv = dv;
! 1103: break;
! 1104: }
! 1105: }
! 1106:
! 1107: if (rootdv->dv_class == DV_IFNET)
! 1108: goto gotswap;
! 1109:
! 1110: /* try to build swap device out of new root device */
! 1111: while (1) {
! 1112: printf("swap device");
! 1113: if (rootdv != NULL)
! 1114: printf(" (default %s%s)", rootdv->dv_xname,
! 1115: rootdv->dv_class == DV_DISK ? "b" : "");
! 1116: printf(": ");
! 1117: s = splhigh();
! 1118: cnpollc(TRUE);
! 1119: len = getsn(buf, sizeof(buf));
! 1120: cnpollc(FALSE);
! 1121: splx(s);
! 1122: if (strcmp(buf, "exit") == 0)
! 1123: boot(exitflags);
! 1124: if (len == 0 && rootdv != NULL) {
! 1125: switch (rootdv->dv_class) {
! 1126: case DV_IFNET:
! 1127: nswapdev = NODEV;
! 1128: break;
! 1129: case DV_DISK:
! 1130: nswapdev = MAKEDISKDEV(major(nrootdev),
! 1131: DISKUNIT(nrootdev), 1);
! 1132: if (nswapdev == nrootdev)
! 1133: continue;
! 1134: break;
! 1135: default:
! 1136: break;
! 1137: }
! 1138: break;
! 1139: }
! 1140: dv = getdisk(buf, len, 1, &nswapdev);
! 1141: if (dv) {
! 1142: if (dv->dv_class == DV_IFNET)
! 1143: nswapdev = NODEV;
! 1144: if (nswapdev == nrootdev)
! 1145: continue;
! 1146: break;
! 1147: }
! 1148: }
! 1149: gotswap:
! 1150: rootdev = nrootdev;
! 1151: dumpdev = nswapdev;
! 1152: swdevt[0].sw_dev = nswapdev;
! 1153: swdevt[1].sw_dev = NODEV;
! 1154: #if defined(NFSCLIENT)
! 1155: } else if (mountroot == nfs_mountroot) {
! 1156: rootdv = bootdv;
! 1157: rootdev = dumpdev = swapdev = NODEV;
! 1158: #endif
! 1159: } else if (mountroot == NULL) {
! 1160: /* `swap generic': Use the device the ROM told us to use */
! 1161: rootdv = bootdv;
! 1162: majdev = findblkmajor(rootdv);
! 1163: if (majdev >= 0) {
! 1164: /*
! 1165: * Root and swap are on the disk.
! 1166: * Assume swap is on partition b.
! 1167: */
! 1168: rootdev = MAKEDISKDEV(majdev, rootdv->dv_unit, part);
! 1169: nswapdev = MAKEDISKDEV(majdev, rootdv->dv_unit, 1);
! 1170: } else {
! 1171: /*
! 1172: * Root and swap are on a net.
! 1173: */
! 1174: nswapdev = NODEV;
! 1175: }
! 1176: dumpdev = nswapdev;
! 1177: swdevt[0].sw_dev = nswapdev;
! 1178: /* swdevt[1].sw_dev = NODEV; */
! 1179: } else {
! 1180: /* Completely pre-configured, but we want rootdv .. */
! 1181: majdev = major(rootdev);
! 1182: if (findblkname(majdev) == NULL)
! 1183: return;
! 1184: unit = DISKUNIT(rootdev);
! 1185: part = DISKPART(rootdev);
! 1186: snprintf(buf, sizeof buf, "%s%d%c",
! 1187: findblkname(majdev), unit, 'a' + part);
! 1188: rootdv = parsedisk(buf, strlen(buf), 0, &nrootdev);
! 1189: }
! 1190:
! 1191: switch (rootdv->dv_class) {
! 1192: #if defined(NFSCLIENT)
! 1193: case DV_IFNET:
! 1194: mountroot = nfs_mountroot;
! 1195: nfsbootdevname = rootdv->dv_xname;
! 1196: return;
! 1197: #endif
! 1198: case DV_DISK:
! 1199: mountroot = dk_mountroot;
! 1200: part = DISKPART(rootdev);
! 1201: break;
! 1202: default:
! 1203: printf("can't figure root, hope your kernel is right\n");
! 1204: return;
! 1205: }
! 1206:
! 1207: printf("root on %s%c", rootdv->dv_xname, 'a' + part);
! 1208:
! 1209: /*
! 1210: * Make the swap partition on the root drive the primary swap.
! 1211: */
! 1212: for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
! 1213: if (major(rootdev) == major(swp->sw_dev) &&
! 1214: DISKUNIT(rootdev) == DISKUNIT(swp->sw_dev)) {
! 1215: temp = swdevt[0].sw_dev;
! 1216: swdevt[0].sw_dev = swp->sw_dev;
! 1217: swp->sw_dev = temp;
! 1218: break;
! 1219: }
! 1220: }
! 1221: if (swp->sw_dev != NODEV) {
! 1222: /*
! 1223: * If dumpdev was the same as the old primary swap device,
! 1224: * move it to the new primary swap device.
! 1225: */
! 1226: if (temp == dumpdev)
! 1227: dumpdev = swdevt[0].sw_dev;
! 1228: }
! 1229: if (swdevt[0].sw_dev != NODEV)
! 1230: printf(" swap on %s%d%c", findblkname(major(swdevt[0].sw_dev)),
! 1231: DISKUNIT(swdevt[0].sw_dev),
! 1232: 'a' + DISKPART(swdevt[0].sw_dev));
! 1233: if (dumpdev != NODEV)
! 1234: printf(" dump on %s%d%c", findblkname(major(dumpdev)),
! 1235: DISKUNIT(dumpdev), 'a' + DISKPART(dumpdev));
! 1236: printf("\n");
! 1237: }
! 1238:
! 1239: extern struct nam2blk nam2blk[];
! 1240:
! 1241: int
! 1242: findblkmajor(struct device *dv)
! 1243: {
! 1244: char *name = dv->dv_xname;
! 1245: int i;
! 1246:
! 1247: for (i = 0; nam2blk[i].name; i++)
! 1248: if (!strncmp(name, nam2blk[i].name, strlen(nam2blk[i].name)))
! 1249: return (nam2blk[i].maj);
! 1250: return (-1);
! 1251: }
! 1252:
! 1253: char *
! 1254: findblkname(int maj)
! 1255: {
! 1256: int i;
! 1257:
! 1258: for (i = 0; nam2blk[i].name; i++)
! 1259: if (nam2blk[i].maj == maj)
! 1260: return (nam2blk[i].name);
! 1261: return (NULL);
! 1262: }
CVSweb