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