Home | History | Annotate | Line # | Download | only in kern
subr_disk_4bsd.c revision 1.1
      1 /*	$NetBSD: subr_disk_4bsd.c,v 1.1 2026/04/04 00:23:09 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1982, 1986, 1988, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  * (c) UNIX System Laboratories, Inc.
      7  * All or some portions of this file are derived from material licensed
      8  * to the University of California by American Telephone and Telegraph
      9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
     10  * the permission of UNIX System Laboratories, Inc.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  * 3. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  *
     36  *	@(#)ufs_disksubr.c	8.5 (Berkeley) 1/21/94
     37  */
     38 
     39 #include <sys/cdefs.h>
     40 __KERNEL_RCSID(0, "$NetBSD: subr_disk_4bsd.c,v 1.1 2026/04/04 00:23:09 thorpej Exp $");
     41 
     42 #include <sys/param.h>
     43 #include <sys/systm.h>
     44 #include <sys/buf.h>
     45 #include <sys/disk.h>
     46 #include <sys/disklabel.h>
     47 
     48 /*
     49  * Implementation of readdisklabel() and writedisklabel() for the simple
     50  * "basic scheme from 4BSD".
     51  *
     52  * Lifted verbatim from the hp300 copy.
     53  */
     54 
     55 /*
     56  * Attempt to read a disk label from a device using the indicated strategy
     57  * routine.  The label must be partly set up before this: secpercyl and
     58  * anything required in the strategy routine (e.g., sector size) must be
     59  * filled in before calling us.  Returns null on success and an error
     60  * string on failure.
     61  */
     62 const char *
     63 readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
     64     struct cpu_disklabel *osdep)
     65 {
     66 	struct buf *bp;
     67 	struct disklabel *dlp;
     68 	const char *msg = NULL;
     69 	int i;
     70 
     71 	if (lp->d_secsize == 0)
     72 		lp->d_secsize = DEV_BSIZE;
     73 	if (lp->d_secperunit == 0)
     74 		lp->d_secperunit = 0x1fffffff;
     75 	if (lp->d_npartitions < RAW_PART + 1)
     76 		lp->d_npartitions = RAW_PART + 1;
     77 	for (i = 0; i < RAW_PART; i++) {
     78 		lp->d_partitions[i].p_size = 0;
     79 		lp->d_partitions[i].p_offset = 0;
     80 	}
     81 	if (lp->d_partitions[RAW_PART].p_size == 0)
     82 		lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
     83 	lp->d_partitions[RAW_PART].p_offset = 0;
     84 
     85 	lp->d_partitions[0].p_size = lp->d_partitions[RAW_PART].p_size;
     86 	lp->d_partitions[0].p_fstype = FS_BSDFFS;
     87 
     88 	bp = geteblk((int)lp->d_secsize);
     89 	bp->b_dev = dev;
     90 	bp->b_blkno = LABELSECTOR;
     91 	bp->b_bcount = lp->d_secsize;
     92 	bp->b_flags |= B_READ;
     93 	bp->b_cylinder = LABELSECTOR / lp->d_secpercyl;
     94 	(*strat)(bp);
     95 	if (biowait(bp))
     96 		msg = "I/O error";
     97 	else for (dlp = (struct disklabel *)bp->b_data;
     98 	    dlp <= (struct disklabel *)((char *)bp->b_data +
     99 	    DEV_BSIZE - sizeof(*dlp));
    100 	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
    101 		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
    102 			if (msg == NULL)
    103 				msg = "no disk label";
    104 		} else if (dlp->d_npartitions > MAXPARTITIONS ||
    105 			   dkcksum(dlp) != 0)
    106 			msg = "disk label corrupted";
    107 		else {
    108 			*lp = *dlp;
    109 			msg = NULL;
    110 			break;
    111 		}
    112 	}
    113 	brelse(bp, 0);
    114 	return msg;
    115 }
    116 
    117 /*
    118  * Write disk label back to device after modification.
    119  */
    120 int
    121 writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
    122     struct cpu_disklabel *osdep)
    123 {
    124 	struct buf *bp;
    125 	struct disklabel *dlp;
    126 	int labelpart;
    127 	int error = 0;
    128 
    129 	labelpart = DISKPART(dev);
    130 	if (lp->d_partitions[labelpart].p_offset != 0) {
    131 		if (lp->d_partitions[0].p_offset != 0)
    132 			return EXDEV;			/* not quite right */
    133 		labelpart = 0;
    134 	}
    135 	bp = geteblk((int)lp->d_secsize);
    136 	bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), labelpart);
    137 	bp->b_blkno = LABELSECTOR;
    138 	bp->b_bcount = lp->d_secsize;
    139 	bp->b_flags |= B_READ;
    140 	(*strat)(bp);
    141 	if ((error = biowait(bp)) != 0)
    142 		goto done;
    143 	for (dlp = (struct disklabel *)bp->b_data;
    144 	    dlp <= (struct disklabel *)
    145 	      ((char *)bp->b_data + lp->d_secsize - sizeof(*dlp));
    146 	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
    147 		if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
    148 		    dkcksum(dlp) == 0) {
    149 			*dlp = *lp;
    150 			bp->b_oflags &= ~(BO_DONE);
    151 			bp->b_flags &= ~(B_READ);
    152 			bp->b_flags |= B_WRITE;
    153 			(*strat)(bp);
    154 			error = biowait(bp);
    155 			goto done;
    156 		}
    157 	}
    158 	error = ESRCH;
    159  done:
    160 	brelse(bp, 0);
    161 	return error;
    162 }
    163