Home | History | Annotate | Line # | Download | only in evbppc
      1 /*	$NetBSD: disksubr.c,v 1.20 2026/07/14 13:34:34 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  *
     31  *	@(#)ufs_disksubr.c	7.16 (Berkeley) 5/4/91
     32  */
     33 
     34 #include <sys/cdefs.h>
     35 __KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.20 2026/07/14 13:34:34 thorpej Exp $");
     36 
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/buf.h>
     40 #include <sys/disklabel.h>
     41 #include <sys/disk.h>
     42 #include <sys/syslog.h>
     43 
     44 /*
     45  * Attempt to read a disk label from a device
     46  * using the indicated strategy routine.
     47  * The label must be partly set up before this:
     48  * secpercyl, secsize and anything required for a block i/o read
     49  * operation in the driver's strategy/start routines
     50  * must be filled in before calling us.
     51  *
     52  * If dos partition table requested, attempt to load it and
     53  * find disklabel inside a DOS partition. Also, if bad block
     54  * table needed, attempt to extract it as well. Return buffer
     55  * for use in signalling errors if requested.
     56  *
     57  * Returns null on success and an error string on failure.
     58  */
     59 const char *
     60 readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
     61 	      struct cpu_disklabel *osdep)
     62 {
     63 	struct buf *bp;
     64 	struct disklabel *dlp;
     65 	const char *msg = NULL;
     66 
     67 	/* minimal requirements for archetypal disk label */
     68 	if (lp->d_secsize == 0)
     69 		lp->d_secsize = DEV_BSIZE;
     70 	if (lp->d_secperunit == 0)
     71 		lp->d_secperunit = 0x1fffffff;
     72 	lp->d_npartitions = RAW_PART + 1;
     73 	if (lp->d_partitions[RAW_PART].p_size == 0)
     74 		lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
     75 	lp->d_partitions[RAW_PART].p_offset = 0;
     76 
     77 	/* get a buffer and initialize it */
     78 	bp = geteblk((int)lp->d_secsize);
     79 
     80 	/* next, dig out disk label */
     81 	bp->b_dev = dev;
     82 	bp->b_blkno = LABELSECTOR;
     83 	bp->b_cylinder = 0;
     84 	bp->b_bcount = lp->d_secsize;
     85 	bp->b_flags |= B_READ;
     86 	(*strat)(bp);
     87 
     88 	/* if successful, locate disk label within block and validate */
     89 	if (biowait(bp)) {
     90 		msg = "disk label I/O error";
     91 		goto done;
     92 	}
     93 
     94 	for (dlp = (struct disklabel *)bp->b_data;
     95 	    dlp <= (struct disklabel *)((char *)bp->b_data + lp->d_secsize -
     96 		sizeof(*dlp));
     97 	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
     98 		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
     99 			if (msg == NULL)
    100 				msg = "no disk label";
    101 		} else if (dlp->d_npartitions > MAXPARTITIONS ||
    102 			   dkcksum(dlp) != 0)
    103 			msg = "disk label corrupted";
    104 		else {
    105 			*lp = *dlp;
    106 			msg = NULL;
    107 			break;
    108 		}
    109 	}
    110 
    111 done:
    112 	brelse(bp, BC_INVAL);
    113 	return (msg);
    114 }
    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 error;
    127 
    128 #ifdef maybe
    129 	/* disklabel in appropriate location? */
    130 	if (lp->d_partitions[2].p_offset != 0
    131 		&& lp->d_partitions[2].p_offset != dospartoff) {
    132 		error = EXDEV;
    133 		goto done;
    134 	}
    135 #endif
    136 
    137 	/* get a buffer and initialize it */
    138 	bp = geteblk((int)lp->d_secsize);
    139 	bp->b_dev = dev;
    140 	bp->b_blkno = LABELSECTOR;
    141 	bp->b_cylinder = 0;
    142 	bp->b_bcount = lp->d_secsize;
    143 	bp->b_flags |= B_READ;
    144 	(*strat)(bp);
    145 
    146 	/* if successful, locate disk label within block and validate */
    147 	if ((error = biowait(bp)) != 0)
    148 		goto done;
    149 	for (dlp = (struct disklabel *)bp->b_data;
    150 	    dlp <= (struct disklabel *)((char *)bp->b_data + lp->d_secsize -
    151 		sizeof(*dlp));
    152 	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
    153 		if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
    154 		    dkcksum(dlp) == 0) {
    155 			*dlp = *lp;
    156 			bp->b_cflags = BC_BUSY;
    157 			bp->b_flags = B_WRITE;
    158 			CLR(bp->b_oflags, BO_DONE);
    159 			(*strat)(bp);
    160 			error = biowait(bp);
    161 			goto done;
    162 		}
    163 	}
    164 	error = ESRCH;
    165 
    166 done:
    167 	brelse(bp, 0);
    168 	return (error);
    169 }
    170