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