1 /* $OpenBSD: disksubr.c,v 1.101 2022/10/11 23:39:07 krw Exp $ */
2 /* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */
3
4 /*
5 * Copyright (c) 1997 Niklas Hallqvist
6 * Copyright (c) 1996 Theo de Raadt
7 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/buf.h>
38 #include <sys/disklabel.h>
39 #include <sys/disk.h>
40
41 /*
42 * Attempt to read a disk label from a device
43 * using the indicated strategy routine.
44 * The label must be partly set up before this:
45 * secpercyl, secsize and anything required for a block i/o read
46 * operation in the driver's strategy/start routines
47 * must be filled in before calling us.
48 */
49 int
readdisklabel(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,int spoofonly)50 readdisklabel(dev_t dev, void (*strat)(struct buf *),
51 struct disklabel *lp, int spoofonly)
52 {
53 struct buf *bp = NULL;
54 int error;
55
56 if ((error = initdisklabel(lp)))
57 goto done;
58
59 /* get a buffer and initialize it */
60 bp = geteblk(lp->d_secsize);
61 bp->b_dev = dev;
62
63 if (spoofonly)
64 goto doslabel;
65
66 error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, LABELSECTOR));
67 if (error)
68 goto done;
69
70 error = checkdisklabel(bp->b_dev, bp->b_data + LABELOFFSET, lp, 0,
71 DL_GETDSIZE(lp));
72 if (error == 0)
73 goto done;
74
75 doslabel:
76 error = readdoslabel(bp, strat, lp, NULL, spoofonly);
77 if (error == 0)
78 goto done;
79
80 #if defined(CD9660)
81 error = iso_disklabelspoof(dev, strat, lp);
82 if (error == 0)
83 goto done;
84 #endif
85 #if defined(UDF)
86 error = udf_disklabelspoof(dev, strat, lp);
87 if (error == 0)
88 goto done;
89 #endif
90
91 done:
92 if (bp) {
93 bp->b_flags |= B_INVAL;
94 brelse(bp);
95 }
96 disk_change = 1;
97 return (error);
98 }
99
100 /*
101 * Write disk label back to device after modification.
102 */
103 int
writedisklabel(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp)104 writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
105 {
106 u_int64_t csum = 0, *p;
107 struct disklabel *dlp;
108 struct buf *bp = NULL;
109 int error, i;
110
111 /* get a buffer and initialize it */
112 bp = geteblk(lp->d_secsize);
113 bp->b_dev = dev;
114
115 error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, LABELSECTOR));
116 if (error)
117 goto done;
118
119 /* Write it in the regular place. */
120 dlp = (struct disklabel *)(bp->b_data + LABELOFFSET);
121 *dlp = *lp;
122
123 /* Alpha bootblocks require a checksum over the sector */
124 for (i = 0, p = (u_int64_t *)bp->b_data; i < 63; i++)
125 csum += *p++;
126 *p = csum;
127
128 CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
129 SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW);
130 (*strat)(bp);
131 error = biowait(bp);
132
133 done:
134 if (bp) {
135 bp->b_flags |= B_INVAL;
136 brelse(bp);
137 }
138 disk_change = 1;
139 return (error);
140 }
141