1 /* $NetBSD: disksubr_mbr.c,v 1.18 2013/08/13 00:04:08 matt Exp $ */
2
3 /*
4 * Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Christopher G. Demetriou
17 * for the NetBSD Project.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
62 */
63
64 /*
65 * From i386 disklabel.c rev 1.29, with cleanups and modifications to
66 * make it easier to use on the arm32 and to use as MI code (not quite
67 * clean enough, yet).
68 */
69
70 #include <sys/cdefs.h>
71 __KERNEL_RCSID(0, "$NetBSD: disksubr_mbr.c,v 1.18 2013/08/13 00:04:08 matt Exp $");
72
73 #include <sys/param.h>
74 #include <sys/systm.h>
75 #include <sys/buf.h>
76 #include <sys/disklabel.h>
77
78 #include "opt_mbr.h"
79
80 #define MBRSIGOFS 0x1fe
81 static char mbrsig[2] = {0x55, 0xaa};
82
83 int
mbr_label_read(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,struct cpu_disklabel * osdep,const char ** msgp,int * cylp,int * netbsd_label_offp)84 mbr_label_read(dev_t dev,
85 void (*strat)(struct buf *),
86 struct disklabel *lp,
87 struct cpu_disklabel *osdep,
88 const char **msgp,
89 int *cylp, int *netbsd_label_offp)
90 {
91 struct mbr_partition *mbrp;
92 struct partition *pp;
93 int cyl, mbrpartoff, i;
94 struct buf *bp;
95 int rv = 1;
96
97 /* get a buffer and initialize it */
98 bp = geteblk((int)lp->d_secsize);
99 bp->b_dev = dev;
100
101 /* In case nothing sets them */
102 mbrpartoff = 0;
103 cyl = LABELSECTOR / lp->d_secpercyl;
104
105 mbrp = osdep->mbrparts;
106
107 /* read master boot record */
108 bp->b_blkno = MBR_BBSECTOR;
109 bp->b_bcount = lp->d_secsize;
110 bp->b_flags |= B_READ;
111 bp->b_cylinder = MBR_BBSECTOR / lp->d_secpercyl;
112 (*strat)(bp);
113
114 /* if successful, wander through dos partition table */
115 if (biowait(bp)) {
116 *msgp = "dos partition I/O error";
117 goto out;
118 } else {
119 struct mbr_partition *ourmbrp = NULL;
120 int nfound = 0;
121
122 /* XXX "there has to be a better check than this." */
123 if (memcmp((char *)bp->b_data + MBRSIGOFS, mbrsig,
124 sizeof(mbrsig))) {
125 rv = 0;
126 goto out;
127 }
128
129 /* XXX how do we check veracity/bounds of this? */
130 memcpy(mbrp, (char *)bp->b_data + MBR_PART_OFFSET,
131 MBR_PART_COUNT * sizeof(*mbrp));
132
133 /* look for NetBSD partition */
134 ourmbrp = NULL;
135 for (i = 0; !ourmbrp && i < MBR_PART_COUNT; i++) {
136 if (mbrp[i].mbrp_type == MBR_PTYPE_NETBSD)
137 ourmbrp = &mbrp[i];
138 }
139 #ifdef COMPAT_386BSD_MBRPART
140 /* didn't find it -- look for 386BSD partition */
141 for (i = 0; !ourmbrp && i < MBR_PART_COUNT; i++) {
142 if (mbrp[i].mbrp_type == MBR_PTYPE_386BSD) {
143 printf("WARNING: old BSD partition ID!\n");
144 ourmbrp = &mbrp[i];
145 break;
146 }
147 }
148 #endif
149 pp = &lp->d_partitions['e' - 'a'];
150 for (i = 0; i < MBR_PART_COUNT; i++, mbrp++, pp++) {
151 if ((i == 0 && mbrp->mbrp_type == MBR_PTYPE_PMBR)
152 || mbrp->mbrp_type == MBR_PTYPE_UNUSED) {
153 memset(pp, 0, sizeof(*pp));
154 continue;
155 }
156 if (le32toh(mbrp->mbrp_start) +
157 le32toh(mbrp->mbrp_size) > lp->d_secperunit) {
158 /* This mbr doesn't look good.... */
159 memset(pp, 0, sizeof(*pp));
160 continue;
161 }
162 nfound++;
163
164 /* Install in partition e, f, g, or h. */
165 pp->p_offset = le32toh(mbrp->mbrp_start);
166 pp->p_size = le32toh(mbrp->mbrp_size);
167 pp->p_fstype = xlat_mbr_fstype(mbrp->mbrp_type);
168
169 /* is this ours? */
170 if (mbrp != ourmbrp)
171 continue;
172
173 /* need sector address for SCSI/IDE,
174 cylinder for ESDI/ST506/RLL */
175 mbrpartoff = le32toh(mbrp->mbrp_start);
176 cyl = MBR_PCYL(mbrp->mbrp_scyl, mbrp->mbrp_ssect);
177
178 #ifdef __i386__ /* XXX? */
179 /* update disklabel with details */
180 lp->d_partitions[2].p_size = le32toh(mbrp->mbrp_size);
181 lp->d_partitions[2].p_offset =
182 le32toh(mbrp->mbrp_start);
183 lp->d_ntracks = mbrp->mbrp_ehd + 1;
184 lp->d_nsectors = MBR_PSECT(mbrp->mbrp_esect);
185 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
186 #endif
187 }
188 i += 'e' - 'a';
189 if (nfound > 0) {
190 lp->d_npartitions = i;
191 strncpy(lp->d_packname, "fictitious-MBR",
192 sizeof lp->d_packname);
193 }
194 if (lp->d_npartitions < MAXPARTITIONS) {
195 memset(pp, 0, (MAXPARTITIONS - i) * sizeof(*pp));
196 }
197 }
198
199 *cylp = cyl;
200 *netbsd_label_offp = mbrpartoff;
201 *msgp = NULL;
202 out:
203 brelse(bp, 0);
204 return (rv);
205 }
206
207 /*
208 * Return -1 not found, 0 found positive errno
209 */
210 int
mbr_label_locate(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,struct cpu_disklabel * osdep,int * cylp,int * netbsd_label_offp)211 mbr_label_locate(dev_t dev,
212 void (*strat)(struct buf *),
213 struct disklabel *lp,
214 struct cpu_disklabel *osdep,
215 int *cylp, int *netbsd_label_offp)
216 {
217 struct mbr_partition *mbrp;
218 int cyl, mbrpartoff, i;
219 struct mbr_partition *ourmbrp = NULL;
220 struct buf *bp;
221 int rv;
222
223 /* get a buffer and initialize it */
224 bp = geteblk((int)lp->d_secsize);
225 bp->b_dev = dev;
226
227 /* do MBR partitions in the process of getting disklabel? */
228 mbrpartoff = 0;
229 cyl = LABELSECTOR / lp->d_secpercyl;
230
231 mbrp = osdep->mbrparts;
232
233 /* read master boot record */
234 bp->b_blkno = MBR_BBSECTOR;
235 bp->b_bcount = lp->d_secsize;
236 bp->b_flags |= B_READ;
237 bp->b_cylinder = MBR_BBSECTOR / lp->d_secpercyl;
238 (*strat)(bp);
239
240 if ((rv = biowait(bp)) != 0) {
241 goto out;
242 }
243
244 if (memcmp((char *)bp->b_data + MBRSIGOFS, mbrsig, sizeof(mbrsig))) {
245 rv = 0;
246 goto out;
247 }
248
249 /* XXX how do we check veracity/bounds of this? */
250 memcpy(mbrp, (char *)bp->b_data + MBR_PART_OFFSET,
251 MBR_PART_COUNT * sizeof(*mbrp));
252
253 /* look for NetBSD partition */
254 ourmbrp = NULL;
255 for (i = 0; !ourmbrp && i < MBR_PART_COUNT; i++) {
256 if (mbrp[i].mbrp_type == MBR_PTYPE_NETBSD)
257 ourmbrp = &mbrp[i];
258 }
259 #ifdef COMPAT_386BSD_MBRPART
260 /* didn't find it -- look for 386BSD partition */
261 for (i = 0; !ourmbrp && i < MBR_PART_COUNT; i++) {
262 if (mbrp[i].mbrp_type == MBR_PTYPE_386BSD) {
263 printf("WARNING: old BSD partition ID!\n");
264 ourmbrp = &mbrp[i];
265 }
266 }
267 #endif
268 if (!ourmbrp) {
269 rv = 0; /* XXX allow easy clobber? */
270 goto out;
271 }
272
273 /* need sector address for SCSI/IDE, cylinder for ESDI/ST506/RLL */
274 mbrpartoff = le32toh(ourmbrp->mbrp_start);
275 cyl = MBR_PCYL(ourmbrp->mbrp_scyl, ourmbrp->mbrp_ssect);
276
277 *cylp = cyl;
278 *netbsd_label_offp = mbrpartoff;
279 rv = -1;
280 out:
281 brelse(bp, 0);
282 return (rv);
283 }
284