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, §orsize); 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, §orsize); 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);
|