disksubr.c revision 1.56
1/* $NetBSD: disksubr.c,v 1.56 2019/12/15 12:50:39 martin 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.56 2019/12/15 12:50:39 martin Exp $"); 36 37#include "opt_compat_ultrix.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/buf.h> 42#include <sys/disk.h> 43#include <sys/disklabel.h> 44 45#include <dev/dec/dec_boot.h> 46#include <ufs/ufs/dinode.h> /* XXX for fs.h */ 47#include <ufs/ffs/fs.h> /* XXX for BBSIZE & SBSIZE */ 48 49const char *compat_label(dev_t dev, void (*strat)(struct buf *bp), 50 struct disklabel *lp, struct cpu_disklabel *osdep); /* XXX */ 51 52/* 53 * Attempt to read a disk label from a device 54 * using the indicated strategy routine. 55 * The label must be partly set up before this: 56 * secpercyl and anything required in the strategy routine 57 * (e.g., sector size) must be filled in before calling us. 58 * Returns null on success and an error string on failure. 59 */ 60const char * 61readdisklabel(dev_t dev, void (*strat)(struct buf *bp), struct disklabel *lp, 62 struct cpu_disklabel *osdep) 63{ 64 struct buf *bp; 65 struct disklabel *dlp; 66 const char *msg = NULL; 67 68 if (lp->d_secperunit == 0) 69 lp->d_secperunit = 0x1fffffff; 70 lp->d_npartitions = 1; 71 if (lp->d_partitions[0].p_size == 0) 72 lp->d_partitions[0].p_size = 0x1fffffff; 73 lp->d_partitions[0].p_offset = 0; 74 75 bp = geteblk((int)lp->d_secsize); 76 bp->b_dev = dev; 77 bp->b_blkno = LABELSECTOR; 78 bp->b_bcount = lp->d_secsize; 79 bp->b_flags |= B_READ; 80 bp->b_cylinder = LABELSECTOR / lp->d_secpercyl; 81 (*strat)(bp); 82 if (biowait(bp)) { 83 msg = "I/O error"; 84 } else for (dlp = (struct disklabel *)bp->b_data; 85 dlp <= (struct disklabel *) 86 ((char *)bp->b_data + DEV_BSIZE - sizeof(*dlp)); 87 dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 88 if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { 89 if (msg == NULL) 90 msg = "no disk label"; 91 } else if (dlp->d_npartitions > MAXPARTITIONS || 92 dkcksum(dlp) != 0) 93 msg = "disk label corrupted"; 94 else { 95 *lp = *dlp; 96 msg = NULL; 97 break; 98 } 99 } 100 brelse(bp, 0); 101 /* 102 * If no NetBSD label was found, check for an Ultrix label and 103 * construct tne incore label from the Ultrix partition information. 104 */ 105 if (msg != NULL) { 106 msg = compat_label(dev, strat, lp, osdep); 107 if (msg == NULL) { 108 printf("WARNING: using Ultrix partition information\n"); 109 /* set geometry? */ 110 } 111 } 112/* XXX If no NetBSD label or Ultrix label found, generate default label here */ 113 return msg; 114} 115 116/* 117 * Given a buffer bp, try and interpret it as an Ultrix disk label, 118 * putting the partition info into a native NetBSD label 119 */ 120const char * 121compat_label(dev_t dev, void (*strat)(struct buf *bp), struct disklabel *lp, 122 struct cpu_disklabel *osdep) 123{ 124 dec_disklabel *dlp; 125 struct buf *bp = NULL; 126 const char *msg = NULL; 127 128 bp = geteblk((int)lp->d_secsize); 129 bp->b_dev = dev; 130 bp->b_blkno = DEC_LABEL_SECTOR; 131 bp->b_bcount = lp->d_secsize; 132 bp->b_flags |= B_READ; 133 bp->b_cylinder = DEC_LABEL_SECTOR / lp->d_secpercyl; 134 (*strat)(bp); 135 136 if (biowait(bp)) { 137 msg = "I/O error"; 138 goto done; 139 } 140 141 for (dlp = (dec_disklabel *)bp->b_data; 142 dlp <= (dec_disklabel *) 143 ((char *)bp->b_data + DEV_BSIZE - sizeof(*dlp)); 144 dlp = (dec_disklabel *)((char *)dlp + sizeof(long))) { 145 146 int part; 147 148 if (dlp->magic != DEC_LABEL_MAGIC) { 149#if 0 150 printf("label: %x\n",dlp->magic); 151#endif 152 msg = ((msg != NULL) ? msg: "no disk label"); 153 goto done; 154 } 155 156#ifdef DIAGNOSTIC 157/*XXX*/ printf("Interpreting Ultrix label\n"); 158#endif 159 160 lp->d_magic = DEC_LABEL_MAGIC; 161 lp->d_npartitions = 0; 162 strncpy(lp->d_packname, "Ultrix label", 16); 163 lp->d_rpm = 3600; 164 lp->d_interleave = 1; 165 lp->d_flags = 0; 166 lp->d_bbsize = BBSIZE; 167 lp->d_sbsize = SBLOCKSIZE; 168 for (part = 0; 169 part <((MAXPARTITIONS<DEC_NUM_DISK_PARTS) ? 170 MAXPARTITIONS : DEC_NUM_DISK_PARTS); 171 part++) { 172 lp->d_partitions[part].p_size = 173 dlp->map[part].num_blocks; 174 lp->d_partitions[part].p_offset = 175 dlp->map[part].start_block; 176 lp->d_partitions[part].p_fsize = 1024; 177 lp->d_partitions[part].p_fstype = 178 (part==1) ? FS_SWAP : FS_BSDFFS; 179 lp->d_npartitions += 1; 180 181#ifdef DIAGNOSTIC 182 printf(" Ultrix label rz%d%c: start %d len %d\n", 183 DISKUNIT(dev), "abcdefgh"[part], 184 lp->d_partitions[part].p_offset, 185 lp->d_partitions[part].p_size); 186#endif 187 } 188 break; 189 } 190 191done: 192 brelse(bp, 0); 193 return msg; 194} 195 196/* 197 * Write disk label back to device after modification. 198 */ 199int 200writedisklabel(dev_t dev, void (*strat)(struct buf *bp), struct disklabel *lp, 201 struct cpu_disklabel *osdep) 202{ 203 struct buf *bp; 204 struct disklabel *dlp; 205 int labelpart; 206 int error = 0; 207 208 labelpart = DISKPART(dev); 209 if (lp->d_partitions[labelpart].p_offset != 0) { 210 if (lp->d_partitions[0].p_offset != 0) 211 return EXDEV; /* not quite right */ 212 labelpart = 0; 213 } 214 bp = geteblk((int)lp->d_secsize); 215 bp->b_dev = makedev(major(dev), DISKMINOR(DISKUNIT(dev), labelpart)); 216 bp->b_blkno = LABELSECTOR; 217 bp->b_bcount = lp->d_secsize; 218 bp->b_flags |= B_READ; 219 (*strat)(bp); 220 if ((error = biowait(bp)) != 0) 221 goto done; 222 for (dlp = (struct disklabel *)bp->b_data; 223 dlp <= (struct disklabel *) 224 ((char *)bp->b_data + lp->d_secsize - sizeof(*dlp)); 225 dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 226 if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && 227 dkcksum(dlp) == 0) { 228 *dlp = *lp; 229 bp->b_oflags &= ~(BO_DONE); 230 bp->b_flags &= ~(B_READ); 231 bp->b_flags |= B_WRITE; 232 (*strat)(bp); 233 error = biowait(bp); 234 goto done; 235 } 236 } 237 error = ESRCH; 238done: 239 brelse(bp, 0); 240 return error; 241} 242