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