11d3aed33SMarcel Moolenaar /*- 21d3aed33SMarcel Moolenaar * Copyright (c) 2006, 2007 Marcel Moolenaar 31d3aed33SMarcel Moolenaar * All rights reserved. 41d3aed33SMarcel Moolenaar * 51d3aed33SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 61d3aed33SMarcel Moolenaar * modification, are permitted provided that the following conditions 71d3aed33SMarcel Moolenaar * are met: 81d3aed33SMarcel Moolenaar * 91d3aed33SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 101d3aed33SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 111d3aed33SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 121d3aed33SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 131d3aed33SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 141d3aed33SMarcel Moolenaar * 151d3aed33SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 161d3aed33SMarcel Moolenaar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 171d3aed33SMarcel Moolenaar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 181d3aed33SMarcel Moolenaar * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 191d3aed33SMarcel Moolenaar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 201d3aed33SMarcel Moolenaar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 211d3aed33SMarcel Moolenaar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 221d3aed33SMarcel Moolenaar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 231d3aed33SMarcel Moolenaar * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 241d3aed33SMarcel Moolenaar * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 251d3aed33SMarcel Moolenaar */ 261d3aed33SMarcel Moolenaar 271d3aed33SMarcel Moolenaar #include <sys/cdefs.h> 281d3aed33SMarcel Moolenaar __FBSDID("$FreeBSD$"); 291d3aed33SMarcel Moolenaar 301d3aed33SMarcel Moolenaar #include <sys/param.h> 311d3aed33SMarcel Moolenaar #include <sys/apm.h> 321d3aed33SMarcel Moolenaar #include <sys/bio.h> 331d3aed33SMarcel Moolenaar #include <sys/diskmbr.h> 341d3aed33SMarcel Moolenaar #include <sys/endian.h> 351d3aed33SMarcel Moolenaar #include <sys/kernel.h> 361d3aed33SMarcel Moolenaar #include <sys/kobj.h> 371d3aed33SMarcel Moolenaar #include <sys/limits.h> 381d3aed33SMarcel Moolenaar #include <sys/lock.h> 391d3aed33SMarcel Moolenaar #include <sys/malloc.h> 401d3aed33SMarcel Moolenaar #include <sys/mutex.h> 411d3aed33SMarcel Moolenaar #include <sys/queue.h> 421d3aed33SMarcel Moolenaar #include <sys/sbuf.h> 431d3aed33SMarcel Moolenaar #include <sys/systm.h> 441d3aed33SMarcel Moolenaar #include <geom/geom.h> 451d3aed33SMarcel Moolenaar #include <geom/part/g_part.h> 461d3aed33SMarcel Moolenaar 471d3aed33SMarcel Moolenaar #include "g_part_if.h" 481d3aed33SMarcel Moolenaar 491d3aed33SMarcel Moolenaar struct g_part_apm_table { 501d3aed33SMarcel Moolenaar struct g_part_table base; 511d3aed33SMarcel Moolenaar struct apm_ddr ddr; 521d3aed33SMarcel Moolenaar struct apm_ent self; 531d3aed33SMarcel Moolenaar }; 541d3aed33SMarcel Moolenaar 551d3aed33SMarcel Moolenaar struct g_part_apm_entry { 561d3aed33SMarcel Moolenaar struct g_part_entry base; 571d3aed33SMarcel Moolenaar struct apm_ent ent; 581d3aed33SMarcel Moolenaar }; 591d3aed33SMarcel Moolenaar 601d3aed33SMarcel Moolenaar static int g_part_apm_add(struct g_part_table *, struct g_part_entry *, 611d3aed33SMarcel Moolenaar struct g_part_parms *); 621d3aed33SMarcel Moolenaar static int g_part_apm_create(struct g_part_table *, struct g_part_parms *); 631d3aed33SMarcel Moolenaar static int g_part_apm_destroy(struct g_part_table *, struct g_part_parms *); 641d3aed33SMarcel Moolenaar static int g_part_apm_dumpto(struct g_part_table *, struct g_part_entry *); 651d3aed33SMarcel Moolenaar static int g_part_apm_modify(struct g_part_table *, struct g_part_entry *, 661d3aed33SMarcel Moolenaar struct g_part_parms *); 671d3aed33SMarcel Moolenaar static char *g_part_apm_name(struct g_part_table *, struct g_part_entry *, 681d3aed33SMarcel Moolenaar char *, size_t); 691d3aed33SMarcel Moolenaar static int g_part_apm_probe(struct g_part_table *, struct g_consumer *); 701d3aed33SMarcel Moolenaar static int g_part_apm_read(struct g_part_table *, struct g_consumer *); 711d3aed33SMarcel Moolenaar static const char *g_part_apm_type(struct g_part_table *, struct g_part_entry *, 721d3aed33SMarcel Moolenaar char *, size_t); 731d3aed33SMarcel Moolenaar static int g_part_apm_write(struct g_part_table *, struct g_consumer *); 741d3aed33SMarcel Moolenaar 751d3aed33SMarcel Moolenaar static kobj_method_t g_part_apm_methods[] = { 761d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_add, g_part_apm_add), 771d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_create, g_part_apm_create), 781d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_destroy, g_part_apm_destroy), 791d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_dumpto, g_part_apm_dumpto), 801d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_modify, g_part_apm_modify), 811d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_name, g_part_apm_name), 821d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_probe, g_part_apm_probe), 831d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_read, g_part_apm_read), 841d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_type, g_part_apm_type), 851d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_write, g_part_apm_write), 861d3aed33SMarcel Moolenaar { 0, 0 } 871d3aed33SMarcel Moolenaar }; 881d3aed33SMarcel Moolenaar 891d3aed33SMarcel Moolenaar static struct g_part_scheme g_part_apm_scheme = { 901d3aed33SMarcel Moolenaar "APM", 911d3aed33SMarcel Moolenaar g_part_apm_methods, 921d3aed33SMarcel Moolenaar sizeof(struct g_part_apm_table), 931d3aed33SMarcel Moolenaar .gps_entrysz = sizeof(struct g_part_apm_entry), 941d3aed33SMarcel Moolenaar .gps_minent = 16, 951d3aed33SMarcel Moolenaar .gps_maxent = INT_MAX, 961d3aed33SMarcel Moolenaar }; 971d3aed33SMarcel Moolenaar G_PART_SCHEME_DECLARE(g_part_apm_scheme); 981d3aed33SMarcel Moolenaar 991d3aed33SMarcel Moolenaar static int 1001d3aed33SMarcel Moolenaar apm_parse_type(const char *type, char *buf, size_t bufsz) 1011d3aed33SMarcel Moolenaar { 102d287f590SMarcel Moolenaar const char *alias; 1031d3aed33SMarcel Moolenaar 104d287f590SMarcel Moolenaar if (type[0] == '!') { 105d287f590SMarcel Moolenaar type++; 1061d3aed33SMarcel Moolenaar if (strlen(type) > bufsz) 1071d3aed33SMarcel Moolenaar return (EINVAL); 1081d3aed33SMarcel Moolenaar if (!strcmp(type, APM_ENT_TYPE_SELF) || 1091d3aed33SMarcel Moolenaar !strcmp(type, APM_ENT_TYPE_UNUSED)) 1101d3aed33SMarcel Moolenaar return (EINVAL); 1111d3aed33SMarcel Moolenaar strncpy(buf, type, bufsz); 1121d3aed33SMarcel Moolenaar return (0); 1131d3aed33SMarcel Moolenaar } 114d287f590SMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD); 115d287f590SMarcel Moolenaar if (!strcasecmp(type, alias)) { 1161d3aed33SMarcel Moolenaar strcpy(buf, APM_ENT_TYPE_FREEBSD); 1171d3aed33SMarcel Moolenaar return (0); 1181d3aed33SMarcel Moolenaar } 119d287f590SMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_SWAP); 120d287f590SMarcel Moolenaar if (!strcasecmp(type, alias)) { 121d287f590SMarcel Moolenaar strcpy(buf, APM_ENT_TYPE_FREEBSD_SWAP); 122d287f590SMarcel Moolenaar return (0); 123d287f590SMarcel Moolenaar } 124d287f590SMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_UFS); 125d287f590SMarcel Moolenaar if (!strcasecmp(type, alias)) { 126d287f590SMarcel Moolenaar strcpy(buf, APM_ENT_TYPE_FREEBSD_UFS); 127d287f590SMarcel Moolenaar return (0); 128d287f590SMarcel Moolenaar } 129d287f590SMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_VINUM); 130d287f590SMarcel Moolenaar if (!strcasecmp(type, alias)) { 131d287f590SMarcel Moolenaar strcpy(buf, APM_ENT_TYPE_FREEBSD_VINUM); 132d287f590SMarcel Moolenaar return (0); 133d287f590SMarcel Moolenaar } 134d287f590SMarcel Moolenaar return (EINVAL); 135d287f590SMarcel Moolenaar } 1361d3aed33SMarcel Moolenaar 1371d3aed33SMarcel Moolenaar static int 1381d3aed33SMarcel Moolenaar apm_read_ent(struct g_consumer *cp, uint32_t blk, struct apm_ent *ent) 1391d3aed33SMarcel Moolenaar { 1401d3aed33SMarcel Moolenaar struct g_provider *pp; 1411d3aed33SMarcel Moolenaar char *buf; 1421d3aed33SMarcel Moolenaar int error; 1431d3aed33SMarcel Moolenaar 1441d3aed33SMarcel Moolenaar pp = cp->provider; 1451d3aed33SMarcel Moolenaar buf = g_read_data(cp, pp->sectorsize * blk, pp->sectorsize, &error); 1461d3aed33SMarcel Moolenaar if (buf == NULL) 1471d3aed33SMarcel Moolenaar return (error); 1481d3aed33SMarcel Moolenaar ent->ent_sig = be16dec(buf); 1491d3aed33SMarcel Moolenaar ent->ent_pmblkcnt = be32dec(buf + 4); 1501d3aed33SMarcel Moolenaar ent->ent_start = be32dec(buf + 8); 1511d3aed33SMarcel Moolenaar ent->ent_size = be32dec(buf + 12); 1521d3aed33SMarcel Moolenaar bcopy(buf + 16, ent->ent_name, sizeof(ent->ent_name)); 1531d3aed33SMarcel Moolenaar bcopy(buf + 48, ent->ent_type, sizeof(ent->ent_type)); 1541d3aed33SMarcel Moolenaar g_free(buf); 1551d3aed33SMarcel Moolenaar return (0); 1561d3aed33SMarcel Moolenaar } 1571d3aed33SMarcel Moolenaar 1581d3aed33SMarcel Moolenaar static int 1591d3aed33SMarcel Moolenaar g_part_apm_add(struct g_part_table *basetable, struct g_part_entry *baseentry, 1601d3aed33SMarcel Moolenaar struct g_part_parms *gpp) 1611d3aed33SMarcel Moolenaar { 1621d3aed33SMarcel Moolenaar struct g_part_apm_entry *entry; 1631d3aed33SMarcel Moolenaar struct g_part_apm_table *table; 1641d3aed33SMarcel Moolenaar int error; 1651d3aed33SMarcel Moolenaar 1661d3aed33SMarcel Moolenaar entry = (struct g_part_apm_entry *)baseentry; 1671d3aed33SMarcel Moolenaar table = (struct g_part_apm_table *)basetable; 1681d3aed33SMarcel Moolenaar entry->ent.ent_sig = APM_ENT_SIG; 1691d3aed33SMarcel Moolenaar entry->ent.ent_pmblkcnt = table->self.ent_pmblkcnt; 1701d3aed33SMarcel Moolenaar entry->ent.ent_start = gpp->gpp_start; 1711d3aed33SMarcel Moolenaar entry->ent.ent_size = gpp->gpp_size; 1721d3aed33SMarcel Moolenaar if (baseentry->gpe_deleted) { 1731d3aed33SMarcel Moolenaar bzero(entry->ent.ent_type, sizeof(entry->ent.ent_type)); 1741d3aed33SMarcel Moolenaar bzero(entry->ent.ent_name, sizeof(entry->ent.ent_name)); 1751d3aed33SMarcel Moolenaar } 1761d3aed33SMarcel Moolenaar error = apm_parse_type(gpp->gpp_type, entry->ent.ent_type, 1771d3aed33SMarcel Moolenaar sizeof(entry->ent.ent_type)); 1781d3aed33SMarcel Moolenaar if (error) 1791d3aed33SMarcel Moolenaar return (error); 1801d3aed33SMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_LABEL) { 1811d3aed33SMarcel Moolenaar if (strlen(gpp->gpp_label) > sizeof(entry->ent.ent_name)) 1821d3aed33SMarcel Moolenaar return (EINVAL); 1831d3aed33SMarcel Moolenaar strncpy(entry->ent.ent_name, gpp->gpp_label, 1841d3aed33SMarcel Moolenaar sizeof(entry->ent.ent_name)); 1851d3aed33SMarcel Moolenaar } 1861d3aed33SMarcel Moolenaar return (0); 1871d3aed33SMarcel Moolenaar } 1881d3aed33SMarcel Moolenaar 1891d3aed33SMarcel Moolenaar static int 1901d3aed33SMarcel Moolenaar g_part_apm_create(struct g_part_table *basetable, struct g_part_parms *gpp) 1911d3aed33SMarcel Moolenaar { 1921d3aed33SMarcel Moolenaar struct g_provider *pp; 1931d3aed33SMarcel Moolenaar struct g_part_apm_table *table; 1941d3aed33SMarcel Moolenaar 1951d3aed33SMarcel Moolenaar table = (struct g_part_apm_table *)basetable; 1961d3aed33SMarcel Moolenaar pp = gpp->gpp_provider; 1971d3aed33SMarcel Moolenaar if (pp->sectorsize != 512 || 1981d3aed33SMarcel Moolenaar pp->mediasize < (2 + 2 * basetable->gpt_entries) * pp->sectorsize) 1991d3aed33SMarcel Moolenaar return (ENOSPC); 2001d3aed33SMarcel Moolenaar 2011d3aed33SMarcel Moolenaar basetable->gpt_first = 2 + basetable->gpt_entries; 2021d3aed33SMarcel Moolenaar basetable->gpt_last = (pp->mediasize / pp->sectorsize) - 1; 2031d3aed33SMarcel Moolenaar 2041d3aed33SMarcel Moolenaar table->ddr.ddr_sig = APM_DDR_SIG; 2051d3aed33SMarcel Moolenaar table->ddr.ddr_blksize = pp->sectorsize; 2061d3aed33SMarcel Moolenaar table->ddr.ddr_blkcount = basetable->gpt_last + 1; 2071d3aed33SMarcel Moolenaar 2081d3aed33SMarcel Moolenaar table->self.ent_sig = APM_ENT_SIG; 2091d3aed33SMarcel Moolenaar table->self.ent_pmblkcnt = basetable->gpt_entries + 1; 2101d3aed33SMarcel Moolenaar table->self.ent_start = 1; 2111d3aed33SMarcel Moolenaar table->self.ent_size = table->self.ent_pmblkcnt; 2121d3aed33SMarcel Moolenaar strcpy(table->self.ent_name, "Apple"); 2131d3aed33SMarcel Moolenaar strcpy(table->self.ent_type, APM_ENT_TYPE_SELF); 2141d3aed33SMarcel Moolenaar return (0); 2151d3aed33SMarcel Moolenaar } 2161d3aed33SMarcel Moolenaar 2171d3aed33SMarcel Moolenaar static int 2181d3aed33SMarcel Moolenaar g_part_apm_destroy(struct g_part_table *basetable, struct g_part_parms *gpp) 2191d3aed33SMarcel Moolenaar { 2201d3aed33SMarcel Moolenaar 2211d3aed33SMarcel Moolenaar /* Wipe the first 2 sectors to clear the partitioning. */ 2221d3aed33SMarcel Moolenaar basetable->gpt_smhead |= 3; 2231d3aed33SMarcel Moolenaar return (0); 2241d3aed33SMarcel Moolenaar } 2251d3aed33SMarcel Moolenaar 2261d3aed33SMarcel Moolenaar static int 2271d3aed33SMarcel Moolenaar g_part_apm_dumpto(struct g_part_table *table, struct g_part_entry *baseentry) 2281d3aed33SMarcel Moolenaar { 2291d3aed33SMarcel Moolenaar struct g_part_apm_entry *entry; 2301d3aed33SMarcel Moolenaar 2311d3aed33SMarcel Moolenaar entry = (struct g_part_apm_entry *)baseentry; 2321d3aed33SMarcel Moolenaar return ((!strcmp(entry->ent.ent_type, APM_ENT_TYPE_FREEBSD_SWAP)) 2331d3aed33SMarcel Moolenaar ? 1 : 0); 2341d3aed33SMarcel Moolenaar } 2351d3aed33SMarcel Moolenaar 2361d3aed33SMarcel Moolenaar static int 2371d3aed33SMarcel Moolenaar g_part_apm_modify(struct g_part_table *basetable, 2381d3aed33SMarcel Moolenaar struct g_part_entry *baseentry, struct g_part_parms *gpp) 2391d3aed33SMarcel Moolenaar { 2401d3aed33SMarcel Moolenaar struct g_part_apm_entry *entry; 2411d3aed33SMarcel Moolenaar int error; 2421d3aed33SMarcel Moolenaar 2431d3aed33SMarcel Moolenaar entry = (struct g_part_apm_entry *)baseentry; 2441d3aed33SMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_LABEL) { 2451d3aed33SMarcel Moolenaar if (strlen(gpp->gpp_label) > sizeof(entry->ent.ent_name)) 2461d3aed33SMarcel Moolenaar return (EINVAL); 2471d3aed33SMarcel Moolenaar } 2481d3aed33SMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_TYPE) { 2491d3aed33SMarcel Moolenaar error = apm_parse_type(gpp->gpp_type, entry->ent.ent_type, 2501d3aed33SMarcel Moolenaar sizeof(entry->ent.ent_type)); 2511d3aed33SMarcel Moolenaar if (error) 2521d3aed33SMarcel Moolenaar return (error); 2531d3aed33SMarcel Moolenaar } 2541d3aed33SMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_LABEL) { 2551d3aed33SMarcel Moolenaar strncpy(entry->ent.ent_name, gpp->gpp_label, 2561d3aed33SMarcel Moolenaar sizeof(entry->ent.ent_name)); 2571d3aed33SMarcel Moolenaar } 2581d3aed33SMarcel Moolenaar return (0); 2591d3aed33SMarcel Moolenaar } 2601d3aed33SMarcel Moolenaar 2611d3aed33SMarcel Moolenaar static char * 2621d3aed33SMarcel Moolenaar g_part_apm_name(struct g_part_table *table, struct g_part_entry *baseentry, 2631d3aed33SMarcel Moolenaar char *buf, size_t bufsz) 2641d3aed33SMarcel Moolenaar { 2651d3aed33SMarcel Moolenaar 2661d3aed33SMarcel Moolenaar snprintf(buf, bufsz, "s%d", baseentry->gpe_index + 1); 2671d3aed33SMarcel Moolenaar return (buf); 2681d3aed33SMarcel Moolenaar } 2691d3aed33SMarcel Moolenaar 2701d3aed33SMarcel Moolenaar static int 2711d3aed33SMarcel Moolenaar g_part_apm_probe(struct g_part_table *basetable, struct g_consumer *cp) 2721d3aed33SMarcel Moolenaar { 2731d3aed33SMarcel Moolenaar struct g_provider *pp; 2741d3aed33SMarcel Moolenaar struct g_part_apm_table *table; 2751d3aed33SMarcel Moolenaar char *buf; 2761d3aed33SMarcel Moolenaar int error; 2771d3aed33SMarcel Moolenaar 2781d3aed33SMarcel Moolenaar /* We don't nest, which means that our depth should be 0. */ 2791d3aed33SMarcel Moolenaar if (basetable->gpt_depth != 0) 2801d3aed33SMarcel Moolenaar return (ENXIO); 2811d3aed33SMarcel Moolenaar 2821d3aed33SMarcel Moolenaar table = (struct g_part_apm_table *)basetable; 2831d3aed33SMarcel Moolenaar pp = cp->provider; 2841d3aed33SMarcel Moolenaar 2851d3aed33SMarcel Moolenaar /* Sanity-check the provider. */ 2861d3aed33SMarcel Moolenaar if (pp->mediasize < 4 * pp->sectorsize) 2871d3aed33SMarcel Moolenaar return (ENOSPC); 2881d3aed33SMarcel Moolenaar 2891d3aed33SMarcel Moolenaar /* Check that there's a Driver Descriptor Record (DDR). */ 2901d3aed33SMarcel Moolenaar buf = g_read_data(cp, 0L, pp->sectorsize, &error); 2911d3aed33SMarcel Moolenaar if (buf == NULL) 2921d3aed33SMarcel Moolenaar return (error); 2931d3aed33SMarcel Moolenaar table->ddr.ddr_sig = be16dec(buf); 2941d3aed33SMarcel Moolenaar table->ddr.ddr_blksize = be16dec(buf + 2); 2951d3aed33SMarcel Moolenaar table->ddr.ddr_blkcount = be32dec(buf + 4); 2961d3aed33SMarcel Moolenaar g_free(buf); 2971d3aed33SMarcel Moolenaar if (table->ddr.ddr_sig != APM_DDR_SIG) 2981d3aed33SMarcel Moolenaar return (ENXIO); 2991d3aed33SMarcel Moolenaar if (table->ddr.ddr_blksize != pp->sectorsize) 3001d3aed33SMarcel Moolenaar return (ENXIO); 3011d3aed33SMarcel Moolenaar 3021d3aed33SMarcel Moolenaar /* Check that there's a Partition Map. */ 3031d3aed33SMarcel Moolenaar error = apm_read_ent(cp, 1, &table->self); 3041d3aed33SMarcel Moolenaar if (error) 3051d3aed33SMarcel Moolenaar return (error); 3061d3aed33SMarcel Moolenaar if (table->self.ent_sig != APM_ENT_SIG) 3071d3aed33SMarcel Moolenaar return (ENXIO); 3081d3aed33SMarcel Moolenaar if (strcmp(table->self.ent_type, APM_ENT_TYPE_SELF)) 3091d3aed33SMarcel Moolenaar return (ENXIO); 3101d3aed33SMarcel Moolenaar if (table->self.ent_pmblkcnt >= table->ddr.ddr_blkcount) 3111d3aed33SMarcel Moolenaar return (ENXIO); 3121d3aed33SMarcel Moolenaar return (G_PART_PROBE_PRI_NORM); 3131d3aed33SMarcel Moolenaar } 3141d3aed33SMarcel Moolenaar 3151d3aed33SMarcel Moolenaar static int 3161d3aed33SMarcel Moolenaar g_part_apm_read(struct g_part_table *basetable, struct g_consumer *cp) 3171d3aed33SMarcel Moolenaar { 3181d3aed33SMarcel Moolenaar struct apm_ent ent; 3191d3aed33SMarcel Moolenaar struct g_part_apm_entry *entry; 3201d3aed33SMarcel Moolenaar struct g_part_apm_table *table; 3211d3aed33SMarcel Moolenaar int error, index; 3221d3aed33SMarcel Moolenaar 3231d3aed33SMarcel Moolenaar table = (struct g_part_apm_table *)basetable; 3241d3aed33SMarcel Moolenaar 3251d3aed33SMarcel Moolenaar basetable->gpt_first = table->self.ent_pmblkcnt + 1; 3261d3aed33SMarcel Moolenaar basetable->gpt_last = table->ddr.ddr_blkcount - 1; 3271d3aed33SMarcel Moolenaar basetable->gpt_entries = table->self.ent_pmblkcnt - 1; 3281d3aed33SMarcel Moolenaar 3291d3aed33SMarcel Moolenaar for (index = table->self.ent_pmblkcnt - 1; index > 0; index--) { 3301d3aed33SMarcel Moolenaar error = apm_read_ent(cp, index + 1, &ent); 3311d3aed33SMarcel Moolenaar if (error) 3321d3aed33SMarcel Moolenaar continue; 3331d3aed33SMarcel Moolenaar if (!strcmp(ent.ent_type, APM_ENT_TYPE_UNUSED)) 3341d3aed33SMarcel Moolenaar continue; 3351d3aed33SMarcel Moolenaar entry = (struct g_part_apm_entry *)g_part_new_entry(basetable, 3361d3aed33SMarcel Moolenaar index, ent.ent_start, ent.ent_start + ent.ent_size - 1); 3371d3aed33SMarcel Moolenaar entry->ent = ent; 3381d3aed33SMarcel Moolenaar } 3391d3aed33SMarcel Moolenaar 3401d3aed33SMarcel Moolenaar return (0); 3411d3aed33SMarcel Moolenaar } 3421d3aed33SMarcel Moolenaar 3431d3aed33SMarcel Moolenaar static const char * 3441d3aed33SMarcel Moolenaar g_part_apm_type(struct g_part_table *basetable, struct g_part_entry *baseentry, 3451d3aed33SMarcel Moolenaar char *buf, size_t bufsz) 3461d3aed33SMarcel Moolenaar { 3471d3aed33SMarcel Moolenaar struct g_part_apm_entry *entry; 3481d3aed33SMarcel Moolenaar const char *type; 3491d3aed33SMarcel Moolenaar size_t len; 3501d3aed33SMarcel Moolenaar 3511d3aed33SMarcel Moolenaar entry = (struct g_part_apm_entry *)baseentry; 3521d3aed33SMarcel Moolenaar type = entry->ent.ent_type; 3531d3aed33SMarcel Moolenaar if (!strcmp(type, APM_ENT_TYPE_FREEBSD)) 3541d3aed33SMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD)); 3551d3aed33SMarcel Moolenaar if (!strcmp(type, APM_ENT_TYPE_FREEBSD_SWAP)) 3561d3aed33SMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_SWAP)); 3571d3aed33SMarcel Moolenaar if (!strcmp(type, APM_ENT_TYPE_FREEBSD_UFS)) 3581d3aed33SMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_UFS)); 3591d3aed33SMarcel Moolenaar if (!strcmp(type, APM_ENT_TYPE_FREEBSD_VINUM)) 3601d3aed33SMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_VINUM)); 361cf231470SMarcel Moolenaar buf[0] = '!'; 362cf231470SMarcel Moolenaar len = MIN(sizeof(entry->ent.ent_type), bufsz - 2); 363cf231470SMarcel Moolenaar bcopy(type, buf + 1, len); 364cf231470SMarcel Moolenaar buf[len + 1] = '\0'; 3651d3aed33SMarcel Moolenaar return (buf); 3661d3aed33SMarcel Moolenaar } 3671d3aed33SMarcel Moolenaar 3681d3aed33SMarcel Moolenaar static int 3691d3aed33SMarcel Moolenaar g_part_apm_write(struct g_part_table *basetable, struct g_consumer *cp) 3701d3aed33SMarcel Moolenaar { 3711d3aed33SMarcel Moolenaar char buf[512]; 3721d3aed33SMarcel Moolenaar struct g_part_entry *baseentry; 3731d3aed33SMarcel Moolenaar struct g_part_apm_entry *entry; 3741d3aed33SMarcel Moolenaar struct g_part_apm_table *table; 3751d3aed33SMarcel Moolenaar int error, index; 3761d3aed33SMarcel Moolenaar 3771d3aed33SMarcel Moolenaar table = (struct g_part_apm_table *)basetable; 3781d3aed33SMarcel Moolenaar bzero(buf, sizeof(buf)); 3791d3aed33SMarcel Moolenaar 3801d3aed33SMarcel Moolenaar /* Write the DDR and 'self' entry only when we're newly created. */ 3811d3aed33SMarcel Moolenaar if (basetable->gpt_created) { 3821d3aed33SMarcel Moolenaar be16enc(buf, table->ddr.ddr_sig); 3831d3aed33SMarcel Moolenaar be16enc(buf + 2, table->ddr.ddr_blksize); 3841d3aed33SMarcel Moolenaar be32enc(buf + 4, table->ddr.ddr_blkcount); 3851d3aed33SMarcel Moolenaar error = g_write_data(cp, 0, buf, sizeof(buf)); 3861d3aed33SMarcel Moolenaar if (error) 3871d3aed33SMarcel Moolenaar return (error); 3881d3aed33SMarcel Moolenaar } 3891d3aed33SMarcel Moolenaar 3901d3aed33SMarcel Moolenaar be16enc(buf, table->self.ent_sig); 3911d3aed33SMarcel Moolenaar be16enc(buf + 2, 0); 3921d3aed33SMarcel Moolenaar be32enc(buf + 4, table->self.ent_pmblkcnt); 3931d3aed33SMarcel Moolenaar 3941d3aed33SMarcel Moolenaar if (basetable->gpt_created) { 3951d3aed33SMarcel Moolenaar be32enc(buf + 8, table->self.ent_start); 3961d3aed33SMarcel Moolenaar be32enc(buf + 12, table->self.ent_size); 3971d3aed33SMarcel Moolenaar bcopy(table->self.ent_name, buf + 16, 3981d3aed33SMarcel Moolenaar sizeof(table->self.ent_name)); 3991d3aed33SMarcel Moolenaar bcopy(table->self.ent_type, buf + 48, 4001d3aed33SMarcel Moolenaar sizeof(table->self.ent_type)); 4011d3aed33SMarcel Moolenaar error = g_write_data(cp, 512, buf, sizeof(buf)); 4021d3aed33SMarcel Moolenaar if (error) 4031d3aed33SMarcel Moolenaar return (error); 4041d3aed33SMarcel Moolenaar } 4051d3aed33SMarcel Moolenaar 4061d3aed33SMarcel Moolenaar baseentry = LIST_FIRST(&basetable->gpt_entry); 4071d3aed33SMarcel Moolenaar for (index = 1; index <= basetable->gpt_entries; index++) { 408d287f590SMarcel Moolenaar entry = (baseentry != NULL && index == baseentry->gpe_index) 409d287f590SMarcel Moolenaar ? (struct g_part_apm_entry *)baseentry : NULL; 410d287f590SMarcel Moolenaar if (entry != NULL && !baseentry->gpe_deleted) { 4111d3aed33SMarcel Moolenaar be32enc(buf + 8, entry->ent.ent_start); 4121d3aed33SMarcel Moolenaar be32enc(buf + 12, entry->ent.ent_size); 4131d3aed33SMarcel Moolenaar bcopy(entry->ent.ent_name, buf + 16, 4141d3aed33SMarcel Moolenaar sizeof(entry->ent.ent_name)); 4151d3aed33SMarcel Moolenaar bcopy(entry->ent.ent_type, buf + 48, 4161d3aed33SMarcel Moolenaar sizeof(entry->ent.ent_type)); 4171d3aed33SMarcel Moolenaar } else { 4181d3aed33SMarcel Moolenaar bzero(buf + 8, 4 + 4 + 32 + 32); 4191d3aed33SMarcel Moolenaar strcpy(buf + 48, APM_ENT_TYPE_UNUSED); 4201d3aed33SMarcel Moolenaar } 4211d3aed33SMarcel Moolenaar error = g_write_data(cp, (index + 1) * 512, buf, sizeof(buf)); 4221d3aed33SMarcel Moolenaar if (error) 4231d3aed33SMarcel Moolenaar return (error); 424d287f590SMarcel Moolenaar if (entry != NULL) 425d287f590SMarcel Moolenaar baseentry = LIST_NEXT(baseentry, gpe_entry); 4261d3aed33SMarcel Moolenaar } 4271d3aed33SMarcel Moolenaar 4281d3aed33SMarcel Moolenaar return (0); 4291d3aed33SMarcel Moolenaar } 430