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 93776 2002-04-04 09:54:13Z phk $
|
35 * $FreeBSD: head/sys/geom/geom_mbr.c 94287 2002-04-09 15:43:32Z 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/errno.h> 56#include <sys/disklabel.h> 57#include <sys/sbuf.h> 58#include <geom/geom.h> 59#include <geom/geom_slice.h> 60 61#define MBR_CLASS_NAME "MBR-class" 62#define MBREXT_CLASS_NAME "MBREXT-class" 63 64static void 65g_dec_dos_partition(u_char *ptr, struct dos_partition *d) 66{ 67 68 d->dp_flag = ptr[0]; 69 d->dp_shd = ptr[1]; 70 d->dp_ssect = ptr[2]; 71 d->dp_scyl = ptr[3]; 72 d->dp_typ = ptr[4]; 73 d->dp_ehd = ptr[5]; 74 d->dp_esect = ptr[6]; 75 d->dp_ecyl = ptr[7]; 76 d->dp_start = g_dec_le4(ptr + 8); 77 d->dp_size = g_dec_le4(ptr + 12); 78} 79 80#if 0 81static void 82g_enc_dos_partition(u_char *ptr, struct dos_partition *d) 83{ 84 85 ptr[0] = d->dp_flag; 86 ptr[1] = d->dp_shd; 87 ptr[2] = d->dp_ssect; 88 ptr[3] = d->dp_scyl; 89 ptr[4] = d->dp_typ; 90 ptr[5] = d->dp_ehd; 91 ptr[6] = d->dp_esect; 92 ptr[7] = d->dp_ecyl; 93 g_enc_le4(ptr + 8, d->dp_start); 94 g_enc_le4(ptr + 12, d->dp_size); 95} 96#endif 97 98struct g_mbr_softc { 99 int type [NDOSPART]; 100 struct dos_partition dospart[NDOSPART]; 101}; 102 103static int 104g_mbr_start(struct bio *bp) 105{ 106 struct g_provider *pp; 107 struct g_geom *gp; 108 struct g_mbr_softc *mp; 109 struct g_slicer *gsp; 110 int index; 111 112 pp = bp->bio_to; 113 index = pp->index; 114 gp = pp->geom; 115 gsp = gp->softc; 116 mp = gsp->softc; 117 if (bp->bio_cmd == BIO_GETATTR) { 118 if (g_haveattr_int(bp, "MBR::type", mp->type[index])) 119 return (1); 120 } 121 return (0); 122} 123 124static void 125g_mbr_dumpconf(struct sbuf *sb, char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp) 126{ 127 struct g_mbr_softc *mp; 128 struct g_slicer *gsp; 129 130 g_slice_dumpconf(sb, indent, gp, cp, pp); 131 gsp = gp->softc; 132 mp = gsp->softc; 133 if (pp != NULL) { 134 sbuf_printf(sb, "%s<type>%d</type>\n", 135 indent, mp->type[pp->index]); 136 } 137} 138 139 140static struct dos_partition historical_bogus_partition_table[NDOSPART] = { 141 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 142 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 143 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 144 { 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, }, 145}; 146static struct dos_partition historical_bogus_partition_table_fixed[NDOSPART] = { 147 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 148 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 149 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 150 { 0x80, 0, 1, 0, DOSPTYP_386BSD, 254, 255, 255, 0, 50000, }, 151}; 152 153static void 154g_mbr_print(int i __unused, struct dos_partition *dp __unused) 155{ 156 157#if 0 158 g_hexdump(dp, sizeof(dp[0])); 159 printf("[%d] f:%02x typ:%d", i, dp->dp_flag, dp->dp_typ); 160 printf(" s(CHS):%d/%d/%d", dp->dp_scyl, dp->dp_shd, dp->dp_ssect); 161 printf(" e(CHS):%d/%d/%d", dp->dp_ecyl, dp->dp_ehd, dp->dp_esect); 162 printf(" s:%d l:%d\n", dp->dp_start, dp->dp_size); 163#endif 164} 165 166static struct g_geom * 167g_mbr_taste(struct g_class *mp, struct g_provider *pp, int insist) 168{ 169 struct g_geom *gp; 170 struct g_consumer *cp; 171 struct g_provider *pp2;
|
172 int error, i, j, npart;
|
172 int error, i, npart; |
173 struct dos_partition dp[NDOSPART]; 174 struct g_mbr_softc *ms;
|
175 struct g_slicer *gsp; 176 u_int fwsectors, sectorsize; |
177 u_char *buf; 178
|
177 if (sizeof(struct dos_partition) != 16) {
178 printf("WARNING: struct dos_partition compiles to %d bytes, should be 16.\n",
179 (int)sizeof(struct dos_partition));
180 return (NULL);
181 }
|
179 g_trace(G_T_TOPOLOGY, "mbr_taste(%s,%s)", mp->name, pp->name); 180 g_topology_assert(); 181 gp = g_slice_new(mp, NDOSPART, pp, &cp, &ms, sizeof *ms, g_mbr_start); 182 if (gp == NULL) 183 return (NULL);
|
184 gsp = gp->softc; |
185 g_topology_unlock(); 186 gp->dumpconf = g_mbr_dumpconf; 187 npart = 0; 188 while (1) { /* a trick to allow us to use break */ 189 if (gp->rank != 2 && insist == 0) 190 break;
|
193 j = sizeof i;
194 /* For now we only support 512 bytes sectors */
195 error = g_io_getattr("GEOM::sectorsize", cp, &j, &i);
196 if (!error && i != 512)
|
191 error = g_getattr("GEOM::fwsectors", cp, &fwsectors); 192 if (error) 193 fwsectors = 17; 194 error = g_getattr("GEOM::sectorsize", cp, §orsize); 195 if (error) |
196 break;
|
198 buf = g_read_data(cp, 0, 512, &error);
|
197 if (!error && sectorsize != 512) 198 break; 199 gsp->frontstuff = sectorsize * fwsectors; 200 buf = g_read_data(cp, 0, sectorsize, &error); |
201 if (buf == NULL || error != 0) 202 break; 203 if (buf[0x1fe] != 0x55 && buf[0x1ff] != 0xaa) { 204 g_free(buf); 205 break; 206 } 207 for (i = 0; i < NDOSPART; i++) 208 g_dec_dos_partition( 209 buf + DOSPARTOFF + i * sizeof(struct dos_partition), 210 dp + i); 211 g_free(buf); 212 if (bcmp(dp, historical_bogus_partition_table, 213 sizeof historical_bogus_partition_table) == 0) 214 break; 215 if (bcmp(dp, historical_bogus_partition_table_fixed, 216 sizeof historical_bogus_partition_table_fixed) == 0) 217 break; 218 npart = 0; 219 for (i = 0; i < NDOSPART; i++) { 220 if (dp[i].dp_flag != 0 && dp[i].dp_flag != 0x80) 221 continue; 222 if (dp[i].dp_size == 0) 223 continue; 224 g_mbr_print(i, dp + i); 225 npart++; 226 ms->type[i] = dp[i].dp_typ; 227 pp2 = g_slice_addslice(gp, i, 228 ((off_t)dp[i].dp_start) << 9ULL, 229 ((off_t)dp[i].dp_size) << 9ULL, 230 "%ss%d", gp->name, i + 1); 231 } 232 break; 233 } 234 g_topology_lock(); 235 error = g_access_rel(cp, -1, 0, 0); 236 if (npart > 0) { 237 LIST_FOREACH(pp, &gp->provider, provider) 238 g_error_provider(pp, 0); 239 return (gp); 240 } 241 g_std_spoiled(cp); 242 return (NULL); 243} 244 245 246static struct g_class g_mbr_class = { 247 MBR_CLASS_NAME, 248 g_mbr_taste, 249 NULL, 250 G_CLASS_INITSTUFF 251}; 252 253DECLARE_GEOM_CLASS(g_mbr_class, g_mbr); 254 255#define NDOSEXTPART 32 256struct g_mbrext_softc { 257 int type [NDOSEXTPART]; 258}; 259 260static int 261g_mbrext_start(struct bio *bp) 262{ 263 struct g_provider *pp; 264 struct g_geom *gp; 265 struct g_mbrext_softc *mp; 266 struct g_slicer *gsp; 267 int index; 268 269 pp = bp->bio_to; 270 index = pp->index; 271 gp = pp->geom; 272 gsp = gp->softc; 273 mp = gsp->softc; 274 if (bp->bio_cmd == BIO_GETATTR) { 275 if (g_haveattr_int(bp, "MBR::type", mp->type[index])) 276 return (1); 277 } 278 return (0); 279} 280 281static void 282g_mbrext_dumpconf(struct sbuf *sb, char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp) 283{ 284 struct g_mbrext_softc *mp; 285 struct g_slicer *gsp; 286 287 g_slice_dumpconf(sb, indent, gp, cp, pp); 288 gsp = gp->softc; 289 mp = gsp->softc; 290 if (pp != NULL) { 291 sbuf_printf(sb, "%s<type>%d</type>\n", 292 indent, mp->type[pp->index]); 293 } 294} 295 296static void 297g_mbrext_print(int i, struct dos_partition *dp) 298{ 299 g_hexdump(dp, sizeof(dp[0])); 300 printf("[%d] f:%02x typ:%d", i, dp->dp_flag, dp->dp_typ); 301 printf(" s(CHS):%d/%d/%d", dp->dp_scyl, dp->dp_shd, dp->dp_ssect); 302 printf(" e(CHS):%d/%d/%d", dp->dp_ecyl, dp->dp_ehd, dp->dp_esect); 303 printf(" s:%d l:%d\n", dp->dp_start, dp->dp_size); 304} 305 306static struct g_geom * 307g_mbrext_taste(struct g_class *mp, struct g_provider *pp, int insist __unused) 308{ 309 struct g_geom *gp; 310 struct g_consumer *cp; 311 struct g_provider *pp2;
|
310 int error, i, j, slice;
|
312 int error, i, slice; |
313 struct g_mbrext_softc *ms; 314 off_t off; 315 u_char *buf; 316 struct dos_partition dp[4];
|
317 u_int fwsectors, sectorsize; 318 struct g_slicer *gsp; |
319 320 g_trace(G_T_TOPOLOGY, "g_mbrext_taste(%s,%s)", mp->name, pp->name); 321 g_topology_assert(); 322 if (strcmp(pp->geom->class->name, MBR_CLASS_NAME)) 323 return (NULL); 324 gp = g_slice_new(mp, NDOSEXTPART, pp, &cp, &ms, sizeof *ms, g_mbrext_start); 325 if (gp == NULL) 326 return (NULL);
|
327 gsp = gp->softc; |
328 g_topology_unlock(); 329 gp->dumpconf = g_mbrext_dumpconf; 330 off = 0; 331 slice = 0; 332 while (1) { /* a trick to allow us to use break */
|
328 j = sizeof i;
329 error = g_io_getattr("MBR::type", cp, &j, &i);
|
333 error = g_getattr("MBR::type", cp, &i); |
334 if (error || i != DOSPTYP_EXT) 335 break;
|
336 error = g_getattr("GEOM::fwsectors", cp, &fwsectors); 337 if (error) 338 fwsectors = 17; 339 error = g_getattr("GEOM::sectorsize", cp, §orsize); 340 if (error) 341 break; 342 if (!error && sectorsize != 512) 343 break; 344 gsp->frontstuff = sectorsize * fwsectors; |
345 for (;;) {
|
333 buf = g_read_data(cp, off, DEV_BSIZE, &error);
|
346 buf = g_read_data(cp, off, sectorsize, &error); |
347 if (buf == NULL || error != 0) 348 break; 349 if (buf[0x1fe] != 0x55 && buf[0x1ff] != 0xaa) 350 break; 351 for (i = 0; i < NDOSPART; i++) 352 g_dec_dos_partition( 353 buf + DOSPARTOFF + i * sizeof(struct dos_partition), 354 dp + i); 355 g_free(buf); 356 g_mbrext_print(0, dp); 357 g_mbrext_print(1, dp + 1); 358 if (dp[0].dp_flag == 0 && dp[0].dp_size != 0) { 359 pp2 = g_slice_addslice(gp, slice, 360 (((off_t)dp[0].dp_start) << 9ULL) + off, 361 ((off_t)dp[0].dp_size) << 9ULL, 362 "%*.*s%d", 363 strlen(gp->name) - 1, 364 strlen(gp->name) - 1, 365 gp->name, 366 slice + 5); 367 ms->type[slice] = dp[0].dp_typ; 368 slice++; 369 g_error_provider(pp2, 0); 370 } 371 if (dp[1].dp_flag != 0) 372 break; 373 if (dp[1].dp_typ != DOSPTYP_EXT) 374 break; 375 if (dp[1].dp_size == 0) 376 break; 377 off = ((off_t)dp[1].dp_start) << 9ULL; 378 } 379 break; 380 } 381 g_topology_lock(); 382 error = g_access_rel(cp, -1, 0, 0); 383 if (slice > 0) 384 return (gp); 385 386 g_topology_assert(); 387 g_std_spoiled(cp); 388 g_topology_assert(); 389 return (NULL); 390} 391 392 393static struct g_class g_mbrext_class = { 394 MBREXT_CLASS_NAME, 395 g_mbrext_taste, 396 NULL, 397 G_CLASS_INITSTUFF 398}; 399 400DECLARE_GEOM_CLASS(g_mbrext_class, g_mbrext);
|