1 /* $NetBSD: disksubr.c,v 1.44 2026/07/14 13:34:33 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 5 * All rights reserved. 6 * 7 * Authors: Keith Bostic, Chris G. Demetriou 8 * 9 * Permission to use, copy, modify and distribute this software and 10 * its documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 */ 29 30 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 31 32 __KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.44 2026/07/14 13:34:33 thorpej Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/buf.h> 37 #include <sys/ioccom.h> 38 #include <sys/device.h> 39 #include <sys/disklabel.h> 40 #include <sys/disk.h> 41 42 #include <machine/cpu.h> 43 #include <machine/autoconf.h> 44 45 extern device_t bootdv; 46 47 /* 48 * Attempt to read a disk label from a device 49 * using the indicated strategy routine. 50 * The label must be partly set up before this: 51 * secpercyl and anything required in the strategy routine 52 * (e.g., sector size) must be filled in before calling us. 53 * Returns null on success and an error string on failure. 54 */ 55 const char * 56 readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *clp) 57 { 58 struct buf *bp; 59 struct disklabel *dlp; 60 const char *msg = NULL; 61 62 /* minimal requirements for archetypal disk label */ 63 if (lp->d_secsize == 0) 64 lp->d_secsize = DEV_BSIZE; 65 if (lp->d_secperunit == 0) 66 lp->d_secperunit = 0x1fffffff; 67 lp->d_npartitions = RAW_PART + 1; 68 if (lp->d_partitions[RAW_PART].p_size == 0) 69 lp->d_partitions[RAW_PART].p_size = lp->d_secperunit; 70 lp->d_partitions[RAW_PART].p_offset = 0; 71 72 /* obtain buffer to probe drive with */ 73 bp = geteblk((int)lp->d_secsize); 74 75 /* next, dig out disk label */ 76 bp->b_dev = dev; 77 bp->b_blkno = LABELSECTOR; 78 bp->b_cylinder = 0; 79 bp->b_bcount = lp->d_secsize; 80 bp->b_flags |= B_READ; 81 (*strat)(bp); 82 83 /* if successful, locate disk label within block and validate */ 84 if (biowait(bp)) { 85 msg = "disk label read error"; 86 goto done; 87 } 88 89 dlp = (struct disklabel *)((char *)bp->b_data + LABELOFFSET); 90 if (dlp->d_magic == DISKMAGIC) { 91 if (dkcksum(dlp)) 92 msg = "NetBSD disk label corrupted"; 93 else 94 *lp = *dlp; 95 } else 96 msg = "no disk label"; 97 98 done: 99 brelse(bp, 0); 100 return (msg); 101 } 102 103 /* 104 * Write disk label back to device after modification. 105 * This means write out the rigid disk blocks to represent the 106 * label. Hope the user was careful. 107 */ 108 int 109 writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *clp) 110 { 111 struct buf *bp; 112 struct disklabel *dlp; 113 int error = 0; 114 115 bp = geteblk((int)lp->d_secsize); 116 bp->b_dev = dev; 117 bp->b_blkno = LABELSECTOR; 118 bp->b_cylinder = 0; 119 bp->b_bcount = lp->d_secsize; 120 bp->b_flags |= B_READ; /* get current label */ 121 (*strat)(bp); 122 if ((error = biowait(bp)) != 0) 123 goto done; 124 125 dlp = (struct disklabel *)((char *)bp->b_data + LABELOFFSET); 126 *dlp = *lp; /* struct assignment */ 127 128 /* 129 * The Alpha requires that the boot block be checksummed. 130 * The first 63 8-bit quantites are summed into the 64th. 131 */ 132 { 133 int i; 134 u_long *dp, sum; 135 136 dp = (u_long *)bp->b_data; 137 sum = 0; 138 for (i = 0; i < 63; i++) 139 sum += dp[i]; 140 dp[63] = sum; 141 } 142 143 bp->b_flags &= ~B_READ; 144 bp->b_flags |= B_WRITE; 145 bp->b_oflags &= ~BO_DONE; 146 (*strat)(bp); 147 error = biowait(bp); 148 149 done: 150 brelse(bp, 0); 151 return (error); 152 } 153