192108Sphk/*- 292108Sphk * Copyright (c) 2002 Poul-Henning Kamp 392108Sphk * Copyright (c) 2002 Networks Associates Technology, Inc. 492108Sphk * All rights reserved. 592108Sphk * 692108Sphk * This software was developed for the FreeBSD Project by Poul-Henning Kamp 792108Sphk * and NAI Labs, the Security Research Division of Network Associates, Inc. 892108Sphk * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 992108Sphk * DARPA CHATS research program. 1092108Sphk * 1192108Sphk * Redistribution and use in source and binary forms, with or without 1292108Sphk * modification, are permitted provided that the following conditions 1392108Sphk * are met: 1492108Sphk * 1. Redistributions of source code must retain the above copyright 1592108Sphk * notice, this list of conditions and the following disclaimer. 1692108Sphk * 2. Redistributions in binary form must reproduce the above copyright 1792108Sphk * notice, this list of conditions and the following disclaimer in the 1892108Sphk * documentation and/or other materials provided with the distribution. 1992108Sphk * 2092108Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2192108Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2292108Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2392108Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2492108Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2592108Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2692108Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2792108Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2892108Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2992108Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3092108Sphk * SUCH DAMAGE. 3192108Sphk */ 3292108Sphk 33116196Sobrien#include <sys/cdefs.h> 34116196Sobrien__FBSDID("$FreeBSD: releng/10.3/sys/geom/geom_mbr.c 243333 2012-11-20 12:32:18Z jh $"); 35116196Sobrien 3692108Sphk#include <sys/param.h> 37107956Sphk#include <sys/errno.h> 38113011Sphk#include <sys/endian.h> 3992108Sphk#include <sys/systm.h> 40219029Snetchild#include <sys/sysctl.h> 4192108Sphk#include <sys/kernel.h> 42138732Sphk#include <sys/fcntl.h> 4392108Sphk#include <sys/malloc.h> 4492108Sphk#include <sys/bio.h> 4592108Sphk#include <sys/lock.h> 4692108Sphk#include <sys/mutex.h> 47140532Spjd#include <sys/md5.h> 48230643Sattilio#include <sys/proc.h> 4992108Sphk 50104292Sphk#include <sys/diskmbr.h> 5192108Sphk#include <sys/sbuf.h> 5292108Sphk#include <geom/geom.h> 5392108Sphk#include <geom/geom_slice.h> 5492108Sphk 55219029SnetchildFEATURE(geom_mbr, "GEOM DOS/MBR partitioning support"); 56219029Snetchild 5797075Sphk#define MBR_CLASS_NAME "MBR" 5897075Sphk#define MBREXT_CLASS_NAME "MBREXT" 5992108Sphk 60107956Sphkstatic struct dos_partition historical_bogus_partition_table[NDOSPART] = { 61107956Sphk { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 62107956Sphk { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 63107956Sphk { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 64107956Sphk { 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, }, 65107956Sphk}; 66113286Sphk 67107956Sphkstatic struct dos_partition historical_bogus_partition_table_fixed[NDOSPART] = { 68107956Sphk { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 69107956Sphk { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 70107956Sphk { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 71107956Sphk { 0x80, 0, 1, 0, DOSPTYP_386BSD, 254, 255, 255, 0, 50000, }, 72107956Sphk}; 73109101Sphk 7493090Sphkstatic void 75109101Sphkg_mbr_print(int i, struct dos_partition *dp) 76109101Sphk{ 77109101Sphk 78109101Sphk printf("[%d] f:%02x typ:%d", i, dp->dp_flag, dp->dp_typ); 79113286Sphk printf(" s(CHS):%d/%d/%d", DPCYL(dp->dp_scyl, dp->dp_ssect), 80113286Sphk dp->dp_shd, DPSECT(dp->dp_ssect)); 81113286Sphk printf(" e(CHS):%d/%d/%d", DPCYL(dp->dp_ecyl, dp->dp_esect), 82113286Sphk dp->dp_ehd, DPSECT(dp->dp_esect)); 83109101Sphk printf(" s:%d l:%d\n", dp->dp_start, dp->dp_size); 84109101Sphk} 85109101Sphk 8692108Sphkstruct g_mbr_softc { 8792108Sphk int type [NDOSPART]; 88109101Sphk u_int sectorsize; 89108393Sphk u_char sec0[512]; 90140532Spjd u_char slicesum[16]; 9192108Sphk}; 9292108Sphk 93148034Sphk/* 94148034Sphk * XXX: Add gctl_req arg and give good error msgs. 95148034Sphk * XXX: Check that length argument does not bring boot code inside any slice. 96148034Sphk */ 9792108Sphkstatic int 98148034Sphkg_mbr_modify(struct g_geom *gp, struct g_mbr_softc *ms, u_char *sec0, int len __unused) 99107956Sphk{ 100107956Sphk int i, error; 101107956Sphk off_t l[NDOSPART]; 102108393Sphk struct dos_partition ndp[NDOSPART], *dp; 103140532Spjd MD5_CTX md5sum; 104107956Sphk 105107956Sphk g_topology_assert(); 106107956Sphk 107108393Sphk if (sec0[0x1fe] != 0x55 && sec0[0x1ff] != 0xaa) 108108393Sphk return (EBUSY); 109108393Sphk 110108393Sphk dp = ndp; 111109101Sphk for (i = 0; i < NDOSPART; i++) { 112113389Sphk dos_partition_dec( 113108393Sphk sec0 + DOSPARTOFF + i * sizeof(struct dos_partition), 114108393Sphk dp + i); 115109101Sphk } 116107956Sphk if ((!bcmp(dp, historical_bogus_partition_table, 117107956Sphk sizeof historical_bogus_partition_table)) || 118107956Sphk (!bcmp(dp, historical_bogus_partition_table_fixed, 119107956Sphk sizeof historical_bogus_partition_table_fixed))) { 120107956Sphk /* 121107956Sphk * We will not allow people to write these from "the inside", 122107956Sphk * Since properly selfdestructing takes too much code. If 123107956Sphk * people really want to do this, they cannot have any 124107956Sphk * providers of this geom open, and in that case they can just 125107956Sphk * as easily overwrite the MBR in the parent device. 126107956Sphk */ 127107956Sphk return(EBUSY); 128107956Sphk } 129107956Sphk for (i = 0; i < NDOSPART; i++) { 130107956Sphk /* 131107956Sphk * A Protective MBR (PMBR) has a single partition of 132107956Sphk * type 0xEE spanning the whole disk. Such a MBR 133107956Sphk * protects a GPT on the disk from MBR tools that 134107956Sphk * don't know anything about GPT. We're interpreting 135107956Sphk * it a bit more loosely: any partition of type 0xEE 136107956Sphk * is to be skipped as it doesn't contain any data 137107956Sphk * that we should care about. We still allow other 138107956Sphk * partitions to be present in the MBR. A PMBR will 139107956Sphk * be handled correctly anyway. 140107956Sphk */ 141113030Sphk if (dp[i].dp_typ == DOSPTYP_PMBR) 142107956Sphk l[i] = 0; 143107956Sphk else if (dp[i].dp_flag != 0 && dp[i].dp_flag != 0x80) 144107956Sphk l[i] = 0; 145107956Sphk else if (dp[i].dp_typ == 0) 146107956Sphk l[i] = 0; 147107956Sphk else 148109101Sphk l[i] = (off_t)dp[i].dp_size * ms->sectorsize; 149107956Sphk error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK, 150109101Sphk (off_t)dp[i].dp_start * ms->sectorsize, l[i], 151109101Sphk ms->sectorsize, "%ss%d", gp->name, 1 + i); 152107956Sphk if (error) 153107956Sphk return (error); 154107956Sphk } 155107956Sphk for (i = 0; i < NDOSPART; i++) { 156107956Sphk ms->type[i] = dp[i].dp_typ; 157107956Sphk g_slice_config(gp, i, G_SLICE_CONFIG_SET, 158109101Sphk (off_t)dp[i].dp_start * ms->sectorsize, l[i], 159109101Sphk ms->sectorsize, "%ss%d", gp->name, 1 + i); 160107956Sphk } 161108393Sphk bcopy(sec0, ms->sec0, 512); 162140532Spjd 163140532Spjd /* 164140532Spjd * Calculate MD5 from the first sector and use it for avoiding 165140532Spjd * recursive slices creation. 166140532Spjd */ 167140532Spjd MD5Init(&md5sum); 168140532Spjd MD5Update(&md5sum, ms->sec0, sizeof(ms->sec0)); 169140532Spjd MD5Final(ms->slicesum, &md5sum); 170140532Spjd 171107956Sphk return (0); 172107956Sphk} 173107956Sphk 174119660Sphkstatic int 175138732Sphkg_mbr_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td) 176108393Sphk{ 177108393Sphk struct g_geom *gp; 178119660Sphk struct g_mbr_softc *ms; 179108393Sphk struct g_slicer *gsp; 180108393Sphk struct g_consumer *cp; 181138171Sphk int error, opened; 182108393Sphk 183119660Sphk gp = pp->geom; 184108393Sphk gsp = gp->softc; 185108393Sphk ms = gsp->softc; 186108393Sphk 187138171Sphk opened = 0; 188138171Sphk error = 0; 189119660Sphk switch(cmd) { 190119660Sphk case DIOCSMBR: { 191138732Sphk if (!(fflag & FWRITE)) 192138732Sphk return (EPERM); 193119660Sphk DROP_GIANT(); 194119660Sphk g_topology_lock(); 195119660Sphk cp = LIST_FIRST(&gp->consumer); 196138171Sphk if (cp->acw == 0) { 197138171Sphk error = g_access(cp, 0, 1, 0); 198138171Sphk if (error == 0) 199138171Sphk opened = 1; 200138171Sphk } 201138171Sphk if (!error) 202148034Sphk error = g_mbr_modify(gp, ms, data, 512); 203138171Sphk if (!error) 204138171Sphk error = g_write_data(cp, 0, data, 512); 205138171Sphk if (opened) 206138171Sphk g_access(cp, 0, -1 , 0); 207119660Sphk g_topology_unlock(); 208119660Sphk PICKUP_GIANT(); 209119660Sphk return(error); 210108393Sphk } 211119660Sphk default: 212119660Sphk return (ENOIOCTL); 213119660Sphk } 214108393Sphk} 215108393Sphk 216107956Sphkstatic int 21792108Sphkg_mbr_start(struct bio *bp) 21892108Sphk{ 21992108Sphk struct g_provider *pp; 22092108Sphk struct g_geom *gp; 22192108Sphk struct g_mbr_softc *mp; 22292108Sphk struct g_slicer *gsp; 223119660Sphk int idx; 22492108Sphk 22592108Sphk pp = bp->bio_to; 226107953Sphk idx = pp->index; 22792108Sphk gp = pp->geom; 22892108Sphk gsp = gp->softc; 22992108Sphk mp = gsp->softc; 23092108Sphk if (bp->bio_cmd == BIO_GETATTR) { 231107953Sphk if (g_handleattr_int(bp, "MBR::type", mp->type[idx])) 23292108Sphk return (1); 233106076Sphk if (g_handleattr_off_t(bp, "MBR::offset", 234107953Sphk gsp->slices[idx].offset)) 235106076Sphk return (1); 236140532Spjd if (g_handleattr(bp, "MBR::slicesum", mp->slicesum, 237140532Spjd sizeof(mp->slicesum))) 238140532Spjd return (1); 23992108Sphk } 240108393Sphk 241119660Sphk return (0); 24292108Sphk} 24392108Sphk 24492108Sphkstatic void 245107953Sphkg_mbr_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp) 24692108Sphk{ 24792108Sphk struct g_mbr_softc *mp; 24892108Sphk struct g_slicer *gsp; 24992108Sphk 25092108Sphk gsp = gp->softc; 25192108Sphk mp = gsp->softc; 252106076Sphk g_slice_dumpconf(sb, indent, gp, cp, pp); 25392108Sphk if (pp != NULL) { 254106341Smarcel if (indent == NULL) 255106341Smarcel sbuf_printf(sb, " ty %d", mp->type[pp->index]); 256106341Smarcel else 257106341Smarcel sbuf_printf(sb, "%s<type>%d</type>\n", indent, 258106341Smarcel mp->type[pp->index]); 25992108Sphk } 26092108Sphk} 26192108Sphk 26292108Sphkstatic struct g_geom * 26393250Sphkg_mbr_taste(struct g_class *mp, struct g_provider *pp, int insist) 26492108Sphk{ 26592108Sphk struct g_geom *gp; 26692108Sphk struct g_consumer *cp; 267108393Sphk int error; 26892108Sphk struct g_mbr_softc *ms; 26994287Sphk u_int fwsectors, sectorsize; 27092108Sphk u_char *buf; 271140532Spjd u_char hash[16]; 272140532Spjd MD5_CTX md5sum; 27392108Sphk 27492108Sphk g_trace(G_T_TOPOLOGY, "mbr_taste(%s,%s)", mp->name, pp->name); 27592108Sphk g_topology_assert(); 276143590Sphk if (!strcmp(pp->geom->class->name, MBR_CLASS_NAME)) 277143590Sphk return (NULL); 27892108Sphk gp = g_slice_new(mp, NDOSPART, pp, &cp, &ms, sizeof *ms, g_mbr_start); 27992108Sphk if (gp == NULL) 28092108Sphk return (NULL); 28192108Sphk g_topology_unlock(); 282113285Sphk do { 28394287Sphk error = g_getattr("GEOM::fwsectors", cp, &fwsectors); 28494287Sphk if (error) 28594287Sphk fwsectors = 17; 286105551Sphk sectorsize = cp->provider->sectorsize; 287109101Sphk if (sectorsize < 512) 28894287Sphk break; 289109101Sphk ms->sectorsize = sectorsize; 290152971Ssobomax buf = g_read_data(cp, 0, sectorsize, NULL); 291152967Ssobomax if (buf == NULL) 29292108Sphk break; 293140532Spjd 294140532Spjd /* 295140532Spjd * Calculate MD5 from the first sector and use it for avoiding 296140532Spjd * recursive slices creation. 297140532Spjd */ 298140532Spjd bcopy(buf, ms->sec0, 512); 299140532Spjd MD5Init(&md5sum); 300140532Spjd MD5Update(&md5sum, ms->sec0, sizeof(ms->sec0)); 301140532Spjd MD5Final(ms->slicesum, &md5sum); 302140532Spjd 303140532Spjd error = g_getattr("MBR::slicesum", cp, &hash); 304140532Spjd if (!error && !bcmp(ms->slicesum, hash, sizeof(hash))) { 305140532Spjd g_free(buf); 306140532Spjd break; 307140532Spjd } 308140532Spjd 309107968Sphk g_topology_lock(); 310148034Sphk g_mbr_modify(gp, ms, buf, 512); 311107968Sphk g_topology_unlock(); 312108393Sphk g_free(buf); 31392108Sphk break; 314113285Sphk } while (0); 31592108Sphk g_topology_lock(); 316125755Sphk g_access(cp, -1, 0, 0); 317107956Sphk if (LIST_EMPTY(&gp->provider)) { 318114517Sphk g_slice_spoiled(cp); 319107956Sphk return (NULL); 32092108Sphk } 321107956Sphk return (gp); 32292108Sphk} 32392108Sphk 324148034Sphkstatic void 325148034Sphkg_mbr_config(struct gctl_req *req, struct g_class *mp, const char *verb) 326148034Sphk{ 327148034Sphk struct g_geom *gp; 328148034Sphk struct g_consumer *cp; 329148034Sphk struct g_mbr_softc *ms; 330148034Sphk struct g_slicer *gsp; 331148034Sphk int opened = 0, error = 0; 332148034Sphk void *data; 333148034Sphk int len; 334148034Sphk 335148034Sphk g_topology_assert(); 336148034Sphk gp = gctl_get_geom(req, mp, "geom"); 337148034Sphk if (gp == NULL) 338148034Sphk return; 339148034Sphk if (strcmp(verb, "write MBR")) { 340148034Sphk gctl_error(req, "Unknown verb"); 341148034Sphk return; 342148034Sphk } 343148034Sphk gsp = gp->softc; 344148034Sphk ms = gsp->softc; 345148034Sphk data = gctl_get_param(req, "data", &len); 346148034Sphk if (data == NULL) 347148034Sphk return; 348148034Sphk if (len < 512 || (len % 512)) { 349148034Sphk gctl_error(req, "Wrong request length"); 350148034Sphk return; 351148034Sphk } 352148034Sphk cp = LIST_FIRST(&gp->consumer); 353148034Sphk if (cp->acw == 0) { 354148034Sphk error = g_access(cp, 0, 1, 0); 355148034Sphk if (error == 0) 356148034Sphk opened = 1; 357148034Sphk } 358148034Sphk if (!error) 359148034Sphk error = g_mbr_modify(gp, ms, data, len); 360148034Sphk if (error) 361148034Sphk gctl_error(req, "conflict with open slices"); 362148034Sphk if (!error) 363148034Sphk error = g_write_data(cp, 0, data, len); 364148034Sphk if (error) 365148034Sphk gctl_error(req, "sector zero write failed"); 366148034Sphk if (opened) 367148034Sphk g_access(cp, 0, -1 , 0); 368148034Sphk return; 369148034Sphk} 370148034Sphk 37193248Sphkstatic struct g_class g_mbr_class = { 372112552Sphk .name = MBR_CLASS_NAME, 373133318Sphk .version = G_VERSION, 374112552Sphk .taste = g_mbr_taste, 375133314Sphk .dumpconf = g_mbr_dumpconf, 376148034Sphk .ctlreq = g_mbr_config, 377133314Sphk .ioctl = g_mbr_ioctl, 37892108Sphk}; 37992108Sphk 38093248SphkDECLARE_GEOM_CLASS(g_mbr_class, g_mbr); 38193090Sphk 38293090Sphk#define NDOSEXTPART 32 38393090Sphkstruct g_mbrext_softc { 38493090Sphk int type [NDOSEXTPART]; 38593090Sphk}; 38693090Sphk 38793090Sphkstatic int 38893090Sphkg_mbrext_start(struct bio *bp) 38993090Sphk{ 39093090Sphk struct g_provider *pp; 39193090Sphk struct g_geom *gp; 39293090Sphk struct g_mbrext_softc *mp; 39393090Sphk struct g_slicer *gsp; 394107953Sphk int idx; 39593090Sphk 39693090Sphk pp = bp->bio_to; 397107953Sphk idx = pp->index; 39893090Sphk gp = pp->geom; 39993090Sphk gsp = gp->softc; 40093090Sphk mp = gsp->softc; 40193090Sphk if (bp->bio_cmd == BIO_GETATTR) { 402107953Sphk if (g_handleattr_int(bp, "MBR::type", mp->type[idx])) 40393090Sphk return (1); 40493090Sphk } 40593090Sphk return (0); 40693090Sphk} 40793090Sphk 40893090Sphkstatic void 409107953Sphkg_mbrext_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp) 41093090Sphk{ 41193090Sphk struct g_mbrext_softc *mp; 41293090Sphk struct g_slicer *gsp; 41393090Sphk 41493090Sphk g_slice_dumpconf(sb, indent, gp, cp, pp); 41593090Sphk gsp = gp->softc; 41693090Sphk mp = gsp->softc; 41793090Sphk if (pp != NULL) { 418106341Smarcel if (indent == NULL) 419106341Smarcel sbuf_printf(sb, " ty %d", mp->type[pp->index]); 420106341Smarcel else 421106341Smarcel sbuf_printf(sb, "%s<type>%d</type>\n", indent, 422106341Smarcel mp->type[pp->index]); 42393090Sphk } 42493090Sphk} 42593090Sphk 42693090Sphkstatic struct g_geom * 42793250Sphkg_mbrext_taste(struct g_class *mp, struct g_provider *pp, int insist __unused) 42893090Sphk{ 42993090Sphk struct g_geom *gp; 43093090Sphk struct g_consumer *cp; 43194287Sphk int error, i, slice; 43293090Sphk struct g_mbrext_softc *ms; 43393090Sphk off_t off; 43493090Sphk u_char *buf; 43593090Sphk struct dos_partition dp[4]; 43694287Sphk u_int fwsectors, sectorsize; 43793090Sphk 43893090Sphk g_trace(G_T_TOPOLOGY, "g_mbrext_taste(%s,%s)", mp->name, pp->name); 43993090Sphk g_topology_assert(); 44093248Sphk if (strcmp(pp->geom->class->name, MBR_CLASS_NAME)) 44193090Sphk return (NULL); 442110706Sphk gp = g_slice_new(mp, NDOSEXTPART, pp, &cp, &ms, sizeof *ms, 443110706Sphk g_mbrext_start); 44493090Sphk if (gp == NULL) 44593090Sphk return (NULL); 44693090Sphk g_topology_unlock(); 44793090Sphk off = 0; 44893090Sphk slice = 0; 449113285Sphk do { 45094287Sphk error = g_getattr("MBR::type", cp, &i); 451103100Sphk if (error || (i != DOSPTYP_EXT && i != DOSPTYP_EXTLBA)) 45293090Sphk break; 45394287Sphk error = g_getattr("GEOM::fwsectors", cp, &fwsectors); 45494287Sphk if (error) 45594287Sphk fwsectors = 17; 456105551Sphk sectorsize = cp->provider->sectorsize; 457104087Sphk if (sectorsize != 512) 45894287Sphk break; 45993090Sphk for (;;) { 460152971Ssobomax buf = g_read_data(cp, off, sectorsize, NULL); 461152967Ssobomax if (buf == NULL) 46293090Sphk break; 463114517Sphk if (buf[0x1fe] != 0x55 && buf[0x1ff] != 0xaa) { 464114517Sphk g_free(buf); 46593090Sphk break; 466114517Sphk } 46793090Sphk for (i = 0; i < NDOSPART; i++) 468113389Sphk dos_partition_dec( 469106263Sphk buf + DOSPARTOFF + 470106263Sphk i * sizeof(struct dos_partition), dp + i); 47193090Sphk g_free(buf); 472137150Sphk if (0 && bootverbose) { 473113294Sphk printf("MBREXT Slice %d on %s:\n", 474113294Sphk slice + 5, gp->name); 475113294Sphk g_mbr_print(0, dp); 476113294Sphk g_mbr_print(1, dp + 1); 477113294Sphk } 478106397Sphk if ((dp[0].dp_flag & 0x7f) == 0 && 479106397Sphk dp[0].dp_size != 0 && dp[0].dp_typ != 0) { 480108093Sphk g_topology_lock(); 481107956Sphk g_slice_config(gp, slice, G_SLICE_CONFIG_SET, 48293090Sphk (((off_t)dp[0].dp_start) << 9ULL) + off, 48393090Sphk ((off_t)dp[0].dp_size) << 9ULL, 484105542Sphk sectorsize, 48593090Sphk "%*.*s%d", 486243333Sjh (int)strlen(gp->name) - 1, 487243333Sjh (int)strlen(gp->name) - 1, 48893090Sphk gp->name, 48993090Sphk slice + 5); 490104064Sphk g_topology_unlock(); 49193090Sphk ms->type[slice] = dp[0].dp_typ; 49293090Sphk slice++; 49393090Sphk } 49493090Sphk if (dp[1].dp_flag != 0) 49593090Sphk break; 496118150Sphk if (dp[1].dp_typ != DOSPTYP_EXT && 497118150Sphk dp[1].dp_typ != DOSPTYP_EXTLBA) 49893090Sphk break; 49993090Sphk if (dp[1].dp_size == 0) 50093090Sphk break; 50193090Sphk off = ((off_t)dp[1].dp_start) << 9ULL; 50293090Sphk } 50393090Sphk break; 504113285Sphk } while (0); 50593090Sphk g_topology_lock(); 506125755Sphk g_access(cp, -1, 0, 0); 507107956Sphk if (LIST_EMPTY(&gp->provider)) { 508114517Sphk g_slice_spoiled(cp); 509107956Sphk return (NULL); 51097078Sphk } 511107956Sphk return (gp); 51293090Sphk} 51393090Sphk 51493090Sphk 51593248Sphkstatic struct g_class g_mbrext_class = { 516113031Sphk .name = MBREXT_CLASS_NAME, 517133318Sphk .version = G_VERSION, 518113031Sphk .taste = g_mbrext_taste, 519133314Sphk .dumpconf = g_mbrext_dumpconf, 52093090Sphk}; 52193090Sphk 52293248SphkDECLARE_GEOM_CLASS(g_mbrext_class, g_mbrext); 523