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 *); 635db67052SMarcel Moolenaar static int g_part_bsd_dumpconf(struct g_part_table *, struct g_part_entry *, 645db67052SMarcel Moolenaar struct sbuf *, const char *); 655aaa8fefSMarcel Moolenaar static int g_part_bsd_dumpto(struct g_part_table *, struct g_part_entry *); 665aaa8fefSMarcel Moolenaar static int g_part_bsd_modify(struct g_part_table *, struct g_part_entry *, 675aaa8fefSMarcel Moolenaar struct g_part_parms *); 685aaa8fefSMarcel Moolenaar static char *g_part_bsd_name(struct g_part_table *, struct g_part_entry *, 695aaa8fefSMarcel Moolenaar char *, size_t); 705aaa8fefSMarcel Moolenaar static int g_part_bsd_probe(struct g_part_table *, struct g_consumer *); 715aaa8fefSMarcel Moolenaar static int g_part_bsd_read(struct g_part_table *, struct g_consumer *); 725aaa8fefSMarcel Moolenaar static const char *g_part_bsd_type(struct g_part_table *, struct g_part_entry *, 735aaa8fefSMarcel Moolenaar char *, size_t); 745aaa8fefSMarcel Moolenaar static int g_part_bsd_write(struct g_part_table *, struct g_consumer *); 755aaa8fefSMarcel Moolenaar 765aaa8fefSMarcel Moolenaar static kobj_method_t g_part_bsd_methods[] = { 775aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_add, g_part_bsd_add), 785aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_create, g_part_bsd_create), 795aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_destroy, g_part_bsd_destroy), 805db67052SMarcel Moolenaar KOBJMETHOD(g_part_dumpconf, g_part_bsd_dumpconf), 815aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_dumpto, g_part_bsd_dumpto), 825aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_modify, g_part_bsd_modify), 835aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_name, g_part_bsd_name), 845aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_probe, g_part_bsd_probe), 855aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_read, g_part_bsd_read), 865aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_type, g_part_bsd_type), 875aaa8fefSMarcel Moolenaar KOBJMETHOD(g_part_write, g_part_bsd_write), 885aaa8fefSMarcel Moolenaar { 0, 0 } 895aaa8fefSMarcel Moolenaar }; 905aaa8fefSMarcel Moolenaar 915aaa8fefSMarcel Moolenaar static struct g_part_scheme g_part_bsd_scheme = { 925aaa8fefSMarcel Moolenaar "BSD", 935aaa8fefSMarcel Moolenaar g_part_bsd_methods, 945aaa8fefSMarcel Moolenaar sizeof(struct g_part_bsd_table), 955aaa8fefSMarcel Moolenaar .gps_entrysz = sizeof(struct g_part_bsd_entry), 965aaa8fefSMarcel Moolenaar .gps_minent = 8, 975aaa8fefSMarcel Moolenaar .gps_maxent = 20, 985aaa8fefSMarcel Moolenaar }; 994ffca444SMarcel Moolenaar G_PART_SCHEME_DECLARE(g_part_bsd); 1005aaa8fefSMarcel Moolenaar 1015aaa8fefSMarcel Moolenaar static int 1025aaa8fefSMarcel Moolenaar bsd_parse_type(const char *type, uint8_t *fstype) 1035aaa8fefSMarcel Moolenaar { 1045aaa8fefSMarcel Moolenaar const char *alias; 1055aaa8fefSMarcel Moolenaar char *endp; 1065aaa8fefSMarcel Moolenaar long lt; 1075aaa8fefSMarcel Moolenaar 1085aaa8fefSMarcel Moolenaar if (type[0] == '!') { 1095aaa8fefSMarcel Moolenaar lt = strtol(type + 1, &endp, 0); 1105aaa8fefSMarcel Moolenaar if (type[1] == '\0' || *endp != '\0' || lt <= 0 || lt >= 256) 1115aaa8fefSMarcel Moolenaar return (EINVAL); 1125aaa8fefSMarcel Moolenaar *fstype = (u_int)lt; 1135aaa8fefSMarcel Moolenaar return (0); 1145aaa8fefSMarcel Moolenaar } 1155aaa8fefSMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_SWAP); 1165aaa8fefSMarcel Moolenaar if (!strcasecmp(type, alias)) { 1175aaa8fefSMarcel Moolenaar *fstype = FS_SWAP; 1185aaa8fefSMarcel Moolenaar return (0); 1195aaa8fefSMarcel Moolenaar } 1205aaa8fefSMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_UFS); 1215aaa8fefSMarcel Moolenaar if (!strcasecmp(type, alias)) { 1225aaa8fefSMarcel Moolenaar *fstype = FS_BSDFFS; 1235aaa8fefSMarcel Moolenaar return (0); 1245aaa8fefSMarcel Moolenaar } 1255aaa8fefSMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_VINUM); 1265aaa8fefSMarcel Moolenaar if (!strcasecmp(type, alias)) { 1275aaa8fefSMarcel Moolenaar *fstype = FS_VINUM; 1285aaa8fefSMarcel Moolenaar return (0); 1295aaa8fefSMarcel Moolenaar } 130ddba2641SMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_ZFS); 131ddba2641SMarcel Moolenaar if (!strcasecmp(type, alias)) { 132ddba2641SMarcel Moolenaar *fstype = FS_ZFS; 133ddba2641SMarcel Moolenaar return (0); 134ddba2641SMarcel Moolenaar } 1355aaa8fefSMarcel Moolenaar return (EINVAL); 1365aaa8fefSMarcel Moolenaar } 1375aaa8fefSMarcel Moolenaar 1385aaa8fefSMarcel Moolenaar static int 1395aaa8fefSMarcel Moolenaar g_part_bsd_add(struct g_part_table *basetable, struct g_part_entry *baseentry, 1405aaa8fefSMarcel Moolenaar struct g_part_parms *gpp) 1415aaa8fefSMarcel Moolenaar { 1425aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 1435aaa8fefSMarcel Moolenaar struct g_part_bsd_table *table; 1445aaa8fefSMarcel Moolenaar 1455aaa8fefSMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_LABEL) 1465aaa8fefSMarcel Moolenaar return (EINVAL); 1475aaa8fefSMarcel Moolenaar 1485aaa8fefSMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 1495aaa8fefSMarcel Moolenaar table = (struct g_part_bsd_table *)basetable; 1505aaa8fefSMarcel Moolenaar 151392ffadeSMarcel Moolenaar entry->part.p_size = gpp->gpp_size; 152392ffadeSMarcel Moolenaar entry->part.p_offset = gpp->gpp_start + table->offset; 1535aaa8fefSMarcel Moolenaar entry->part.p_fsize = 0; 1545aaa8fefSMarcel Moolenaar entry->part.p_frag = 0; 1555aaa8fefSMarcel Moolenaar entry->part.p_cpg = 0; 1565aaa8fefSMarcel Moolenaar return (bsd_parse_type(gpp->gpp_type, &entry->part.p_fstype)); 1575aaa8fefSMarcel Moolenaar } 1585aaa8fefSMarcel Moolenaar 1595aaa8fefSMarcel Moolenaar static int 1605aaa8fefSMarcel Moolenaar g_part_bsd_create(struct g_part_table *basetable, struct g_part_parms *gpp) 1615aaa8fefSMarcel Moolenaar { 1625aaa8fefSMarcel Moolenaar struct g_consumer *cp; 1635aaa8fefSMarcel Moolenaar struct g_provider *pp; 1645aaa8fefSMarcel Moolenaar struct g_part_entry *baseentry; 1655aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 1665aaa8fefSMarcel Moolenaar struct g_part_bsd_table *table; 1675aaa8fefSMarcel Moolenaar u_char *ptr; 1685aaa8fefSMarcel Moolenaar uint64_t msize; 1695aaa8fefSMarcel Moolenaar uint32_t ncyls, secpercyl; 1705aaa8fefSMarcel Moolenaar 1715aaa8fefSMarcel Moolenaar pp = gpp->gpp_provider; 1725aaa8fefSMarcel Moolenaar cp = LIST_FIRST(&pp->consumers); 1735aaa8fefSMarcel Moolenaar 1745aaa8fefSMarcel Moolenaar if (pp->sectorsize < sizeof(struct disklabel)) 1755aaa8fefSMarcel Moolenaar return (ENOSPC); 1765aaa8fefSMarcel Moolenaar 1775aaa8fefSMarcel Moolenaar msize = pp->mediasize / pp->sectorsize; 1785aaa8fefSMarcel Moolenaar secpercyl = basetable->gpt_sectors * basetable->gpt_heads; 1795aaa8fefSMarcel Moolenaar ncyls = msize / secpercyl; 1805aaa8fefSMarcel Moolenaar 1815aaa8fefSMarcel Moolenaar table = (struct g_part_bsd_table *)basetable; 1825aaa8fefSMarcel Moolenaar ptr = table->label = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO); 1835aaa8fefSMarcel Moolenaar 1845aaa8fefSMarcel Moolenaar le32enc(ptr + 0, DISKMAGIC); /* d_magic */ 1855aaa8fefSMarcel Moolenaar le32enc(ptr + 40, pp->sectorsize); /* d_secsize */ 1865aaa8fefSMarcel Moolenaar le32enc(ptr + 44, basetable->gpt_sectors); /* d_nsectors */ 1875aaa8fefSMarcel Moolenaar le32enc(ptr + 48, basetable->gpt_heads); /* d_ntracks */ 1885aaa8fefSMarcel Moolenaar le32enc(ptr + 52, ncyls); /* d_ncylinders */ 1895aaa8fefSMarcel Moolenaar le32enc(ptr + 56, secpercyl); /* d_secpercyl */ 190392ffadeSMarcel Moolenaar le32enc(ptr + 60, msize); /* d_secperunit */ 1915aaa8fefSMarcel Moolenaar le16enc(ptr + 72, 3600); /* d_rpm */ 1925aaa8fefSMarcel Moolenaar le32enc(ptr + 132, DISKMAGIC); /* d_magic2 */ 1935aaa8fefSMarcel Moolenaar le16enc(ptr + 138, basetable->gpt_entries); /* d_npartitions */ 1945aaa8fefSMarcel Moolenaar le32enc(ptr + 140, BBSIZE); /* d_bbsize */ 1955aaa8fefSMarcel Moolenaar 1965aaa8fefSMarcel Moolenaar basetable->gpt_first = 0; 197392ffadeSMarcel Moolenaar basetable->gpt_last = msize - 1; 1985aaa8fefSMarcel Moolenaar basetable->gpt_isleaf = 1; 1995aaa8fefSMarcel Moolenaar 2005aaa8fefSMarcel Moolenaar baseentry = g_part_new_entry(basetable, RAW_PART + 1, 2015aaa8fefSMarcel Moolenaar basetable->gpt_first, basetable->gpt_last); 2025aaa8fefSMarcel Moolenaar baseentry->gpe_internal = 1; 2035aaa8fefSMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 2045aaa8fefSMarcel Moolenaar entry->part.p_size = basetable->gpt_last + 1; 205392ffadeSMarcel Moolenaar entry->part.p_offset = table->offset; 2065aaa8fefSMarcel Moolenaar 2075aaa8fefSMarcel Moolenaar return (0); 2085aaa8fefSMarcel Moolenaar } 2095aaa8fefSMarcel Moolenaar 2105aaa8fefSMarcel Moolenaar static int 2115aaa8fefSMarcel Moolenaar g_part_bsd_destroy(struct g_part_table *basetable, struct g_part_parms *gpp) 2125aaa8fefSMarcel Moolenaar { 2135aaa8fefSMarcel Moolenaar 2145aaa8fefSMarcel Moolenaar /* Wipe the second sector to clear the partitioning. */ 2155aaa8fefSMarcel Moolenaar basetable->gpt_smhead |= 2; 2165aaa8fefSMarcel Moolenaar return (0); 2175aaa8fefSMarcel Moolenaar } 2185aaa8fefSMarcel Moolenaar 2195aaa8fefSMarcel Moolenaar static int 2205db67052SMarcel Moolenaar g_part_bsd_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry, 2215db67052SMarcel Moolenaar struct sbuf *sb, const char *indent) 2225db67052SMarcel Moolenaar { 2235db67052SMarcel Moolenaar struct g_part_bsd_entry *entry; 2245db67052SMarcel Moolenaar 2255db67052SMarcel Moolenaar if (indent != NULL) 2265db67052SMarcel Moolenaar return (0); 2275db67052SMarcel Moolenaar 2285db67052SMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 2295db67052SMarcel Moolenaar sbuf_printf(sb, " xs BSD xt %u", entry->part.p_fstype); 2305db67052SMarcel Moolenaar return (0); 2315db67052SMarcel Moolenaar } 2325db67052SMarcel Moolenaar 2335db67052SMarcel Moolenaar static int 2345aaa8fefSMarcel Moolenaar g_part_bsd_dumpto(struct g_part_table *table, struct g_part_entry *baseentry) 2355aaa8fefSMarcel Moolenaar { 2365aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 2375aaa8fefSMarcel Moolenaar 2385aaa8fefSMarcel Moolenaar /* Allow dumping to a swap partition only. */ 2395aaa8fefSMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 2405aaa8fefSMarcel Moolenaar return ((entry->part.p_fstype == FS_SWAP) ? 1 : 0); 2415aaa8fefSMarcel Moolenaar } 2425aaa8fefSMarcel Moolenaar 2435aaa8fefSMarcel Moolenaar static int 2445aaa8fefSMarcel Moolenaar g_part_bsd_modify(struct g_part_table *basetable, 2455aaa8fefSMarcel Moolenaar struct g_part_entry *baseentry, struct g_part_parms *gpp) 2465aaa8fefSMarcel Moolenaar { 2475aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 2485aaa8fefSMarcel Moolenaar 2495aaa8fefSMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_LABEL) 2505aaa8fefSMarcel Moolenaar return (EINVAL); 2515aaa8fefSMarcel Moolenaar 2525aaa8fefSMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 2535aaa8fefSMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_TYPE) 2545aaa8fefSMarcel Moolenaar return (bsd_parse_type(gpp->gpp_type, &entry->part.p_fstype)); 2555aaa8fefSMarcel Moolenaar return (0); 2565aaa8fefSMarcel Moolenaar } 2575aaa8fefSMarcel Moolenaar 2585aaa8fefSMarcel Moolenaar static char * 2595aaa8fefSMarcel Moolenaar g_part_bsd_name(struct g_part_table *table, struct g_part_entry *baseentry, 2605aaa8fefSMarcel Moolenaar char *buf, size_t bufsz) 2615aaa8fefSMarcel Moolenaar { 2625aaa8fefSMarcel Moolenaar 2635aaa8fefSMarcel Moolenaar snprintf(buf, bufsz, "%c", 'a' + baseentry->gpe_index - 1); 2645aaa8fefSMarcel Moolenaar return (buf); 2655aaa8fefSMarcel Moolenaar } 2665aaa8fefSMarcel Moolenaar 2675aaa8fefSMarcel Moolenaar static int 2685aaa8fefSMarcel Moolenaar g_part_bsd_probe(struct g_part_table *table, struct g_consumer *cp) 2695aaa8fefSMarcel Moolenaar { 2705aaa8fefSMarcel Moolenaar struct g_provider *pp; 2715aaa8fefSMarcel Moolenaar u_char *buf; 2725aaa8fefSMarcel Moolenaar uint32_t magic1, magic2; 2735aaa8fefSMarcel Moolenaar int error; 2745aaa8fefSMarcel Moolenaar 2755aaa8fefSMarcel Moolenaar pp = cp->provider; 2765aaa8fefSMarcel Moolenaar 2775aaa8fefSMarcel Moolenaar /* Sanity-check the provider. */ 2785aaa8fefSMarcel Moolenaar if (pp->sectorsize < sizeof(struct disklabel) || 2795aaa8fefSMarcel Moolenaar pp->mediasize < BBSIZE) 2805aaa8fefSMarcel Moolenaar return (ENOSPC); 2815aaa8fefSMarcel Moolenaar 2825aaa8fefSMarcel Moolenaar /* Check that there's a disklabel. */ 2835aaa8fefSMarcel Moolenaar buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error); 2845aaa8fefSMarcel Moolenaar if (buf == NULL) 2855aaa8fefSMarcel Moolenaar return (error); 2865aaa8fefSMarcel Moolenaar magic1 = le32dec(buf + 0); 2875aaa8fefSMarcel Moolenaar magic2 = le32dec(buf + 132); 2885aaa8fefSMarcel Moolenaar g_free(buf); 2895aaa8fefSMarcel Moolenaar return ((magic1 == DISKMAGIC && magic2 == DISKMAGIC) 2905aaa8fefSMarcel Moolenaar ? G_PART_PROBE_PRI_NORM : ENXIO); 2915aaa8fefSMarcel Moolenaar } 2925aaa8fefSMarcel Moolenaar 2935aaa8fefSMarcel Moolenaar static int 2945aaa8fefSMarcel Moolenaar g_part_bsd_read(struct g_part_table *basetable, struct g_consumer *cp) 2955aaa8fefSMarcel Moolenaar { 2965aaa8fefSMarcel Moolenaar struct g_provider *pp; 2975aaa8fefSMarcel Moolenaar struct g_part_bsd_table *table; 2985aaa8fefSMarcel Moolenaar struct g_part_entry *baseentry; 2995aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 3005aaa8fefSMarcel Moolenaar struct partition part; 3015aaa8fefSMarcel Moolenaar u_char *buf, *p; 3025aaa8fefSMarcel Moolenaar off_t chs, msize; 3035aaa8fefSMarcel Moolenaar u_int sectors, heads; 3045aaa8fefSMarcel Moolenaar int error, index; 3055aaa8fefSMarcel Moolenaar 3065aaa8fefSMarcel Moolenaar pp = cp->provider; 3075aaa8fefSMarcel Moolenaar table = (struct g_part_bsd_table *)basetable; 3085aaa8fefSMarcel Moolenaar msize = pp->mediasize / pp->sectorsize; 3095aaa8fefSMarcel Moolenaar 3105aaa8fefSMarcel Moolenaar buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error); 3115aaa8fefSMarcel Moolenaar if (buf == NULL) 3125aaa8fefSMarcel Moolenaar return (error); 3135aaa8fefSMarcel Moolenaar 3145aaa8fefSMarcel Moolenaar table->label = buf; 3155aaa8fefSMarcel Moolenaar 3165aaa8fefSMarcel Moolenaar if (le32dec(buf + 40) != pp->sectorsize) 3175aaa8fefSMarcel Moolenaar goto invalid_label; 3185aaa8fefSMarcel Moolenaar sectors = le32dec(buf + 44); 3195aaa8fefSMarcel Moolenaar if (sectors < 1 || sectors > 63) 3205aaa8fefSMarcel Moolenaar goto invalid_label; 321392ffadeSMarcel Moolenaar if (sectors != basetable->gpt_sectors && !basetable->gpt_fixgeom) { 3225aaa8fefSMarcel Moolenaar g_part_geometry_heads(msize, sectors, &chs, &heads); 323392ffadeSMarcel Moolenaar if (chs != 0) { 3245aaa8fefSMarcel Moolenaar basetable->gpt_sectors = sectors; 3255aaa8fefSMarcel Moolenaar basetable->gpt_heads = heads; 3265aaa8fefSMarcel Moolenaar } 327392ffadeSMarcel Moolenaar } 3285aaa8fefSMarcel Moolenaar heads = le32dec(buf + 48); 3295aaa8fefSMarcel Moolenaar if (heads < 1 || heads > 255) 3305aaa8fefSMarcel Moolenaar goto invalid_label; 331392ffadeSMarcel Moolenaar if (heads != basetable->gpt_heads && !basetable->gpt_fixgeom) 3325aaa8fefSMarcel Moolenaar basetable->gpt_heads = heads; 333392ffadeSMarcel Moolenaar if (sectors != basetable->gpt_sectors || 334392ffadeSMarcel Moolenaar heads != basetable->gpt_heads) 335392ffadeSMarcel Moolenaar printf("GEOM: %s: geometry does not match label.\n", pp->name); 336392ffadeSMarcel Moolenaar 337392ffadeSMarcel Moolenaar chs = le32dec(buf + 60); 3385aaa8fefSMarcel Moolenaar if (chs < 1 || chs > msize) 3395aaa8fefSMarcel Moolenaar goto invalid_label; 340392ffadeSMarcel Moolenaar if (chs != msize) 341392ffadeSMarcel Moolenaar printf("GEOM: %s: media size does not match label.\n", 342392ffadeSMarcel Moolenaar pp->name); 3435aaa8fefSMarcel Moolenaar 3445aaa8fefSMarcel Moolenaar basetable->gpt_first = 0; 345392ffadeSMarcel Moolenaar basetable->gpt_last = msize - 1; 3465aaa8fefSMarcel Moolenaar basetable->gpt_isleaf = 1; 3475aaa8fefSMarcel Moolenaar 3485aaa8fefSMarcel Moolenaar basetable->gpt_entries = le16dec(buf + 138); 3495aaa8fefSMarcel Moolenaar if (basetable->gpt_entries < g_part_bsd_scheme.gps_minent || 3505aaa8fefSMarcel Moolenaar basetable->gpt_entries > g_part_bsd_scheme.gps_maxent) 3515aaa8fefSMarcel Moolenaar goto invalid_label; 3525aaa8fefSMarcel Moolenaar 353392ffadeSMarcel Moolenaar table->offset = le32dec(buf + 148 + RAW_PART * 16 + 4); 3545aaa8fefSMarcel Moolenaar for (index = basetable->gpt_entries - 1; index >= 0; index--) { 3555aaa8fefSMarcel Moolenaar p = buf + 148 + index * 16; 3565aaa8fefSMarcel Moolenaar part.p_size = le32dec(p + 0); 3575aaa8fefSMarcel Moolenaar part.p_offset = le32dec(p + 4); 3585aaa8fefSMarcel Moolenaar part.p_fsize = le32dec(p + 8); 3595aaa8fefSMarcel Moolenaar part.p_fstype = p[12]; 3605aaa8fefSMarcel Moolenaar part.p_frag = p[13]; 3615aaa8fefSMarcel Moolenaar part.p_cpg = le16dec(p + 14); 3625aaa8fefSMarcel Moolenaar if (part.p_size == 0) 3635aaa8fefSMarcel Moolenaar continue; 3645aaa8fefSMarcel Moolenaar if (part.p_fstype == FS_UNUSED && index != RAW_PART) 3655aaa8fefSMarcel Moolenaar continue; 366392ffadeSMarcel Moolenaar if (part.p_offset < table->offset) 3675aaa8fefSMarcel Moolenaar continue; 3685aaa8fefSMarcel Moolenaar baseentry = g_part_new_entry(basetable, index + 1, 369392ffadeSMarcel Moolenaar part.p_offset - table->offset, 370392ffadeSMarcel Moolenaar part.p_offset - table->offset + part.p_size - 1); 3715aaa8fefSMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 3725aaa8fefSMarcel Moolenaar entry->part = part; 3735aaa8fefSMarcel Moolenaar if (part.p_fstype == FS_UNUSED) 3745aaa8fefSMarcel Moolenaar baseentry->gpe_internal = 1; 3755aaa8fefSMarcel Moolenaar } 3765aaa8fefSMarcel Moolenaar 3775aaa8fefSMarcel Moolenaar return (0); 3785aaa8fefSMarcel Moolenaar 3795aaa8fefSMarcel Moolenaar invalid_label: 3805aaa8fefSMarcel Moolenaar printf("GEOM: %s: invalid disklabel.\n", pp->name); 3815aaa8fefSMarcel Moolenaar g_free(table->label); 3825aaa8fefSMarcel Moolenaar return (EINVAL); 3835aaa8fefSMarcel Moolenaar } 3845aaa8fefSMarcel Moolenaar 3855aaa8fefSMarcel Moolenaar static const char * 3865aaa8fefSMarcel Moolenaar g_part_bsd_type(struct g_part_table *basetable, struct g_part_entry *baseentry, 3875aaa8fefSMarcel Moolenaar char *buf, size_t bufsz) 3885aaa8fefSMarcel Moolenaar { 3895aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 3905aaa8fefSMarcel Moolenaar int type; 3915aaa8fefSMarcel Moolenaar 3925aaa8fefSMarcel Moolenaar entry = (struct g_part_bsd_entry *)baseentry; 3935aaa8fefSMarcel Moolenaar type = entry->part.p_fstype; 3945aaa8fefSMarcel Moolenaar if (type == FS_SWAP) 3955aaa8fefSMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_SWAP)); 3965aaa8fefSMarcel Moolenaar if (type == FS_BSDFFS) 3975aaa8fefSMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_UFS)); 3985aaa8fefSMarcel Moolenaar if (type == FS_VINUM) 3995aaa8fefSMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_VINUM)); 400ddba2641SMarcel Moolenaar if (type == FS_ZFS) 401ddba2641SMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_ZFS)); 4025aaa8fefSMarcel Moolenaar snprintf(buf, bufsz, "!%d", type); 4035aaa8fefSMarcel Moolenaar return (buf); 4045aaa8fefSMarcel Moolenaar } 4055aaa8fefSMarcel Moolenaar 4065aaa8fefSMarcel Moolenaar static int 4075aaa8fefSMarcel Moolenaar g_part_bsd_write(struct g_part_table *basetable, struct g_consumer *cp) 4085aaa8fefSMarcel Moolenaar { 4095aaa8fefSMarcel Moolenaar struct g_provider *pp; 4105aaa8fefSMarcel Moolenaar struct g_part_entry *baseentry; 4115aaa8fefSMarcel Moolenaar struct g_part_bsd_entry *entry; 4125aaa8fefSMarcel Moolenaar struct g_part_bsd_table *table; 4135aaa8fefSMarcel Moolenaar uint16_t sum; 4145aaa8fefSMarcel Moolenaar u_char *p, *pe; 4155aaa8fefSMarcel Moolenaar int error, index; 4165aaa8fefSMarcel Moolenaar 4175aaa8fefSMarcel Moolenaar pp = cp->provider; 4185aaa8fefSMarcel Moolenaar table = (struct g_part_bsd_table *)basetable; 4195aaa8fefSMarcel Moolenaar baseentry = LIST_FIRST(&basetable->gpt_entry); 4205aaa8fefSMarcel Moolenaar for (index = 1; index <= basetable->gpt_entries; index++) { 4215aaa8fefSMarcel Moolenaar p = table->label + 148 + (index - 1) * 16; 4225aaa8fefSMarcel Moolenaar entry = (baseentry != NULL && index == baseentry->gpe_index) 4235aaa8fefSMarcel Moolenaar ? (struct g_part_bsd_entry *)baseentry : NULL; 4245aaa8fefSMarcel Moolenaar if (entry != NULL && !baseentry->gpe_deleted) { 4255aaa8fefSMarcel Moolenaar le32enc(p + 0, entry->part.p_size); 4265aaa8fefSMarcel Moolenaar le32enc(p + 4, entry->part.p_offset); 4275aaa8fefSMarcel Moolenaar le32enc(p + 8, entry->part.p_fsize); 4285aaa8fefSMarcel Moolenaar p[12] = entry->part.p_fstype; 4295aaa8fefSMarcel Moolenaar p[13] = entry->part.p_frag; 4305aaa8fefSMarcel Moolenaar le16enc(p + 14, entry->part.p_cpg); 4315aaa8fefSMarcel Moolenaar } else 4325aaa8fefSMarcel Moolenaar bzero(p, 16); 4335aaa8fefSMarcel Moolenaar 4345aaa8fefSMarcel Moolenaar if (entry != NULL) 4355aaa8fefSMarcel Moolenaar baseentry = LIST_NEXT(baseentry, gpe_entry); 4365aaa8fefSMarcel Moolenaar } 4375aaa8fefSMarcel Moolenaar 4385aaa8fefSMarcel Moolenaar /* Calculate checksum. */ 4395aaa8fefSMarcel Moolenaar le16enc(table->label + 136, 0); 4405aaa8fefSMarcel Moolenaar pe = table->label + 148 + basetable->gpt_entries * 16; 4415aaa8fefSMarcel Moolenaar sum = 0; 4425aaa8fefSMarcel Moolenaar for (p = table->label; p < pe; p += 2) 4435aaa8fefSMarcel Moolenaar sum ^= le16dec(p); 4445aaa8fefSMarcel Moolenaar le16enc(table->label + 136, sum); 4455aaa8fefSMarcel Moolenaar 4465aaa8fefSMarcel Moolenaar error = g_write_data(cp, pp->sectorsize, table->label, pp->sectorsize); 4475aaa8fefSMarcel Moolenaar return (error); 4485aaa8fefSMarcel Moolenaar } 449