15aaa8fefSMarcel Moolenaar /*- 25aaa8fefSMarcel Moolenaar * Copyright (c) 2007 Marcel Moolenaar 35aaa8fefSMarcel Moolenaar * All rights reserved. 45aaa8fefSMarcel Moolenaar * 55aaa8fefSMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 65aaa8fefSMarcel Moolenaar * modification, are permitted provided that the following conditions 75aaa8fefSMarcel Moolenaar * are met: 85aaa8fefSMarcel Moolenaar * 95aaa8fefSMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 105aaa8fefSMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 115aaa8fefSMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 125aaa8fefSMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 135aaa8fefSMarcel Moolenaar * documentation and/or other materials provided with the distribution. 145aaa8fefSMarcel Moolenaar * 155aaa8fefSMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 165aaa8fefSMarcel Moolenaar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 175aaa8fefSMarcel Moolenaar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 185aaa8fefSMarcel Moolenaar * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 195aaa8fefSMarcel Moolenaar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 205aaa8fefSMarcel Moolenaar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 215aaa8fefSMarcel Moolenaar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 225aaa8fefSMarcel Moolenaar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 235aaa8fefSMarcel Moolenaar * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 245aaa8fefSMarcel Moolenaar * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 255aaa8fefSMarcel Moolenaar */ 265aaa8fefSMarcel Moolenaar 275aaa8fefSMarcel Moolenaar #include <sys/cdefs.h> 285aaa8fefSMarcel Moolenaar __FBSDID("$FreeBSD$"); 295aaa8fefSMarcel Moolenaar 305aaa8fefSMarcel Moolenaar #include <sys/param.h> 315aaa8fefSMarcel Moolenaar #include <sys/bio.h> 325aaa8fefSMarcel Moolenaar #include <sys/disklabel.h> 335aaa8fefSMarcel Moolenaar #include <sys/endian.h> 345aaa8fefSMarcel Moolenaar #include <sys/kernel.h> 355aaa8fefSMarcel Moolenaar #include <sys/kobj.h> 365aaa8fefSMarcel Moolenaar #include <sys/limits.h> 375aaa8fefSMarcel Moolenaar #include <sys/lock.h> 385aaa8fefSMarcel Moolenaar #include <sys/malloc.h> 395aaa8fefSMarcel Moolenaar #include <sys/mutex.h> 405aaa8fefSMarcel Moolenaar #include <sys/queue.h> 415aaa8fefSMarcel Moolenaar #include <sys/sbuf.h> 425aaa8fefSMarcel Moolenaar #include <sys/systm.h> 435aaa8fefSMarcel Moolenaar #include <geom/geom.h> 445aaa8fefSMarcel Moolenaar #include <geom/part/g_part.h> 455aaa8fefSMarcel Moolenaar 465aaa8fefSMarcel Moolenaar #include "g_part_if.h" 475aaa8fefSMarcel Moolenaar 485aaa8fefSMarcel Moolenaar struct g_part_bsd_table { 495aaa8fefSMarcel Moolenaar struct g_part_table base; 505aaa8fefSMarcel Moolenaar u_char *label; 51392ffadeSMarcel Moolenaar uint32_t offset; 525aaa8fefSMarcel Moolenaar }; 535aaa8fefSMarcel Moolenaar 545aaa8fefSMarcel Moolenaar struct g_part_bsd_entry { 555aaa8fefSMarcel Moolenaar struct g_part_entry base; 565aaa8fefSMarcel Moolenaar struct partition part; 575aaa8fefSMarcel Moolenaar }; 585aaa8fefSMarcel Moolenaar 595aaa8fefSMarcel Moolenaar static int g_part_bsd_add(struct g_part_table *, struct g_part_entry *, 605aaa8fefSMarcel Moolenaar struct g_part_parms *); 615aaa8fefSMarcel Moolenaar static int g_part_bsd_create(struct g_part_table *, struct g_part_parms *); 625aaa8fefSMarcel Moolenaar static int g_part_bsd_destroy(struct g_part_table *, struct g_part_parms *); 635aaa8fefSMarcel Moolenaar static int g_part_bsd_dumpto(struct g_part_table *, struct g_part_entry *); 645aaa8fefSMarcel Moolenaar static int g_part_bsd_modify(struct g_part_table *, struct g_part_entry *, 655aaa8fefSMarcel Moolenaar struct g_part_parms *); 665aaa8fefSMarcel Moolenaar static char *g_part_bsd_name(struct g_part_table *, struct g_part_entry *, 675aaa8fefSMarcel Moolenaar char *, size_t); 685aaa8fefSMarcel Moolenaar static int g_part_bsd_probe(struct g_part_table *, struct g_consumer *); 695aaa8fefSMarcel Moolenaar static int g_part_bsd_read(struct g_part_table *, struct g_consumer *); 705aaa8fefSMarcel Moolenaar static const char *g_part_bsd_type(struct g_part_table *, struct g_part_entry *, 715aaa8fefSMarcel Moolenaar char *, size_t); 725aaa8fefSMarcel Moolenaar static int g_part_bsd_write(struct g_part_table *, struct g_consumer *); 735aaa8fefSMarcel Moolenaar 745aaa8fefSMarcel Moolenaar static kobj_method_t g_part_bsd_methods[] = { 755aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_add, g_part_bsd_add), 765aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_create, g_part_bsd_create), 775aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_destroy, g_part_bsd_destroy), 785aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_dumpto, g_part_bsd_dumpto), 795aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_modify, g_part_bsd_modify), 805aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_name, g_part_bsd_name), 815aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_probe, g_part_bsd_probe), 825aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_read, g_part_bsd_read), 835aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_type, g_part_bsd_type), 845aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_write, g_part_bsd_write), 855aaa8fefSMarcel Moolenaar { 0, 0 } 865aaa8fefSMarcel Moolenaar }; 875aaa8fefSMarcel Moolenaar 885aaa8fefSMarcel Moolenaar static struct g_part_scheme g_part_bsd_scheme = { 895aaa8fefSMarcel Moolenaar "BSD", 905aaa8fefSMarcel Moolenaar g_part_bsd_methods, 915aaa8fefSMarcel Moolenaar sizeof(struct g_part_bsd_table), 925aaa8fefSMarcel Moolenaar .gps_entrysz = sizeof(struct g_part_bsd_entry), 935aaa8fefSMarcel Moolenaar .gps_minent = 8, 945aaa8fefSMarcel Moolenaar .gps_maxent = 20, 955aaa8fefSMarcel Moolenaar }; 965aaa8fefSMarcel Moolenaar G_PART_SCHEME_DECLARE(g_part_bsd_scheme); 975aaa8fefSMarcel Moolenaar 985aaa8fefSMarcel Moolenaar static int 995aaa8fefSMarcel Moolenaar bsd_parse_type(const char *type, uint8_t *fstype) 1005aaa8fefSMarcel Moolenaar { 1015aaa8fefSMarcel Moolenaar const char *alias; 1025aaa8fefSMarcel Moolenaar char *endp; 1035aaa8fefSMarcel Moolenaar long lt; 1045aaa8fefSMarcel Moolenaar 1055aaa8fefSMarcel Moolenaar if (type[0] == '!') { 1065aaa8fefSMarcel Moolenaar lt = strtol(type + 1, &endp, 0); 1075aaa8fefSMarcel Moolenaar if (type[1] == '\0' || *endp != '\0' || lt <= 0 || lt >= 256) 1085aaa8fefSMarcel Moolenaar return (EINVAL); 1095aaa8fefSMarcel Moolenaar *fstype = (u_int)lt; 1105aaa8fefSMarcel Moolenaar return (0); 1115aaa8fefSMarcel Moolenaar } 1125aaa8fefSMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_SWAP); 1135aaa8fefSMarcel Moolenaar if (!strcasecmp(type, alias)) { 1145aaa8fefSMarcel Moolenaar *fstype = FS_SWAP; 1155aaa8fefSMarcel Moolenaar return (0); 1165aaa8fefSMarcel Moolenaar } 1175aaa8fefSMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_UFS); 1185aaa8fefSMarcel Moolenaar if (!strcasecmp(type, alias)) { 1195aaa8fefSMarcel Moolenaar *fstype = FS_BSDFFS; 1205aaa8fefSMarcel Moolenaar return (0); 1215aaa8fefSMarcel Moolenaar } 1225aaa8fefSMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_VINUM); 1235aaa8fefSMarcel Moolenaar if (!strcasecmp(type, alias)) { 1245aaa8fefSMarcel Moolenaar *fstype = FS_VINUM; 1255aaa8fefSMarcel Moolenaar return (0); 1265aaa8fefSMarcel Moolenaar } 127ddba2641SMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_ZFS); 128ddba2641SMarcel Moolenaar if (!strcasecmp(type, alias)) { 129ddba2641SMarcel Moolenaar *fstype = FS_ZFS; 130ddba2641SMarcel Moolenaar return (0); 131ddba2641SMarcel Moolenaar } 1325aaa8fefSMarcel Moolenaar return (EINVAL); 1335aaa8fefSMarcel Moolenaar } 1345aaa8fefSMarcel Moolenaar 1355aaa8fefSMarcel Moolenaar static int 1365aaa8fefSMarcel Moolenaar g_part_bsd_add(struct g_part_table *basetable, struct g_part_entry *baseentry, 1375aaa8fefSMarcel Moolenaar struct g_part_parms *gpp) 1385aaa8fefSMarcel Moolenaar { 1395aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 1405aaa8fefSMarcel Moolenaar struct g_part_bsd_table *table; 1415aaa8fefSMarcel Moolenaar 1425aaa8fefSMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_LABEL) 1435aaa8fefSMarcel Moolenaar return (EINVAL); 1445aaa8fefSMarcel Moolenaar 1455aaa8fefSMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 1465aaa8fefSMarcel Moolenaar table = (struct g_part_bsd_table *)basetable; 1475aaa8fefSMarcel Moolenaar 148392ffadeSMarcel Moolenaar entry->part.p_size = gpp->gpp_size; 149392ffadeSMarcel Moolenaar entry->part.p_offset = gpp->gpp_start + table->offset; 1505aaa8fefSMarcel Moolenaar entry->part.p_fsize = 0; 1515aaa8fefSMarcel Moolenaar entry->part.p_frag = 0; 1525aaa8fefSMarcel Moolenaar entry->part.p_cpg = 0; 1535aaa8fefSMarcel Moolenaar return (bsd_parse_type(gpp->gpp_type, &entry->part.p_fstype)); 1545aaa8fefSMarcel Moolenaar } 1555aaa8fefSMarcel Moolenaar 1565aaa8fefSMarcel Moolenaar static int 1575aaa8fefSMarcel Moolenaar g_part_bsd_create(struct g_part_table *basetable, struct g_part_parms *gpp) 1585aaa8fefSMarcel Moolenaar { 1595aaa8fefSMarcel Moolenaar struct g_consumer *cp; 1605aaa8fefSMarcel Moolenaar struct g_provider *pp; 1615aaa8fefSMarcel Moolenaar struct g_part_entry *baseentry; 1625aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 1635aaa8fefSMarcel Moolenaar struct g_part_bsd_table *table; 1645aaa8fefSMarcel Moolenaar u_char *ptr; 1655aaa8fefSMarcel Moolenaar uint64_t msize; 1665aaa8fefSMarcel Moolenaar uint32_t ncyls, secpercyl; 1675aaa8fefSMarcel Moolenaar 1685aaa8fefSMarcel Moolenaar pp = gpp->gpp_provider; 1695aaa8fefSMarcel Moolenaar cp = LIST_FIRST(&pp->consumers); 1705aaa8fefSMarcel Moolenaar 1715aaa8fefSMarcel Moolenaar if (pp->sectorsize < sizeof(struct disklabel)) 1725aaa8fefSMarcel Moolenaar return (ENOSPC); 1735aaa8fefSMarcel Moolenaar 1745aaa8fefSMarcel Moolenaar msize = pp->mediasize / pp->sectorsize; 1755aaa8fefSMarcel Moolenaar secpercyl = basetable->gpt_sectors * basetable->gpt_heads; 1765aaa8fefSMarcel Moolenaar ncyls = msize / secpercyl; 1775aaa8fefSMarcel Moolenaar 1785aaa8fefSMarcel Moolenaar table = (struct g_part_bsd_table *)basetable; 1795aaa8fefSMarcel Moolenaar ptr = table->label = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO); 1805aaa8fefSMarcel Moolenaar 1815aaa8fefSMarcel Moolenaar le32enc(ptr + 0, DISKMAGIC); /* d_magic */ 1825aaa8fefSMarcel Moolenaar le32enc(ptr + 40, pp->sectorsize); /* d_secsize */ 1835aaa8fefSMarcel Moolenaar le32enc(ptr + 44, basetable->gpt_sectors); /* d_nsectors */ 1845aaa8fefSMarcel Moolenaar le32enc(ptr + 48, basetable->gpt_heads); /* d_ntracks */ 1855aaa8fefSMarcel Moolenaar le32enc(ptr + 52, ncyls); /* d_ncylinders */ 1865aaa8fefSMarcel Moolenaar le32enc(ptr + 56, secpercyl); /* d_secpercyl */ 187392ffadeSMarcel Moolenaar le32enc(ptr + 60, msize); /* d_secperunit */ 1885aaa8fefSMarcel Moolenaar le16enc(ptr + 72, 3600); /* d_rpm */ 1895aaa8fefSMarcel Moolenaar le32enc(ptr + 132, DISKMAGIC); /* d_magic2 */ 1905aaa8fefSMarcel Moolenaar le16enc(ptr + 138, basetable->gpt_entries); /* d_npartitions */ 1915aaa8fefSMarcel Moolenaar le32enc(ptr + 140, BBSIZE); /* d_bbsize */ 1925aaa8fefSMarcel Moolenaar 1935aaa8fefSMarcel Moolenaar basetable->gpt_first = 0; 194392ffadeSMarcel Moolenaar basetable->gpt_last = msize - 1; 1955aaa8fefSMarcel Moolenaar basetable->gpt_isleaf = 1; 1965aaa8fefSMarcel Moolenaar 1975aaa8fefSMarcel Moolenaar baseentry = g_part_new_entry(basetable, RAW_PART + 1, 1985aaa8fefSMarcel Moolenaar basetable->gpt_first, basetable->gpt_last); 1995aaa8fefSMarcel Moolenaar baseentry->gpe_internal = 1; 2005aaa8fefSMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 2015aaa8fefSMarcel Moolenaar entry->part.p_size = basetable->gpt_last + 1; 202392ffadeSMarcel Moolenaar entry->part.p_offset = table->offset; 2035aaa8fefSMarcel Moolenaar 2045aaa8fefSMarcel Moolenaar return (0); 2055aaa8fefSMarcel Moolenaar } 2065aaa8fefSMarcel Moolenaar 2075aaa8fefSMarcel Moolenaar static int 2085aaa8fefSMarcel Moolenaar g_part_bsd_destroy(struct g_part_table *basetable, struct g_part_parms *gpp) 2095aaa8fefSMarcel Moolenaar { 2105aaa8fefSMarcel Moolenaar 2115aaa8fefSMarcel Moolenaar /* Wipe the second sector to clear the partitioning. */ 2125aaa8fefSMarcel Moolenaar basetable->gpt_smhead |= 2; 2135aaa8fefSMarcel Moolenaar return (0); 2145aaa8fefSMarcel Moolenaar } 2155aaa8fefSMarcel Moolenaar 2165aaa8fefSMarcel Moolenaar static int 2175aaa8fefSMarcel Moolenaar g_part_bsd_dumpto(struct g_part_table *table, struct g_part_entry *baseentry) 2185aaa8fefSMarcel Moolenaar { 2195aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 2205aaa8fefSMarcel Moolenaar 2215aaa8fefSMarcel Moolenaar /* Allow dumping to a swap partition only. */ 2225aaa8fefSMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 2235aaa8fefSMarcel Moolenaar return ((entry->part.p_fstype == FS_SWAP) ? 1 : 0); 2245aaa8fefSMarcel Moolenaar } 2255aaa8fefSMarcel Moolenaar 2265aaa8fefSMarcel Moolenaar static int 2275aaa8fefSMarcel Moolenaar g_part_bsd_modify(struct g_part_table *basetable, 2285aaa8fefSMarcel Moolenaar struct g_part_entry *baseentry, struct g_part_parms *gpp) 2295aaa8fefSMarcel Moolenaar { 2305aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 2315aaa8fefSMarcel Moolenaar 2325aaa8fefSMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_LABEL) 2335aaa8fefSMarcel Moolenaar return (EINVAL); 2345aaa8fefSMarcel Moolenaar 2355aaa8fefSMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 2365aaa8fefSMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_TYPE) 2375aaa8fefSMarcel Moolenaar return (bsd_parse_type(gpp->gpp_type, &entry->part.p_fstype)); 2385aaa8fefSMarcel Moolenaar return (0); 2395aaa8fefSMarcel Moolenaar } 2405aaa8fefSMarcel Moolenaar 2415aaa8fefSMarcel Moolenaar static char * 2425aaa8fefSMarcel Moolenaar g_part_bsd_name(struct g_part_table *table, struct g_part_entry *baseentry, 2435aaa8fefSMarcel Moolenaar char *buf, size_t bufsz) 2445aaa8fefSMarcel Moolenaar { 2455aaa8fefSMarcel Moolenaar 2465aaa8fefSMarcel Moolenaar snprintf(buf, bufsz, "%c", 'a' + baseentry->gpe_index - 1); 2475aaa8fefSMarcel Moolenaar return (buf); 2485aaa8fefSMarcel Moolenaar } 2495aaa8fefSMarcel Moolenaar 2505aaa8fefSMarcel Moolenaar static int 2515aaa8fefSMarcel Moolenaar g_part_bsd_probe(struct g_part_table *table, struct g_consumer *cp) 2525aaa8fefSMarcel Moolenaar { 2535aaa8fefSMarcel Moolenaar struct g_provider *pp; 2545aaa8fefSMarcel Moolenaar u_char *buf; 2555aaa8fefSMarcel Moolenaar uint32_t magic1, magic2; 2565aaa8fefSMarcel Moolenaar int error; 2575aaa8fefSMarcel Moolenaar 2585aaa8fefSMarcel Moolenaar pp = cp->provider; 2595aaa8fefSMarcel Moolenaar 2605aaa8fefSMarcel Moolenaar /* Sanity-check the provider. */ 2615aaa8fefSMarcel Moolenaar if (pp->sectorsize < sizeof(struct disklabel) || 2625aaa8fefSMarcel Moolenaar pp->mediasize < BBSIZE) 2635aaa8fefSMarcel Moolenaar return (ENOSPC); 2645aaa8fefSMarcel Moolenaar 2655aaa8fefSMarcel Moolenaar /* Check that there's a disklabel. */ 2665aaa8fefSMarcel Moolenaar buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error); 2675aaa8fefSMarcel Moolenaar if (buf == NULL) 2685aaa8fefSMarcel Moolenaar return (error); 2695aaa8fefSMarcel Moolenaar magic1 = le32dec(buf + 0); 2705aaa8fefSMarcel Moolenaar magic2 = le32dec(buf + 132); 2715aaa8fefSMarcel Moolenaar g_free(buf); 2725aaa8fefSMarcel Moolenaar return ((magic1 == DISKMAGIC && magic2 == DISKMAGIC) 2735aaa8fefSMarcel Moolenaar ? G_PART_PROBE_PRI_NORM : ENXIO); 2745aaa8fefSMarcel Moolenaar } 2755aaa8fefSMarcel Moolenaar 2765aaa8fefSMarcel Moolenaar static int 2775aaa8fefSMarcel Moolenaar g_part_bsd_read(struct g_part_table *basetable, struct g_consumer *cp) 2785aaa8fefSMarcel Moolenaar { 2795aaa8fefSMarcel Moolenaar struct g_provider *pp; 2805aaa8fefSMarcel Moolenaar struct g_part_bsd_table *table; 2815aaa8fefSMarcel Moolenaar struct g_part_entry *baseentry; 2825aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 2835aaa8fefSMarcel Moolenaar struct partition part; 2845aaa8fefSMarcel Moolenaar u_char *buf, *p; 2855aaa8fefSMarcel Moolenaar off_t chs, msize; 2865aaa8fefSMarcel Moolenaar u_int sectors, heads; 2875aaa8fefSMarcel Moolenaar int error, index; 2885aaa8fefSMarcel Moolenaar 2895aaa8fefSMarcel Moolenaar pp = cp->provider; 2905aaa8fefSMarcel Moolenaar table = (struct g_part_bsd_table *)basetable; 2915aaa8fefSMarcel Moolenaar msize = pp->mediasize / pp->sectorsize; 2925aaa8fefSMarcel Moolenaar 2935aaa8fefSMarcel Moolenaar buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error); 2945aaa8fefSMarcel Moolenaar if (buf == NULL) 2955aaa8fefSMarcel Moolenaar return (error); 2965aaa8fefSMarcel Moolenaar 2975aaa8fefSMarcel Moolenaar table->label = buf; 2985aaa8fefSMarcel Moolenaar 2995aaa8fefSMarcel Moolenaar if (le32dec(buf + 40) != pp->sectorsize) 3005aaa8fefSMarcel Moolenaar goto invalid_label; 3015aaa8fefSMarcel Moolenaar sectors = le32dec(buf + 44); 3025aaa8fefSMarcel Moolenaar if (sectors < 1 || sectors > 63) 3035aaa8fefSMarcel Moolenaar goto invalid_label; 304392ffadeSMarcel Moolenaar if (sectors != basetable->gpt_sectors && !basetable->gpt_fixgeom) { 3055aaa8fefSMarcel Moolenaar g_part_geometry_heads(msize, sectors, &chs, &heads); 306392ffadeSMarcel Moolenaar if (chs != 0) { 3075aaa8fefSMarcel Moolenaar basetable->gpt_sectors = sectors; 3085aaa8fefSMarcel Moolenaar basetable->gpt_heads = heads; 3095aaa8fefSMarcel Moolenaar } 310392ffadeSMarcel Moolenaar } 3115aaa8fefSMarcel Moolenaar heads = le32dec(buf + 48); 3125aaa8fefSMarcel Moolenaar if (heads < 1 || heads > 255) 3135aaa8fefSMarcel Moolenaar goto invalid_label; 314392ffadeSMarcel Moolenaar if (heads != basetable->gpt_heads && !basetable->gpt_fixgeom) 3155aaa8fefSMarcel Moolenaar basetable->gpt_heads = heads; 316392ffadeSMarcel Moolenaar if (sectors != basetable->gpt_sectors || 317392ffadeSMarcel Moolenaar heads != basetable->gpt_heads) 318392ffadeSMarcel Moolenaar printf("GEOM: %s: geometry does not match label.\n", pp->name); 319392ffadeSMarcel Moolenaar 320392ffadeSMarcel Moolenaar chs = le32dec(buf + 60); 3215aaa8fefSMarcel Moolenaar if (chs < 1 || chs > msize) 3225aaa8fefSMarcel Moolenaar goto invalid_label; 323392ffadeSMarcel Moolenaar if (chs != msize) 324392ffadeSMarcel Moolenaar printf("GEOM: %s: media size does not match label.\n", 325392ffadeSMarcel Moolenaar pp->name); 3265aaa8fefSMarcel Moolenaar 3275aaa8fefSMarcel Moolenaar basetable->gpt_first = 0; 328392ffadeSMarcel Moolenaar basetable->gpt_last = msize - 1; 3295aaa8fefSMarcel Moolenaar basetable->gpt_isleaf = 1; 3305aaa8fefSMarcel Moolenaar 3315aaa8fefSMarcel Moolenaar basetable->gpt_entries = le16dec(buf + 138); 3325aaa8fefSMarcel Moolenaar if (basetable->gpt_entries < g_part_bsd_scheme.gps_minent || 3335aaa8fefSMarcel Moolenaar basetable->gpt_entries > g_part_bsd_scheme.gps_maxent) 3345aaa8fefSMarcel Moolenaar goto invalid_label; 3355aaa8fefSMarcel Moolenaar 336392ffadeSMarcel Moolenaar table->offset = le32dec(buf + 148 + RAW_PART * 16 + 4); 3375aaa8fefSMarcel Moolenaar for (index = basetable->gpt_entries - 1; index >= 0; index--) { 3385aaa8fefSMarcel Moolenaar p = buf + 148 + index * 16; 3395aaa8fefSMarcel Moolenaar part.p_size = le32dec(p + 0); 3405aaa8fefSMarcel Moolenaar part.p_offset = le32dec(p + 4); 3415aaa8fefSMarcel Moolenaar part.p_fsize = le32dec(p + 8); 3425aaa8fefSMarcel Moolenaar part.p_fstype = p[12]; 3435aaa8fefSMarcel Moolenaar part.p_frag = p[13]; 3445aaa8fefSMarcel Moolenaar part.p_cpg = le16dec(p + 14); 3455aaa8fefSMarcel Moolenaar if (part.p_size == 0) 3465aaa8fefSMarcel Moolenaar continue; 3475aaa8fefSMarcel Moolenaar if (part.p_fstype == FS_UNUSED && index != RAW_PART) 3485aaa8fefSMarcel Moolenaar continue; 349392ffadeSMarcel Moolenaar if (part.p_offset < table->offset) 3505aaa8fefSMarcel Moolenaar continue; 3515aaa8fefSMarcel Moolenaar baseentry = g_part_new_entry(basetable, index + 1, 352392ffadeSMarcel Moolenaar part.p_offset - table->offset, 353392ffadeSMarcel Moolenaar part.p_offset - table->offset + part.p_size - 1); 3545aaa8fefSMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 3555aaa8fefSMarcel Moolenaar entry->part = part; 3565aaa8fefSMarcel Moolenaar if (part.p_fstype == FS_UNUSED) 3575aaa8fefSMarcel Moolenaar baseentry->gpe_internal = 1; 3585aaa8fefSMarcel Moolenaar } 3595aaa8fefSMarcel Moolenaar 3605aaa8fefSMarcel Moolenaar return (0); 3615aaa8fefSMarcel Moolenaar 3625aaa8fefSMarcel Moolenaar invalid_label: 3635aaa8fefSMarcel Moolenaar printf("GEOM: %s: invalid disklabel.\n", pp->name); 3645aaa8fefSMarcel Moolenaar g_free(table->label); 3655aaa8fefSMarcel Moolenaar return (EINVAL); 3665aaa8fefSMarcel Moolenaar } 3675aaa8fefSMarcel Moolenaar 3685aaa8fefSMarcel Moolenaar static const char * 3695aaa8fefSMarcel Moolenaar g_part_bsd_type(struct g_part_table *basetable, struct g_part_entry *baseentry, 3705aaa8fefSMarcel Moolenaar char *buf, size_t bufsz) 3715aaa8fefSMarcel Moolenaar { 3725aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 3735aaa8fefSMarcel Moolenaar int type; 3745aaa8fefSMarcel Moolenaar 3755aaa8fefSMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 3765aaa8fefSMarcel Moolenaar type = entry->part.p_fstype; 3775aaa8fefSMarcel Moolenaar if (type == FS_SWAP) 3785aaa8fefSMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_SWAP)); 3795aaa8fefSMarcel Moolenaar if (type == FS_BSDFFS) 3805aaa8fefSMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_UFS)); 3815aaa8fefSMarcel Moolenaar if (type == FS_VINUM) 3825aaa8fefSMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_VINUM)); 383ddba2641SMarcel Moolenaar if (type == FS_ZFS) 384ddba2641SMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_ZFS)); 3855aaa8fefSMarcel Moolenaar snprintf(buf, bufsz, "!%d", type); 3865aaa8fefSMarcel Moolenaar return (buf); 3875aaa8fefSMarcel Moolenaar } 3885aaa8fefSMarcel Moolenaar 3895aaa8fefSMarcel Moolenaar static int 3905aaa8fefSMarcel Moolenaar g_part_bsd_write(struct g_part_table *basetable, struct g_consumer *cp) 3915aaa8fefSMarcel Moolenaar { 3925aaa8fefSMarcel Moolenaar struct g_provider *pp; 3935aaa8fefSMarcel Moolenaar struct g_part_entry *baseentry; 3945aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 3955aaa8fefSMarcel Moolenaar struct g_part_bsd_table *table; 3965aaa8fefSMarcel Moolenaar uint16_t sum; 3975aaa8fefSMarcel Moolenaar u_char *p, *pe; 3985aaa8fefSMarcel Moolenaar int error, index; 3995aaa8fefSMarcel Moolenaar 4005aaa8fefSMarcel Moolenaar pp = cp->provider; 4015aaa8fefSMarcel Moolenaar table = (struct g_part_bsd_table *)basetable; 4025aaa8fefSMarcel Moolenaar baseentry = LIST_FIRST(&basetable->gpt_entry); 4035aaa8fefSMarcel Moolenaar for (index = 1; index <= basetable->gpt_entries; index++) { 4045aaa8fefSMarcel Moolenaar p = table->label + 148 + (index - 1) * 16; 4055aaa8fefSMarcel Moolenaar entry = (baseentry != NULL && index == baseentry->gpe_index) 4065aaa8fefSMarcel Moolenaar ? (struct g_part_bsd_entry *)baseentry : NULL; 4075aaa8fefSMarcel Moolenaar if (entry != NULL && !baseentry->gpe_deleted) { 4085aaa8fefSMarcel Moolenaar le32enc(p + 0, entry->part.p_size); 4095aaa8fefSMarcel Moolenaar le32enc(p + 4, entry->part.p_offset); 4105aaa8fefSMarcel Moolenaar le32enc(p + 8, entry->part.p_fsize); 4115aaa8fefSMarcel Moolenaar p[12] = entry->part.p_fstype; 4125aaa8fefSMarcel Moolenaar p[13] = entry->part.p_frag; 4135aaa8fefSMarcel Moolenaar le16enc(p + 14, entry->part.p_cpg); 4145aaa8fefSMarcel Moolenaar } else 4155aaa8fefSMarcel Moolenaar bzero(p, 16); 4165aaa8fefSMarcel Moolenaar 4175aaa8fefSMarcel Moolenaar if (entry != NULL) 4185aaa8fefSMarcel Moolenaar baseentry = LIST_NEXT(baseentry, gpe_entry); 4195aaa8fefSMarcel Moolenaar } 4205aaa8fefSMarcel Moolenaar 4215aaa8fefSMarcel Moolenaar /* Calculate checksum. */ 4225aaa8fefSMarcel Moolenaar le16enc(table->label + 136, 0); 4235aaa8fefSMarcel Moolenaar pe = table->label + 148 + basetable->gpt_entries * 16; 4245aaa8fefSMarcel Moolenaar sum = 0; 4255aaa8fefSMarcel Moolenaar for (p = table->label; p < pe; p += 2) 4265aaa8fefSMarcel Moolenaar sum ^= le16dec(p); 4275aaa8fefSMarcel Moolenaar le16enc(table->label + 136, sum); 4285aaa8fefSMarcel Moolenaar 4295aaa8fefSMarcel Moolenaar error = g_write_data(cp, pp->sectorsize, table->label, pp->sectorsize); 4305aaa8fefSMarcel Moolenaar return (error); 4315aaa8fefSMarcel Moolenaar } 432