1 1.4 thorpej /* $NetBSD: subr_disk_4bsd.c,v 1.4 2026/08/09 16:10:00 thorpej Exp $ */ 2 1.1 thorpej 3 1.1 thorpej /* 4 1.1 thorpej * Copyright (c) 1982, 1986, 1988, 1993 5 1.1 thorpej * The Regents of the University of California. All rights reserved. 6 1.1 thorpej * (c) UNIX System Laboratories, Inc. 7 1.1 thorpej * All or some portions of this file are derived from material licensed 8 1.1 thorpej * to the University of California by American Telephone and Telegraph 9 1.1 thorpej * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10 1.1 thorpej * the permission of UNIX System Laboratories, Inc. 11 1.1 thorpej * 12 1.1 thorpej * Redistribution and use in source and binary forms, with or without 13 1.1 thorpej * modification, are permitted provided that the following conditions 14 1.1 thorpej * are met: 15 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 16 1.1 thorpej * notice, this list of conditions and the following disclaimer. 17 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 18 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 19 1.1 thorpej * documentation and/or other materials provided with the distribution. 20 1.1 thorpej * 3. Neither the name of the University nor the names of its contributors 21 1.1 thorpej * may be used to endorse or promote products derived from this software 22 1.1 thorpej * without specific prior written permission. 23 1.1 thorpej * 24 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 1.1 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 1.1 thorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 1.1 thorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 1.1 thorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 1.1 thorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 1.1 thorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 1.1 thorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 1.1 thorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 1.1 thorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 1.1 thorpej * SUCH DAMAGE. 35 1.1 thorpej * 36 1.1 thorpej * @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94 37 1.1 thorpej */ 38 1.1 thorpej 39 1.1 thorpej #include <sys/cdefs.h> 40 1.4 thorpej __KERNEL_RCSID(0, "$NetBSD: subr_disk_4bsd.c,v 1.4 2026/08/09 16:10:00 thorpej Exp $"); 41 1.4 thorpej 42 1.4 thorpej #define __SUBR_DISK_4BSD_PRIVATE 43 1.1 thorpej 44 1.1 thorpej #include <sys/param.h> 45 1.1 thorpej #include <sys/systm.h> 46 1.1 thorpej #include <sys/buf.h> 47 1.1 thorpej #include <sys/disk.h> 48 1.1 thorpej #include <sys/disklabel.h> 49 1.1 thorpej 50 1.1 thorpej /* 51 1.1 thorpej * Implementation of readdisklabel() and writedisklabel() for the simple 52 1.1 thorpej * "basic scheme from 4BSD". 53 1.1 thorpej */ 54 1.1 thorpej 55 1.1 thorpej /* 56 1.3 thorpej * We prefer the platform's "native" label sector / offset. Look for 57 1.3 thorpej * it there first. Otherwise, scan the first 3 disk sectors for the 58 1.3 thorpej * label. When updating a label, we will write it to where we found 59 1.3 thorpej * it. If writing a new label from scratch, we will write it to the 60 1.3 thorpej * "native" location. 61 1.3 thorpej */ 62 1.3 thorpej static int label_sectors[] = { LABELSECTOR, 0, 1, 2 }; 63 1.3 thorpej static int label_offsets[] = { LABELOFFSET, -1, -1, -1 }; 64 1.3 thorpej 65 1.3 thorpej #define DISKLABEL_SIZE(x) \ 66 1.3 thorpej (offsetof(struct disklabel, d_partitions) + \ 67 1.3 thorpej (sizeof(struct partition) * (x))) 68 1.3 thorpej 69 1.3 thorpej /* Smallest 4.4BSD disklabel that was ever in use. */ 70 1.3 thorpej #define DISKLABEL_MINSIZE DISKLABEL_SIZE(8) 71 1.3 thorpej 72 1.3 thorpej static bool 73 1.3 thorpej taste_label(const struct disklabel *lp, void *buf, size_t secsize) 74 1.3 thorpej { 75 1.3 thorpej uint16_t npartitions; 76 1.3 thorpej 77 1.3 thorpej if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC) { 78 1.3 thorpej return false; 79 1.3 thorpej } 80 1.3 thorpej 81 1.3 thorpej npartitions = lp->d_npartitions; 82 1.3 thorpej 83 1.3 thorpej if ((uintptr_t)lp + DISKLABEL_SIZE(npartitions) > 84 1.3 thorpej (uintptr_t)buf + secsize) { 85 1.3 thorpej /* doesn't fit in the sector. */ 86 1.3 thorpej return false; 87 1.3 thorpej } 88 1.3 thorpej 89 1.3 thorpej if (npartitions > MAXPARTITIONS || dkcksum(lp)) { 90 1.3 thorpej /* disklabel is corrupted. */ 91 1.3 thorpej return false; 92 1.3 thorpej } 93 1.3 thorpej 94 1.3 thorpej return true; 95 1.3 thorpej } 96 1.3 thorpej 97 1.3 thorpej static struct disklabel * 98 1.3 thorpej find_label_in_sector(void *buf, size_t secsize, int offs) 99 1.3 thorpej { 100 1.3 thorpej struct disklabel *lp = buf; 101 1.3 thorpej uintptr_t lp_lim = ((uintptr_t)buf + secsize - DISKLABEL_MINSIZE); 102 1.3 thorpej 103 1.3 thorpej if (offs != -1) { 104 1.3 thorpej lp = (void *)((uintptr_t)lp + offs); 105 1.3 thorpej return taste_label(lp, buf, secsize) ? lp : NULL; 106 1.3 thorpej } 107 1.3 thorpej 108 1.3 thorpej for (;; lp = (void *)((uintptr_t)lp + sizeof(uint32_t))) { 109 1.3 thorpej if ((uintptr_t)lp > lp_lim) { 110 1.3 thorpej /* Not found in this sector. */ 111 1.3 thorpej return NULL; 112 1.3 thorpej } 113 1.3 thorpej if (taste_label(lp, buf, secsize)) { 114 1.3 thorpej return lp; 115 1.3 thorpej } 116 1.3 thorpej } 117 1.3 thorpej } 118 1.3 thorpej 119 1.4 thorpej __weak_alias(readdisklabel, readdisklabel_4bsd); 120 1.4 thorpej __weak_alias(writedisklabel, writedisklabel_4bsd); 121 1.4 thorpej 122 1.3 thorpej /* 123 1.1 thorpej * Attempt to read a disk label from a device using the indicated strategy 124 1.1 thorpej * routine. The label must be partly set up before this: secpercyl and 125 1.1 thorpej * anything required in the strategy routine (e.g., sector size) must be 126 1.1 thorpej * filled in before calling us. Returns null on success and an error 127 1.1 thorpej * string on failure. 128 1.1 thorpej */ 129 1.1 thorpej const char * 130 1.4 thorpej readdisklabel_4bsd(dev_t dev, void (*strat)(struct buf *), 131 1.4 thorpej struct disklabel *lp, struct cpu_disklabel *osdep) 132 1.1 thorpej { 133 1.1 thorpej struct buf *bp; 134 1.1 thorpej struct disklabel *dlp; 135 1.1 thorpej const char *msg = NULL; 136 1.1 thorpej int i; 137 1.1 thorpej 138 1.1 thorpej if (lp->d_secsize == 0) 139 1.1 thorpej lp->d_secsize = DEV_BSIZE; 140 1.1 thorpej if (lp->d_secperunit == 0) 141 1.1 thorpej lp->d_secperunit = 0x1fffffff; 142 1.1 thorpej if (lp->d_npartitions < RAW_PART + 1) 143 1.1 thorpej lp->d_npartitions = RAW_PART + 1; 144 1.1 thorpej for (i = 0; i < RAW_PART; i++) { 145 1.1 thorpej lp->d_partitions[i].p_size = 0; 146 1.1 thorpej lp->d_partitions[i].p_offset = 0; 147 1.1 thorpej } 148 1.1 thorpej if (lp->d_partitions[RAW_PART].p_size == 0) 149 1.1 thorpej lp->d_partitions[RAW_PART].p_size = lp->d_secperunit; 150 1.1 thorpej lp->d_partitions[RAW_PART].p_offset = 0; 151 1.1 thorpej 152 1.1 thorpej lp->d_partitions[0].p_size = lp->d_partitions[RAW_PART].p_size; 153 1.1 thorpej lp->d_partitions[0].p_fstype = FS_BSDFFS; 154 1.1 thorpej 155 1.1 thorpej bp = geteblk((int)lp->d_secsize); 156 1.1 thorpej bp->b_dev = dev; 157 1.3 thorpej 158 1.3 thorpej for (i = 0; i < __arraycount(label_sectors); i++) { 159 1.3 thorpej if (disk_read_sectors(strat, lp, bp, label_sectors[i], 1)) { 160 1.3 thorpej msg = "I/O error"; 161 1.3 thorpej goto done; 162 1.3 thorpej } 163 1.3 thorpej 164 1.3 thorpej dlp = find_label_in_sector(bp->b_data, DEV_BSIZE, 165 1.3 thorpej label_offsets[i]); 166 1.3 thorpej if (dlp != NULL) { 167 1.1 thorpej *lp = *dlp; 168 1.1 thorpej msg = NULL; 169 1.1 thorpej break; 170 1.1 thorpej } 171 1.1 thorpej } 172 1.3 thorpej done: 173 1.1 thorpej brelse(bp, 0); 174 1.1 thorpej return msg; 175 1.1 thorpej } 176 1.1 thorpej 177 1.1 thorpej /* 178 1.1 thorpej * Write disk label back to device after modification. 179 1.1 thorpej */ 180 1.1 thorpej int 181 1.4 thorpej writedisklabel_4bsd(dev_t dev, void (*strat)(struct buf *), 182 1.4 thorpej struct disklabel *lp, struct cpu_disklabel *osdep) 183 1.1 thorpej { 184 1.1 thorpej struct buf *bp; 185 1.1 thorpej struct disklabel *dlp; 186 1.1 thorpej int labelpart; 187 1.3 thorpej int i, error = 0; 188 1.1 thorpej 189 1.1 thorpej labelpart = DISKPART(dev); 190 1.1 thorpej if (lp->d_partitions[labelpart].p_offset != 0) { 191 1.1 thorpej if (lp->d_partitions[0].p_offset != 0) 192 1.1 thorpej return EXDEV; /* not quite right */ 193 1.1 thorpej labelpart = 0; 194 1.1 thorpej } 195 1.1 thorpej bp = geteblk((int)lp->d_secsize); 196 1.1 thorpej bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), labelpart); 197 1.3 thorpej 198 1.3 thorpej for (i = 0; i < __arraycount(label_sectors); i++) { 199 1.3 thorpej if ((error = disk_read_sectors(strat, lp, bp, 200 1.3 thorpej label_sectors[i], 1)) != 0) { 201 1.3 thorpej goto done; 202 1.3 thorpej } 203 1.3 thorpej 204 1.3 thorpej dlp = find_label_in_sector(bp->b_data, DEV_BSIZE, 205 1.3 thorpej label_offsets[i]); 206 1.3 thorpej if (dlp != NULL) { 207 1.1 thorpej *dlp = *lp; 208 1.1 thorpej bp->b_oflags &= ~(BO_DONE); 209 1.1 thorpej bp->b_flags &= ~(B_READ); 210 1.1 thorpej bp->b_flags |= B_WRITE; 211 1.1 thorpej (*strat)(bp); 212 1.1 thorpej error = biowait(bp); 213 1.1 thorpej goto done; 214 1.1 thorpej } 215 1.1 thorpej } 216 1.1 thorpej error = ESRCH; 217 1.1 thorpej done: 218 1.1 thorpej brelse(bp, 0); 219 1.1 thorpej return error; 220 1.1 thorpej } 221