Deleted Added
full compact
geom_mbr.c (105542) geom_mbr.c (105551)
1/*-
2 * Copyright (c) 2002 Poul-Henning Kamp
3 * Copyright (c) 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7 * and NAI Labs, the Security Research Division of Network Associates, Inc.
8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9 * DARPA CHATS research program.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The names of the authors may not be used to endorse or promote
20 * products derived from this software without specific prior written
21 * permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
1/*-
2 * Copyright (c) 2002 Poul-Henning Kamp
3 * Copyright (c) 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7 * and NAI Labs, the Security Research Division of Network Associates, Inc.
8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9 * DARPA CHATS research program.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The names of the authors may not be used to endorse or promote
20 * products derived from this software without specific prior written
21 * permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * $FreeBSD: head/sys/geom/geom_mbr.c 105542 2002-10-20 19:18:07Z phk $
35 * $FreeBSD: head/sys/geom/geom_mbr.c 105551 2002-10-20 20:28:24Z phk $
36 */
37
38#include <sys/param.h>
39#ifndef _KERNEL
40#include <stdio.h>
41#include <string.h>
42#include <signal.h>
43#include <sys/param.h>
44#include <stdlib.h>
45#include <err.h>
46#else
47#include <sys/systm.h>
48#include <sys/kernel.h>
49#include <sys/malloc.h>
50#include <sys/bio.h>
51#include <sys/lock.h>
52#include <sys/mutex.h>
53#endif
54
55#include <sys/diskmbr.h>
56#include <sys/sbuf.h>
57#include <geom/geom.h>
58#include <geom/geom_slice.h>
59
60#define GEOM_GPT
61
62#define MBR_CLASS_NAME "MBR"
63#define MBREXT_CLASS_NAME "MBREXT"
64
65static void
66g_dec_dos_partition(u_char *ptr, struct dos_partition *d)
67{
68
69 d->dp_flag = ptr[0];
70 d->dp_shd = ptr[1];
71 d->dp_ssect = ptr[2];
72 d->dp_scyl = ptr[3];
73 d->dp_typ = ptr[4];
74 d->dp_ehd = ptr[5];
75 d->dp_esect = ptr[6];
76 d->dp_ecyl = ptr[7];
77 d->dp_start = g_dec_le4(ptr + 8);
78 d->dp_size = g_dec_le4(ptr + 12);
79}
80
81#if 0
82static void
83g_enc_dos_partition(u_char *ptr, struct dos_partition *d)
84{
85
86 ptr[0] = d->dp_flag;
87 ptr[1] = d->dp_shd;
88 ptr[2] = d->dp_ssect;
89 ptr[3] = d->dp_scyl;
90 ptr[4] = d->dp_typ;
91 ptr[5] = d->dp_ehd;
92 ptr[6] = d->dp_esect;
93 ptr[7] = d->dp_ecyl;
94 g_enc_le4(ptr + 8, d->dp_start);
95 g_enc_le4(ptr + 12, d->dp_size);
96}
97#endif
98
99struct g_mbr_softc {
100 int type [NDOSPART];
101 struct dos_partition dospart[NDOSPART];
102};
103
104static int
105g_mbr_start(struct bio *bp)
106{
107 struct g_provider *pp;
108 struct g_geom *gp;
109 struct g_mbr_softc *mp;
110 struct g_slicer *gsp;
111 int index;
112
113 pp = bp->bio_to;
114 index = pp->index;
115 gp = pp->geom;
116 gsp = gp->softc;
117 mp = gsp->softc;
118 if (bp->bio_cmd == BIO_GETATTR) {
119 if (g_handleattr_int(bp, "MBR::type", mp->type[index]))
120 return (1);
121 }
122 return (0);
123}
124
125static void
126g_mbr_dumpconf(struct sbuf *sb, char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp)
127{
128 struct g_mbr_softc *mp;
129 struct g_slicer *gsp;
130
131 g_slice_dumpconf(sb, indent, gp, cp, pp);
132 gsp = gp->softc;
133 mp = gsp->softc;
134 if (pp != NULL) {
135 sbuf_printf(sb, "%s<type>%d</type>\n",
136 indent, mp->type[pp->index]);
137 }
138}
139
140
141static struct dos_partition historical_bogus_partition_table[NDOSPART] = {
142 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
143 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
144 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
145 { 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, },
146};
147static struct dos_partition historical_bogus_partition_table_fixed[NDOSPART] = {
148 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
149 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
150 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
151 { 0x80, 0, 1, 0, DOSPTYP_386BSD, 254, 255, 255, 0, 50000, },
152};
153
154static void
155g_mbr_print(int i __unused, struct dos_partition *dp __unused)
156{
157
158#if 0
159 g_hexdump(dp, sizeof(dp[0]));
160 printf("[%d] f:%02x typ:%d", i, dp->dp_flag, dp->dp_typ);
161 printf(" s(CHS):%d/%d/%d", dp->dp_scyl, dp->dp_shd, dp->dp_ssect);
162 printf(" e(CHS):%d/%d/%d", dp->dp_ecyl, dp->dp_ehd, dp->dp_esect);
163 printf(" s:%d l:%d\n", dp->dp_start, dp->dp_size);
164#endif
165}
166
167static struct g_geom *
168g_mbr_taste(struct g_class *mp, struct g_provider *pp, int insist)
169{
170 struct g_geom *gp;
171 struct g_consumer *cp;
172 struct g_provider *pp2;
173 int error, i, npart;
174 struct dos_partition dp[NDOSPART];
175 struct g_mbr_softc *ms;
176 struct g_slicer *gsp;
177 u_int fwsectors, sectorsize;
178 u_char *buf;
179
180 g_trace(G_T_TOPOLOGY, "mbr_taste(%s,%s)", mp->name, pp->name);
181 g_topology_assert();
182 gp = g_slice_new(mp, NDOSPART, pp, &cp, &ms, sizeof *ms, g_mbr_start);
183 if (gp == NULL)
184 return (NULL);
185 gsp = gp->softc;
186 g_topology_unlock();
187 gp->dumpconf = g_mbr_dumpconf;
188 npart = 0;
189 while (1) { /* a trick to allow us to use break */
190 if (gp->rank != 2 && insist == 0)
191 break;
192 error = g_getattr("GEOM::fwsectors", cp, &fwsectors);
193 if (error)
194 fwsectors = 17;
36 */
37
38#include <sys/param.h>
39#ifndef _KERNEL
40#include <stdio.h>
41#include <string.h>
42#include <signal.h>
43#include <sys/param.h>
44#include <stdlib.h>
45#include <err.h>
46#else
47#include <sys/systm.h>
48#include <sys/kernel.h>
49#include <sys/malloc.h>
50#include <sys/bio.h>
51#include <sys/lock.h>
52#include <sys/mutex.h>
53#endif
54
55#include <sys/diskmbr.h>
56#include <sys/sbuf.h>
57#include <geom/geom.h>
58#include <geom/geom_slice.h>
59
60#define GEOM_GPT
61
62#define MBR_CLASS_NAME "MBR"
63#define MBREXT_CLASS_NAME "MBREXT"
64
65static void
66g_dec_dos_partition(u_char *ptr, struct dos_partition *d)
67{
68
69 d->dp_flag = ptr[0];
70 d->dp_shd = ptr[1];
71 d->dp_ssect = ptr[2];
72 d->dp_scyl = ptr[3];
73 d->dp_typ = ptr[4];
74 d->dp_ehd = ptr[5];
75 d->dp_esect = ptr[6];
76 d->dp_ecyl = ptr[7];
77 d->dp_start = g_dec_le4(ptr + 8);
78 d->dp_size = g_dec_le4(ptr + 12);
79}
80
81#if 0
82static void
83g_enc_dos_partition(u_char *ptr, struct dos_partition *d)
84{
85
86 ptr[0] = d->dp_flag;
87 ptr[1] = d->dp_shd;
88 ptr[2] = d->dp_ssect;
89 ptr[3] = d->dp_scyl;
90 ptr[4] = d->dp_typ;
91 ptr[5] = d->dp_ehd;
92 ptr[6] = d->dp_esect;
93 ptr[7] = d->dp_ecyl;
94 g_enc_le4(ptr + 8, d->dp_start);
95 g_enc_le4(ptr + 12, d->dp_size);
96}
97#endif
98
99struct g_mbr_softc {
100 int type [NDOSPART];
101 struct dos_partition dospart[NDOSPART];
102};
103
104static int
105g_mbr_start(struct bio *bp)
106{
107 struct g_provider *pp;
108 struct g_geom *gp;
109 struct g_mbr_softc *mp;
110 struct g_slicer *gsp;
111 int index;
112
113 pp = bp->bio_to;
114 index = pp->index;
115 gp = pp->geom;
116 gsp = gp->softc;
117 mp = gsp->softc;
118 if (bp->bio_cmd == BIO_GETATTR) {
119 if (g_handleattr_int(bp, "MBR::type", mp->type[index]))
120 return (1);
121 }
122 return (0);
123}
124
125static void
126g_mbr_dumpconf(struct sbuf *sb, char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp)
127{
128 struct g_mbr_softc *mp;
129 struct g_slicer *gsp;
130
131 g_slice_dumpconf(sb, indent, gp, cp, pp);
132 gsp = gp->softc;
133 mp = gsp->softc;
134 if (pp != NULL) {
135 sbuf_printf(sb, "%s<type>%d</type>\n",
136 indent, mp->type[pp->index]);
137 }
138}
139
140
141static struct dos_partition historical_bogus_partition_table[NDOSPART] = {
142 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
143 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
144 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
145 { 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, },
146};
147static struct dos_partition historical_bogus_partition_table_fixed[NDOSPART] = {
148 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
149 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
150 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
151 { 0x80, 0, 1, 0, DOSPTYP_386BSD, 254, 255, 255, 0, 50000, },
152};
153
154static void
155g_mbr_print(int i __unused, struct dos_partition *dp __unused)
156{
157
158#if 0
159 g_hexdump(dp, sizeof(dp[0]));
160 printf("[%d] f:%02x typ:%d", i, dp->dp_flag, dp->dp_typ);
161 printf(" s(CHS):%d/%d/%d", dp->dp_scyl, dp->dp_shd, dp->dp_ssect);
162 printf(" e(CHS):%d/%d/%d", dp->dp_ecyl, dp->dp_ehd, dp->dp_esect);
163 printf(" s:%d l:%d\n", dp->dp_start, dp->dp_size);
164#endif
165}
166
167static struct g_geom *
168g_mbr_taste(struct g_class *mp, struct g_provider *pp, int insist)
169{
170 struct g_geom *gp;
171 struct g_consumer *cp;
172 struct g_provider *pp2;
173 int error, i, npart;
174 struct dos_partition dp[NDOSPART];
175 struct g_mbr_softc *ms;
176 struct g_slicer *gsp;
177 u_int fwsectors, sectorsize;
178 u_char *buf;
179
180 g_trace(G_T_TOPOLOGY, "mbr_taste(%s,%s)", mp->name, pp->name);
181 g_topology_assert();
182 gp = g_slice_new(mp, NDOSPART, pp, &cp, &ms, sizeof *ms, g_mbr_start);
183 if (gp == NULL)
184 return (NULL);
185 gsp = gp->softc;
186 g_topology_unlock();
187 gp->dumpconf = g_mbr_dumpconf;
188 npart = 0;
189 while (1) { /* a trick to allow us to use break */
190 if (gp->rank != 2 && insist == 0)
191 break;
192 error = g_getattr("GEOM::fwsectors", cp, &fwsectors);
193 if (error)
194 fwsectors = 17;
195 error = g_getattr("GEOM::sectorsize", cp, &sectorsize);
196 if (error)
197 break;
195 sectorsize = cp->provider->sectorsize;
198 if (sectorsize != 512)
199 break;
200 gsp->frontstuff = sectorsize * fwsectors;
201#ifdef GEOM_GPT
202 /*
203 * XXX: GPT hack: Read the second sector as well and back-off
204 * if it has the GPT signature. The ultimate behaviour would
205 * be to back-off if we detect a protective MBR (PMBR).
206 */
207 buf = g_read_data(cp, 0, 2 * sectorsize, &error);
208#else
209 buf = g_read_data(cp, 0, sectorsize, &error);
210#endif
211 if (buf == NULL || error != 0)
212 break;
213 if (buf[0x1fe] != 0x55 && buf[0x1ff] != 0xaa) {
214 g_free(buf);
215 break;
216 }
217#ifdef GEOM_GPT
218 if (!memcmp(buf + 512, "EFI PART", 8)) {
219 g_free(buf);
220 break;
221 }
222#endif
223 for (i = 0; i < NDOSPART; i++)
224 g_dec_dos_partition(
225 buf + DOSPARTOFF + i * sizeof(struct dos_partition),
226 dp + i);
227 g_free(buf);
228 if (bcmp(dp, historical_bogus_partition_table,
229 sizeof historical_bogus_partition_table) == 0)
230 break;
231 if (bcmp(dp, historical_bogus_partition_table_fixed,
232 sizeof historical_bogus_partition_table_fixed) == 0)
233 break;
234 npart = 0;
235 for (i = 0; i < NDOSPART; i++) {
236 if (dp[i].dp_flag != 0 && dp[i].dp_flag != 0x80)
237 continue;
238 if (dp[i].dp_size == 0)
239 continue;
240 g_mbr_print(i, dp + i);
241 npart++;
242 ms->type[i] = dp[i].dp_typ;
243 g_topology_lock();
244 pp2 = g_slice_addslice(gp, i,
245 (off_t)dp[i].dp_start << 9ULL,
246 (off_t)dp[i].dp_size << 9ULL,
247 sectorsize,
248 "%ss%d", gp->name, i + 1);
249 g_topology_unlock();
250 }
251 break;
252 }
253 g_topology_lock();
254 error = g_access_rel(cp, -1, 0, 0);
255 if (npart > 0) {
256 LIST_FOREACH(pp, &gp->provider, provider)
257 g_error_provider(pp, 0);
258 return (gp);
259 }
260 g_std_spoiled(cp);
261 return (NULL);
262}
263
264
265static struct g_class g_mbr_class = {
266 MBR_CLASS_NAME,
267 g_mbr_taste,
268 NULL,
269 G_CLASS_INITIALIZER
270};
271
272DECLARE_GEOM_CLASS(g_mbr_class, g_mbr);
273
274#define NDOSEXTPART 32
275struct g_mbrext_softc {
276 int type [NDOSEXTPART];
277};
278
279static int
280g_mbrext_start(struct bio *bp)
281{
282 struct g_provider *pp;
283 struct g_geom *gp;
284 struct g_mbrext_softc *mp;
285 struct g_slicer *gsp;
286 int index;
287
288 pp = bp->bio_to;
289 index = pp->index;
290 gp = pp->geom;
291 gsp = gp->softc;
292 mp = gsp->softc;
293 if (bp->bio_cmd == BIO_GETATTR) {
294 if (g_handleattr_int(bp, "MBR::type", mp->type[index]))
295 return (1);
296 }
297 return (0);
298}
299
300static void
301g_mbrext_dumpconf(struct sbuf *sb, char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp)
302{
303 struct g_mbrext_softc *mp;
304 struct g_slicer *gsp;
305
306 g_slice_dumpconf(sb, indent, gp, cp, pp);
307 gsp = gp->softc;
308 mp = gsp->softc;
309 if (pp != NULL) {
310 sbuf_printf(sb, "%s<type>%d</type>\n",
311 indent, mp->type[pp->index]);
312 }
313}
314
315static void
316g_mbrext_print(int i, struct dos_partition *dp)
317{
318 g_hexdump(dp, sizeof(dp[0]));
319 printf("[%d] f:%02x typ:%d", i, dp->dp_flag, dp->dp_typ);
320 printf(" s(CHS):%d/%d/%d", dp->dp_scyl, dp->dp_shd, dp->dp_ssect);
321 printf(" e(CHS):%d/%d/%d", dp->dp_ecyl, dp->dp_ehd, dp->dp_esect);
322 printf(" s:%d l:%d\n", dp->dp_start, dp->dp_size);
323}
324
325static struct g_geom *
326g_mbrext_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
327{
328 struct g_geom *gp;
329 struct g_consumer *cp;
330 struct g_provider *pp2;
331 int error, i, slice;
332 struct g_mbrext_softc *ms;
333 off_t off;
334 u_char *buf;
335 struct dos_partition dp[4];
336 u_int fwsectors, sectorsize;
337 struct g_slicer *gsp;
338
339 g_trace(G_T_TOPOLOGY, "g_mbrext_taste(%s,%s)", mp->name, pp->name);
340 g_topology_assert();
341 if (strcmp(pp->geom->class->name, MBR_CLASS_NAME))
342 return (NULL);
343 gp = g_slice_new(mp, NDOSEXTPART, pp, &cp, &ms, sizeof *ms, g_mbrext_start);
344 if (gp == NULL)
345 return (NULL);
346 gsp = gp->softc;
347 g_topology_unlock();
348 gp->dumpconf = g_mbrext_dumpconf;
349 off = 0;
350 slice = 0;
351 while (1) { /* a trick to allow us to use break */
352 error = g_getattr("MBR::type", cp, &i);
353 if (error || (i != DOSPTYP_EXT && i != DOSPTYP_EXTLBA))
354 break;
355 error = g_getattr("GEOM::fwsectors", cp, &fwsectors);
356 if (error)
357 fwsectors = 17;
196 if (sectorsize != 512)
197 break;
198 gsp->frontstuff = sectorsize * fwsectors;
199#ifdef GEOM_GPT
200 /*
201 * XXX: GPT hack: Read the second sector as well and back-off
202 * if it has the GPT signature. The ultimate behaviour would
203 * be to back-off if we detect a protective MBR (PMBR).
204 */
205 buf = g_read_data(cp, 0, 2 * sectorsize, &error);
206#else
207 buf = g_read_data(cp, 0, sectorsize, &error);
208#endif
209 if (buf == NULL || error != 0)
210 break;
211 if (buf[0x1fe] != 0x55 && buf[0x1ff] != 0xaa) {
212 g_free(buf);
213 break;
214 }
215#ifdef GEOM_GPT
216 if (!memcmp(buf + 512, "EFI PART", 8)) {
217 g_free(buf);
218 break;
219 }
220#endif
221 for (i = 0; i < NDOSPART; i++)
222 g_dec_dos_partition(
223 buf + DOSPARTOFF + i * sizeof(struct dos_partition),
224 dp + i);
225 g_free(buf);
226 if (bcmp(dp, historical_bogus_partition_table,
227 sizeof historical_bogus_partition_table) == 0)
228 break;
229 if (bcmp(dp, historical_bogus_partition_table_fixed,
230 sizeof historical_bogus_partition_table_fixed) == 0)
231 break;
232 npart = 0;
233 for (i = 0; i < NDOSPART; i++) {
234 if (dp[i].dp_flag != 0 && dp[i].dp_flag != 0x80)
235 continue;
236 if (dp[i].dp_size == 0)
237 continue;
238 g_mbr_print(i, dp + i);
239 npart++;
240 ms->type[i] = dp[i].dp_typ;
241 g_topology_lock();
242 pp2 = g_slice_addslice(gp, i,
243 (off_t)dp[i].dp_start << 9ULL,
244 (off_t)dp[i].dp_size << 9ULL,
245 sectorsize,
246 "%ss%d", gp->name, i + 1);
247 g_topology_unlock();
248 }
249 break;
250 }
251 g_topology_lock();
252 error = g_access_rel(cp, -1, 0, 0);
253 if (npart > 0) {
254 LIST_FOREACH(pp, &gp->provider, provider)
255 g_error_provider(pp, 0);
256 return (gp);
257 }
258 g_std_spoiled(cp);
259 return (NULL);
260}
261
262
263static struct g_class g_mbr_class = {
264 MBR_CLASS_NAME,
265 g_mbr_taste,
266 NULL,
267 G_CLASS_INITIALIZER
268};
269
270DECLARE_GEOM_CLASS(g_mbr_class, g_mbr);
271
272#define NDOSEXTPART 32
273struct g_mbrext_softc {
274 int type [NDOSEXTPART];
275};
276
277static int
278g_mbrext_start(struct bio *bp)
279{
280 struct g_provider *pp;
281 struct g_geom *gp;
282 struct g_mbrext_softc *mp;
283 struct g_slicer *gsp;
284 int index;
285
286 pp = bp->bio_to;
287 index = pp->index;
288 gp = pp->geom;
289 gsp = gp->softc;
290 mp = gsp->softc;
291 if (bp->bio_cmd == BIO_GETATTR) {
292 if (g_handleattr_int(bp, "MBR::type", mp->type[index]))
293 return (1);
294 }
295 return (0);
296}
297
298static void
299g_mbrext_dumpconf(struct sbuf *sb, char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp)
300{
301 struct g_mbrext_softc *mp;
302 struct g_slicer *gsp;
303
304 g_slice_dumpconf(sb, indent, gp, cp, pp);
305 gsp = gp->softc;
306 mp = gsp->softc;
307 if (pp != NULL) {
308 sbuf_printf(sb, "%s<type>%d</type>\n",
309 indent, mp->type[pp->index]);
310 }
311}
312
313static void
314g_mbrext_print(int i, struct dos_partition *dp)
315{
316 g_hexdump(dp, sizeof(dp[0]));
317 printf("[%d] f:%02x typ:%d", i, dp->dp_flag, dp->dp_typ);
318 printf(" s(CHS):%d/%d/%d", dp->dp_scyl, dp->dp_shd, dp->dp_ssect);
319 printf(" e(CHS):%d/%d/%d", dp->dp_ecyl, dp->dp_ehd, dp->dp_esect);
320 printf(" s:%d l:%d\n", dp->dp_start, dp->dp_size);
321}
322
323static struct g_geom *
324g_mbrext_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
325{
326 struct g_geom *gp;
327 struct g_consumer *cp;
328 struct g_provider *pp2;
329 int error, i, slice;
330 struct g_mbrext_softc *ms;
331 off_t off;
332 u_char *buf;
333 struct dos_partition dp[4];
334 u_int fwsectors, sectorsize;
335 struct g_slicer *gsp;
336
337 g_trace(G_T_TOPOLOGY, "g_mbrext_taste(%s,%s)", mp->name, pp->name);
338 g_topology_assert();
339 if (strcmp(pp->geom->class->name, MBR_CLASS_NAME))
340 return (NULL);
341 gp = g_slice_new(mp, NDOSEXTPART, pp, &cp, &ms, sizeof *ms, g_mbrext_start);
342 if (gp == NULL)
343 return (NULL);
344 gsp = gp->softc;
345 g_topology_unlock();
346 gp->dumpconf = g_mbrext_dumpconf;
347 off = 0;
348 slice = 0;
349 while (1) { /* a trick to allow us to use break */
350 error = g_getattr("MBR::type", cp, &i);
351 if (error || (i != DOSPTYP_EXT && i != DOSPTYP_EXTLBA))
352 break;
353 error = g_getattr("GEOM::fwsectors", cp, &fwsectors);
354 if (error)
355 fwsectors = 17;
358 error = g_getattr("GEOM::sectorsize", cp, &sectorsize);
359 if (error)
360 break;
356 sectorsize = cp->provider->sectorsize;
361 if (sectorsize != 512)
362 break;
363 gsp->frontstuff = sectorsize * fwsectors;
364 for (;;) {
365 buf = g_read_data(cp, off, sectorsize, &error);
366 if (buf == NULL || error != 0)
367 break;
368 if (buf[0x1fe] != 0x55 && buf[0x1ff] != 0xaa)
369 break;
370 for (i = 0; i < NDOSPART; i++)
371 g_dec_dos_partition(
372 buf + DOSPARTOFF + i * sizeof(struct dos_partition),
373 dp + i);
374 g_free(buf);
375 g_mbrext_print(0, dp);
376 g_mbrext_print(1, dp + 1);
377 if (dp[0].dp_flag == 0 && dp[0].dp_size != 0) {
378 g_topology_lock();
379 pp2 = g_slice_addslice(gp, slice,
380 (((off_t)dp[0].dp_start) << 9ULL) + off,
381 ((off_t)dp[0].dp_size) << 9ULL,
382 sectorsize,
383 "%*.*s%d",
384 strlen(gp->name) - 1,
385 strlen(gp->name) - 1,
386 gp->name,
387 slice + 5);
388 g_topology_unlock();
389 ms->type[slice] = dp[0].dp_typ;
390 slice++;
391 g_error_provider(pp2, 0);
392 }
393 if (dp[1].dp_flag != 0)
394 break;
395 if (dp[1].dp_typ != DOSPTYP_EXT)
396 break;
397 if (dp[1].dp_size == 0)
398 break;
399 off = ((off_t)dp[1].dp_start) << 9ULL;
400 }
401 break;
402 }
403 g_topology_lock();
404 error = g_access_rel(cp, -1, 0, 0);
405 if (slice > 0) {
406 /* XXX: add magic spaces */
407 return (gp);
408 }
409
410 g_topology_assert();
411 g_std_spoiled(cp);
412 g_topology_assert();
413 return (NULL);
414}
415
416
417static struct g_class g_mbrext_class = {
418 MBREXT_CLASS_NAME,
419 g_mbrext_taste,
420 NULL,
421 G_CLASS_INITIALIZER
422};
423
424DECLARE_GEOM_CLASS(g_mbrext_class, g_mbrext);
357 if (sectorsize != 512)
358 break;
359 gsp->frontstuff = sectorsize * fwsectors;
360 for (;;) {
361 buf = g_read_data(cp, off, sectorsize, &error);
362 if (buf == NULL || error != 0)
363 break;
364 if (buf[0x1fe] != 0x55 && buf[0x1ff] != 0xaa)
365 break;
366 for (i = 0; i < NDOSPART; i++)
367 g_dec_dos_partition(
368 buf + DOSPARTOFF + i * sizeof(struct dos_partition),
369 dp + i);
370 g_free(buf);
371 g_mbrext_print(0, dp);
372 g_mbrext_print(1, dp + 1);
373 if (dp[0].dp_flag == 0 && dp[0].dp_size != 0) {
374 g_topology_lock();
375 pp2 = g_slice_addslice(gp, slice,
376 (((off_t)dp[0].dp_start) << 9ULL) + off,
377 ((off_t)dp[0].dp_size) << 9ULL,
378 sectorsize,
379 "%*.*s%d",
380 strlen(gp->name) - 1,
381 strlen(gp->name) - 1,
382 gp->name,
383 slice + 5);
384 g_topology_unlock();
385 ms->type[slice] = dp[0].dp_typ;
386 slice++;
387 g_error_provider(pp2, 0);
388 }
389 if (dp[1].dp_flag != 0)
390 break;
391 if (dp[1].dp_typ != DOSPTYP_EXT)
392 break;
393 if (dp[1].dp_size == 0)
394 break;
395 off = ((off_t)dp[1].dp_start) << 9ULL;
396 }
397 break;
398 }
399 g_topology_lock();
400 error = g_access_rel(cp, -1, 0, 0);
401 if (slice > 0) {
402 /* XXX: add magic spaces */
403 return (gp);
404 }
405
406 g_topology_assert();
407 g_std_spoiled(cp);
408 g_topology_assert();
409 return (NULL);
410}
411
412
413static struct g_class g_mbrext_class = {
414 MBREXT_CLASS_NAME,
415 g_mbrext_taste,
416 NULL,
417 G_CLASS_INITIALIZER
418};
419
420DECLARE_GEOM_CLASS(g_mbrext_class, g_mbrext);