11d3aed33SMarcel Moolenaar /*- 21d3aed33SMarcel Moolenaar * Copyright (c) 2002, 2005, 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/bio.h> 321d3aed33SMarcel Moolenaar #include <sys/diskmbr.h> 331d3aed33SMarcel Moolenaar #include <sys/endian.h> 341d3aed33SMarcel Moolenaar #include <sys/gpt.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 <sys/uuid.h> 451d3aed33SMarcel Moolenaar #include <geom/geom.h> 461d3aed33SMarcel Moolenaar #include <geom/part/g_part.h> 471d3aed33SMarcel Moolenaar 481d3aed33SMarcel Moolenaar #include "g_part_if.h" 491d3aed33SMarcel Moolenaar 501d3aed33SMarcel Moolenaar CTASSERT(offsetof(struct gpt_hdr, padding) == 92); 511d3aed33SMarcel Moolenaar CTASSERT(sizeof(struct gpt_ent) == 128); 521d3aed33SMarcel Moolenaar 531d3aed33SMarcel Moolenaar #define EQUUID(a,b) (memcmp(a, b, sizeof(struct uuid)) == 0) 541d3aed33SMarcel Moolenaar 551d3aed33SMarcel Moolenaar enum gpt_elt { 561d3aed33SMarcel Moolenaar GPT_ELT_PRIHDR, 571d3aed33SMarcel Moolenaar GPT_ELT_PRITBL, 581d3aed33SMarcel Moolenaar GPT_ELT_SECHDR, 591d3aed33SMarcel Moolenaar GPT_ELT_SECTBL, 601d3aed33SMarcel Moolenaar GPT_ELT_COUNT 611d3aed33SMarcel Moolenaar }; 621d3aed33SMarcel Moolenaar 631d3aed33SMarcel Moolenaar enum gpt_state { 641d3aed33SMarcel Moolenaar GPT_STATE_UNKNOWN, /* Not determined. */ 651d3aed33SMarcel Moolenaar GPT_STATE_MISSING, /* No signature found. */ 661d3aed33SMarcel Moolenaar GPT_STATE_CORRUPT, /* Checksum mismatch. */ 671d3aed33SMarcel Moolenaar GPT_STATE_INVALID, /* Nonconformant/invalid. */ 681d3aed33SMarcel Moolenaar GPT_STATE_OK /* Perfectly fine. */ 691d3aed33SMarcel Moolenaar }; 701d3aed33SMarcel Moolenaar 711d3aed33SMarcel Moolenaar struct g_part_gpt_table { 721d3aed33SMarcel Moolenaar struct g_part_table base; 731d3aed33SMarcel Moolenaar struct gpt_hdr hdr; 741d3aed33SMarcel Moolenaar quad_t lba[GPT_ELT_COUNT]; 751d3aed33SMarcel Moolenaar enum gpt_state state[GPT_ELT_COUNT]; 761d3aed33SMarcel Moolenaar }; 771d3aed33SMarcel Moolenaar 781d3aed33SMarcel Moolenaar struct g_part_gpt_entry { 791d3aed33SMarcel Moolenaar struct g_part_entry base; 801d3aed33SMarcel Moolenaar struct gpt_ent ent; 811d3aed33SMarcel Moolenaar }; 821d3aed33SMarcel Moolenaar 831d3aed33SMarcel Moolenaar static int g_part_gpt_add(struct g_part_table *, struct g_part_entry *, 841d3aed33SMarcel Moolenaar struct g_part_parms *); 851d3aed33SMarcel Moolenaar static int g_part_gpt_create(struct g_part_table *, struct g_part_parms *); 861d3aed33SMarcel Moolenaar static int g_part_gpt_destroy(struct g_part_table *, struct g_part_parms *); 871d3aed33SMarcel Moolenaar static int g_part_gpt_dumpto(struct g_part_table *, struct g_part_entry *); 881d3aed33SMarcel Moolenaar static int g_part_gpt_modify(struct g_part_table *, struct g_part_entry *, 891d3aed33SMarcel Moolenaar struct g_part_parms *); 901d3aed33SMarcel Moolenaar static char *g_part_gpt_name(struct g_part_table *, struct g_part_entry *, 911d3aed33SMarcel Moolenaar char *, size_t); 921d3aed33SMarcel Moolenaar static int g_part_gpt_probe(struct g_part_table *, struct g_consumer *); 931d3aed33SMarcel Moolenaar static int g_part_gpt_read(struct g_part_table *, struct g_consumer *); 941d3aed33SMarcel Moolenaar static const char *g_part_gpt_type(struct g_part_table *, struct g_part_entry *, 951d3aed33SMarcel Moolenaar char *, size_t); 961d3aed33SMarcel Moolenaar static int g_part_gpt_write(struct g_part_table *, struct g_consumer *); 971d3aed33SMarcel Moolenaar 981d3aed33SMarcel Moolenaar static kobj_method_t g_part_gpt_methods[] = { 991d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_add, g_part_gpt_add), 1001d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_create, g_part_gpt_create), 1011d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_destroy, g_part_gpt_destroy), 1021d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_dumpto, g_part_gpt_dumpto), 1031d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_modify, g_part_gpt_modify), 1041d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_name, g_part_gpt_name), 1051d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_probe, g_part_gpt_probe), 1061d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_read, g_part_gpt_read), 1071d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_type, g_part_gpt_type), 1081d3aed33SMarcel Moolenaar KOBJMETHOD(g_part_write, g_part_gpt_write), 1091d3aed33SMarcel Moolenaar { 0, 0 } 1101d3aed33SMarcel Moolenaar }; 1111d3aed33SMarcel Moolenaar 1121d3aed33SMarcel Moolenaar static struct g_part_scheme g_part_gpt_scheme = { 1131d3aed33SMarcel Moolenaar "GPT", 1141d3aed33SMarcel Moolenaar g_part_gpt_methods, 1151d3aed33SMarcel Moolenaar sizeof(struct g_part_gpt_table), 1161d3aed33SMarcel Moolenaar .gps_entrysz = sizeof(struct g_part_gpt_entry), 1171d3aed33SMarcel Moolenaar .gps_minent = 128, 1181d3aed33SMarcel Moolenaar .gps_maxent = INT_MAX, 1191d3aed33SMarcel Moolenaar }; 1201d3aed33SMarcel Moolenaar G_PART_SCHEME_DECLARE(g_part_gpt_scheme); 1211d3aed33SMarcel Moolenaar 1221d3aed33SMarcel Moolenaar static struct uuid gpt_uuid_efi = GPT_ENT_TYPE_EFI; 1231d3aed33SMarcel Moolenaar static struct uuid gpt_uuid_freebsd = GPT_ENT_TYPE_FREEBSD; 1241d3aed33SMarcel Moolenaar static struct uuid gpt_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; 1251d3aed33SMarcel Moolenaar static struct uuid gpt_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS; 1261d3aed33SMarcel Moolenaar static struct uuid gpt_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM; 1271d3aed33SMarcel Moolenaar static struct uuid gpt_uuid_linux_swap = GPT_ENT_TYPE_LINUX_SWAP; 1281d3aed33SMarcel Moolenaar static struct uuid gpt_uuid_mbr = GPT_ENT_TYPE_MBR; 1291d3aed33SMarcel Moolenaar static struct uuid gpt_uuid_unused = GPT_ENT_TYPE_UNUSED; 1301d3aed33SMarcel Moolenaar 1311d3aed33SMarcel Moolenaar static void 1321d3aed33SMarcel Moolenaar gpt_read_hdr(struct g_part_gpt_table *table, struct g_consumer *cp, 1331d3aed33SMarcel Moolenaar enum gpt_elt elt, struct gpt_hdr *hdr) 1341d3aed33SMarcel Moolenaar { 1351d3aed33SMarcel Moolenaar struct uuid uuid; 1361d3aed33SMarcel Moolenaar struct g_provider *pp; 1371d3aed33SMarcel Moolenaar char *buf; 1381d3aed33SMarcel Moolenaar quad_t lba, last; 1391d3aed33SMarcel Moolenaar int error; 1401d3aed33SMarcel Moolenaar uint32_t crc, sz; 1411d3aed33SMarcel Moolenaar 1421d3aed33SMarcel Moolenaar pp = cp->provider; 1431d3aed33SMarcel Moolenaar last = (pp->mediasize / pp->sectorsize) - 1; 1441d3aed33SMarcel Moolenaar table->lba[elt] = (elt == GPT_ELT_PRIHDR) ? 1 : last; 1451d3aed33SMarcel Moolenaar table->state[elt] = GPT_STATE_MISSING; 1461d3aed33SMarcel Moolenaar buf = g_read_data(cp, table->lba[elt] * pp->sectorsize, pp->sectorsize, 1471d3aed33SMarcel Moolenaar &error); 1481d3aed33SMarcel Moolenaar if (buf == NULL) 1491d3aed33SMarcel Moolenaar return; 1501d3aed33SMarcel Moolenaar bcopy(buf, hdr, sizeof(*hdr)); 1511d3aed33SMarcel Moolenaar if (memcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) != 0) 1521d3aed33SMarcel Moolenaar return; 1531d3aed33SMarcel Moolenaar 1541d3aed33SMarcel Moolenaar table->state[elt] = GPT_STATE_CORRUPT; 1551d3aed33SMarcel Moolenaar sz = le32toh(hdr->hdr_size); 1561d3aed33SMarcel Moolenaar if (sz < 92 || sz > pp->sectorsize) 1571d3aed33SMarcel Moolenaar return; 1581d3aed33SMarcel Moolenaar crc = le32toh(hdr->hdr_crc_self); 1591d3aed33SMarcel Moolenaar hdr->hdr_crc_self = 0; 1601d3aed33SMarcel Moolenaar if (crc32(hdr, sz) != crc) 1611d3aed33SMarcel Moolenaar return; 1621d3aed33SMarcel Moolenaar hdr->hdr_size = sz; 1631d3aed33SMarcel Moolenaar hdr->hdr_crc_self = crc; 1641d3aed33SMarcel Moolenaar 1651d3aed33SMarcel Moolenaar table->state[elt] = GPT_STATE_INVALID; 1661d3aed33SMarcel Moolenaar hdr->hdr_revision = le32toh(hdr->hdr_revision); 1671d3aed33SMarcel Moolenaar if (hdr->hdr_revision < 0x00010000) 1681d3aed33SMarcel Moolenaar return; 1691d3aed33SMarcel Moolenaar hdr->hdr_lba_self = le64toh(hdr->hdr_lba_self); 1701d3aed33SMarcel Moolenaar if (hdr->hdr_lba_self != table->lba[elt]) 1711d3aed33SMarcel Moolenaar return; 1721d3aed33SMarcel Moolenaar hdr->hdr_lba_alt = le64toh(hdr->hdr_lba_alt); 1731d3aed33SMarcel Moolenaar 1741d3aed33SMarcel Moolenaar /* Check the managed area. */ 1751d3aed33SMarcel Moolenaar hdr->hdr_lba_start = le64toh(hdr->hdr_lba_start); 1761d3aed33SMarcel Moolenaar if (hdr->hdr_lba_start < 2 || hdr->hdr_lba_start >= last) 1771d3aed33SMarcel Moolenaar return; 1781d3aed33SMarcel Moolenaar hdr->hdr_lba_end = le64toh(hdr->hdr_lba_end); 1791d3aed33SMarcel Moolenaar if (hdr->hdr_lba_end < hdr->hdr_lba_start || hdr->hdr_lba_end >= last) 1801d3aed33SMarcel Moolenaar return; 1811d3aed33SMarcel Moolenaar 1821d3aed33SMarcel Moolenaar /* Check the table location and size of the table. */ 1831d3aed33SMarcel Moolenaar hdr->hdr_entries = le32toh(hdr->hdr_entries); 1841d3aed33SMarcel Moolenaar hdr->hdr_entsz = le32toh(hdr->hdr_entsz); 1851d3aed33SMarcel Moolenaar if (hdr->hdr_entries == 0 || hdr->hdr_entsz < 128 || 1861d3aed33SMarcel Moolenaar (hdr->hdr_entsz & 7) != 0) 1871d3aed33SMarcel Moolenaar return; 1881d3aed33SMarcel Moolenaar hdr->hdr_lba_table = le64toh(hdr->hdr_lba_table); 1891d3aed33SMarcel Moolenaar if (hdr->hdr_lba_table < 2 || hdr->hdr_lba_table >= last) 1901d3aed33SMarcel Moolenaar return; 1911d3aed33SMarcel Moolenaar if (hdr->hdr_lba_table >= hdr->hdr_lba_start && 1921d3aed33SMarcel Moolenaar hdr->hdr_lba_table <= hdr->hdr_lba_end) 1931d3aed33SMarcel Moolenaar return; 1941d3aed33SMarcel Moolenaar lba = hdr->hdr_lba_table + 1951d3aed33SMarcel Moolenaar (hdr->hdr_entries * hdr->hdr_entsz + pp->sectorsize - 1) / 1961d3aed33SMarcel Moolenaar pp->sectorsize - 1; 1971d3aed33SMarcel Moolenaar if (lba >= last) 1981d3aed33SMarcel Moolenaar return; 1991d3aed33SMarcel Moolenaar if (lba >= hdr->hdr_lba_start && lba <= hdr->hdr_lba_end) 2001d3aed33SMarcel Moolenaar return; 2011d3aed33SMarcel Moolenaar 2021d3aed33SMarcel Moolenaar table->state[elt] = GPT_STATE_OK; 2031d3aed33SMarcel Moolenaar le_uuid_dec(&hdr->hdr_uuid, &uuid); 2041d3aed33SMarcel Moolenaar hdr->hdr_uuid = uuid; 2051d3aed33SMarcel Moolenaar hdr->hdr_crc_table = le32toh(hdr->hdr_crc_table); 2061d3aed33SMarcel Moolenaar } 2071d3aed33SMarcel Moolenaar 2081d3aed33SMarcel Moolenaar static struct gpt_ent * 2091d3aed33SMarcel Moolenaar gpt_read_tbl(struct g_part_gpt_table *table, struct g_consumer *cp, 2101d3aed33SMarcel Moolenaar enum gpt_elt elt, struct gpt_hdr *hdr) 2111d3aed33SMarcel Moolenaar { 2121d3aed33SMarcel Moolenaar struct g_provider *pp; 2131d3aed33SMarcel Moolenaar struct gpt_ent *ent, *tbl; 2141d3aed33SMarcel Moolenaar char *buf, *p; 2151d3aed33SMarcel Moolenaar unsigned int idx, sectors, tblsz; 2161d3aed33SMarcel Moolenaar int error; 2171d3aed33SMarcel Moolenaar uint16_t ch; 2181d3aed33SMarcel Moolenaar 2191d3aed33SMarcel Moolenaar pp = cp->provider; 2201d3aed33SMarcel Moolenaar table->lba[elt] = hdr->hdr_lba_table; 2211d3aed33SMarcel Moolenaar 2221d3aed33SMarcel Moolenaar table->state[elt] = GPT_STATE_MISSING; 2231d3aed33SMarcel Moolenaar tblsz = hdr->hdr_entries * hdr->hdr_entsz; 2241d3aed33SMarcel Moolenaar sectors = (tblsz + pp->sectorsize - 1) / pp->sectorsize; 2251d3aed33SMarcel Moolenaar buf = g_read_data(cp, table->lba[elt] * pp->sectorsize, 2261d3aed33SMarcel Moolenaar sectors * pp->sectorsize, &error); 2271d3aed33SMarcel Moolenaar if (buf == NULL) 2281d3aed33SMarcel Moolenaar return (NULL); 2291d3aed33SMarcel Moolenaar 2301d3aed33SMarcel Moolenaar table->state[elt] = GPT_STATE_CORRUPT; 2311d3aed33SMarcel Moolenaar if (crc32(buf, tblsz) != hdr->hdr_crc_table) { 2321d3aed33SMarcel Moolenaar g_free(buf); 2331d3aed33SMarcel Moolenaar return (NULL); 2341d3aed33SMarcel Moolenaar } 2351d3aed33SMarcel Moolenaar 2361d3aed33SMarcel Moolenaar table->state[elt] = GPT_STATE_OK; 2371d3aed33SMarcel Moolenaar tbl = g_malloc(hdr->hdr_entries * sizeof(struct gpt_ent), 2381d3aed33SMarcel Moolenaar M_WAITOK | M_ZERO); 2391d3aed33SMarcel Moolenaar 2401d3aed33SMarcel Moolenaar for (idx = 0, ent = tbl, p = buf; 2411d3aed33SMarcel Moolenaar idx < hdr->hdr_entries; 2421d3aed33SMarcel Moolenaar idx++, ent++, p += hdr->hdr_entsz) { 2431d3aed33SMarcel Moolenaar le_uuid_dec(p, &ent->ent_type); 2441d3aed33SMarcel Moolenaar le_uuid_dec(p + 16, &ent->ent_uuid); 2451d3aed33SMarcel Moolenaar ent->ent_lba_start = le64dec(p + 32); 2461d3aed33SMarcel Moolenaar ent->ent_lba_end = le64dec(p + 40); 2471d3aed33SMarcel Moolenaar ent->ent_attr = le64dec(p + 48); 2481d3aed33SMarcel Moolenaar for (ch = 0; ch < sizeof(ent->ent_name)/2; ch++) 2491d3aed33SMarcel Moolenaar ent->ent_name[ch] = le16dec(p + 56 + ch * 2); 2501d3aed33SMarcel Moolenaar } 2511d3aed33SMarcel Moolenaar 2521d3aed33SMarcel Moolenaar g_free(buf); 2531d3aed33SMarcel Moolenaar return (tbl); 2541d3aed33SMarcel Moolenaar } 2551d3aed33SMarcel Moolenaar 2561d3aed33SMarcel Moolenaar static int 2571d3aed33SMarcel Moolenaar gpt_matched_hdrs(struct gpt_hdr *pri, struct gpt_hdr *sec) 2581d3aed33SMarcel Moolenaar { 2591d3aed33SMarcel Moolenaar 2601d3aed33SMarcel Moolenaar if (!EQUUID(&pri->hdr_uuid, &sec->hdr_uuid)) 2611d3aed33SMarcel Moolenaar return (0); 2621d3aed33SMarcel Moolenaar return ((pri->hdr_revision == sec->hdr_revision && 2631d3aed33SMarcel Moolenaar pri->hdr_size == sec->hdr_size && 2641d3aed33SMarcel Moolenaar pri->hdr_lba_start == sec->hdr_lba_start && 2651d3aed33SMarcel Moolenaar pri->hdr_lba_end == sec->hdr_lba_end && 2661d3aed33SMarcel Moolenaar pri->hdr_entries == sec->hdr_entries && 2671d3aed33SMarcel Moolenaar pri->hdr_entsz == sec->hdr_entsz && 2681d3aed33SMarcel Moolenaar pri->hdr_crc_table == sec->hdr_crc_table) ? 1 : 0); 2691d3aed33SMarcel Moolenaar } 2701d3aed33SMarcel Moolenaar 2711d3aed33SMarcel Moolenaar static int 2721d3aed33SMarcel Moolenaar gpt_parse_type(const char *type, struct uuid *uuid) 2731d3aed33SMarcel Moolenaar { 2741d3aed33SMarcel Moolenaar struct uuid tmp; 275d287f590SMarcel Moolenaar const char *alias; 2761d3aed33SMarcel Moolenaar int error; 2771d3aed33SMarcel Moolenaar 278d287f590SMarcel Moolenaar if (type[0] == '!') { 279d287f590SMarcel Moolenaar error = parse_uuid(type + 1, &tmp); 2801d3aed33SMarcel Moolenaar if (error) 2811d3aed33SMarcel Moolenaar return (error); 2821d3aed33SMarcel Moolenaar if (EQUUID(&tmp, &gpt_uuid_unused)) 2831d3aed33SMarcel Moolenaar return (EINVAL); 2841d3aed33SMarcel Moolenaar *uuid = tmp; 2851d3aed33SMarcel Moolenaar return (0); 2861d3aed33SMarcel Moolenaar } 287d287f590SMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_EFI); 288d287f590SMarcel Moolenaar if (!strcasecmp(type, alias)) { 2891d3aed33SMarcel Moolenaar *uuid = gpt_uuid_efi; 2901d3aed33SMarcel Moolenaar return (0); 2911d3aed33SMarcel Moolenaar } 292d287f590SMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD); 293d287f590SMarcel Moolenaar if (!strcasecmp(type, alias)) { 294d287f590SMarcel Moolenaar *uuid = gpt_uuid_freebsd; 295d287f590SMarcel Moolenaar return (0); 296d287f590SMarcel Moolenaar } 297d287f590SMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_SWAP); 298d287f590SMarcel Moolenaar if (!strcasecmp(type, alias)) { 299d287f590SMarcel Moolenaar *uuid = gpt_uuid_freebsd_swap; 300d287f590SMarcel Moolenaar return (0); 301d287f590SMarcel Moolenaar } 302d287f590SMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_UFS); 303d287f590SMarcel Moolenaar if (!strcasecmp(type, alias)) { 304d287f590SMarcel Moolenaar *uuid = gpt_uuid_freebsd_ufs; 305d287f590SMarcel Moolenaar return (0); 306d287f590SMarcel Moolenaar } 307d287f590SMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_VINUM); 308d287f590SMarcel Moolenaar if (!strcasecmp(type, alias)) { 309d287f590SMarcel Moolenaar *uuid = gpt_uuid_freebsd_vinum; 310d287f590SMarcel Moolenaar return (0); 311d287f590SMarcel Moolenaar } 312d287f590SMarcel Moolenaar alias = g_part_alias_name(G_PART_ALIAS_MBR); 313d287f590SMarcel Moolenaar if (!strcasecmp(type, alias)) { 314d287f590SMarcel Moolenaar *uuid = gpt_uuid_mbr; 315d287f590SMarcel Moolenaar return (0); 316d287f590SMarcel Moolenaar } 317d287f590SMarcel Moolenaar return (EINVAL); 318d287f590SMarcel Moolenaar } 3191d3aed33SMarcel Moolenaar 3201d3aed33SMarcel Moolenaar static int 3211d3aed33SMarcel Moolenaar g_part_gpt_add(struct g_part_table *basetable, struct g_part_entry *baseentry, 3221d3aed33SMarcel Moolenaar struct g_part_parms *gpp) 3231d3aed33SMarcel Moolenaar { 3241d3aed33SMarcel Moolenaar struct g_part_gpt_entry *entry; 3251d3aed33SMarcel Moolenaar int error; 3261d3aed33SMarcel Moolenaar 3271d3aed33SMarcel Moolenaar entry = (struct g_part_gpt_entry *)baseentry; 3281d3aed33SMarcel Moolenaar error = gpt_parse_type(gpp->gpp_type, &entry->ent.ent_type); 3291d3aed33SMarcel Moolenaar if (error) 3301d3aed33SMarcel Moolenaar return (error); 3311d3aed33SMarcel Moolenaar kern_uuidgen(&entry->ent.ent_uuid, 1); 3321d3aed33SMarcel Moolenaar entry->ent.ent_lba_start = baseentry->gpe_start; 3331d3aed33SMarcel Moolenaar entry->ent.ent_lba_end = baseentry->gpe_end; 3341d3aed33SMarcel Moolenaar if (baseentry->gpe_deleted) { 3351d3aed33SMarcel Moolenaar entry->ent.ent_attr = 0; 3361d3aed33SMarcel Moolenaar bzero(entry->ent.ent_name, sizeof(entry->ent.ent_name)); 3371d3aed33SMarcel Moolenaar } 3381d3aed33SMarcel Moolenaar /* XXX label */ 3391d3aed33SMarcel Moolenaar return (0); 3401d3aed33SMarcel Moolenaar } 3411d3aed33SMarcel Moolenaar 3421d3aed33SMarcel Moolenaar static int 3431d3aed33SMarcel Moolenaar g_part_gpt_create(struct g_part_table *basetable, struct g_part_parms *gpp) 3441d3aed33SMarcel Moolenaar { 3451d3aed33SMarcel Moolenaar struct g_provider *pp; 3461d3aed33SMarcel Moolenaar struct g_part_gpt_table *table; 3471d3aed33SMarcel Moolenaar quad_t last; 3481d3aed33SMarcel Moolenaar size_t tblsz; 3491d3aed33SMarcel Moolenaar 3501d3aed33SMarcel Moolenaar table = (struct g_part_gpt_table *)basetable; 3511d3aed33SMarcel Moolenaar pp = gpp->gpp_provider; 3521d3aed33SMarcel Moolenaar tblsz = (basetable->gpt_entries * sizeof(struct gpt_ent) + 3531d3aed33SMarcel Moolenaar pp->sectorsize - 1) / pp->sectorsize; 3541d3aed33SMarcel Moolenaar if (pp->sectorsize < 512 || 3551d3aed33SMarcel Moolenaar pp->mediasize < (3 + 2 * tblsz + basetable->gpt_entries) * 3561d3aed33SMarcel Moolenaar pp->sectorsize) 3571d3aed33SMarcel Moolenaar return (ENOSPC); 3581d3aed33SMarcel Moolenaar 3591d3aed33SMarcel Moolenaar last = (pp->mediasize / pp->sectorsize) - 1; 3601d3aed33SMarcel Moolenaar 3611d3aed33SMarcel Moolenaar table->lba[GPT_ELT_PRIHDR] = 1; 3621d3aed33SMarcel Moolenaar table->lba[GPT_ELT_PRITBL] = 2; 3631d3aed33SMarcel Moolenaar table->lba[GPT_ELT_SECHDR] = last; 3641d3aed33SMarcel Moolenaar table->lba[GPT_ELT_SECTBL] = last - tblsz; 3651d3aed33SMarcel Moolenaar 3661d3aed33SMarcel Moolenaar bcopy(GPT_HDR_SIG, table->hdr.hdr_sig, sizeof(table->hdr.hdr_sig)); 3671d3aed33SMarcel Moolenaar table->hdr.hdr_revision = GPT_HDR_REVISION; 3681d3aed33SMarcel Moolenaar table->hdr.hdr_size = offsetof(struct gpt_hdr, padding); 3691d3aed33SMarcel Moolenaar table->hdr.hdr_lba_start = 2 + tblsz; 3701d3aed33SMarcel Moolenaar table->hdr.hdr_lba_end = last - tblsz - 1; 3711d3aed33SMarcel Moolenaar kern_uuidgen(&table->hdr.hdr_uuid, 1); 3721d3aed33SMarcel Moolenaar table->hdr.hdr_entries = basetable->gpt_entries; 3731d3aed33SMarcel Moolenaar table->hdr.hdr_entsz = sizeof(struct gpt_ent); 3741d3aed33SMarcel Moolenaar 3751d3aed33SMarcel Moolenaar basetable->gpt_first = table->hdr.hdr_lba_start; 3761d3aed33SMarcel Moolenaar basetable->gpt_last = table->hdr.hdr_lba_end; 3771d3aed33SMarcel Moolenaar return (0); 3781d3aed33SMarcel Moolenaar } 3791d3aed33SMarcel Moolenaar 3801d3aed33SMarcel Moolenaar static int 3811d3aed33SMarcel Moolenaar g_part_gpt_destroy(struct g_part_table *basetable, struct g_part_parms *gpp) 3821d3aed33SMarcel Moolenaar { 3831d3aed33SMarcel Moolenaar 3841d3aed33SMarcel Moolenaar /* 3851d3aed33SMarcel Moolenaar * Wipe the first 2 sectors as well as the last to clear the 3861d3aed33SMarcel Moolenaar * partitioning. 3871d3aed33SMarcel Moolenaar */ 3881d3aed33SMarcel Moolenaar basetable->gpt_smhead |= 3; 3891d3aed33SMarcel Moolenaar basetable->gpt_smtail |= 1; 3901d3aed33SMarcel Moolenaar return (0); 3911d3aed33SMarcel Moolenaar } 3921d3aed33SMarcel Moolenaar 3931d3aed33SMarcel Moolenaar static int 3941d3aed33SMarcel Moolenaar g_part_gpt_dumpto(struct g_part_table *table, struct g_part_entry *baseentry) 3951d3aed33SMarcel Moolenaar { 3961d3aed33SMarcel Moolenaar struct g_part_gpt_entry *entry; 3971d3aed33SMarcel Moolenaar 3981d3aed33SMarcel Moolenaar entry = (struct g_part_gpt_entry *)baseentry; 3991d3aed33SMarcel Moolenaar return ((EQUUID(&entry->ent.ent_type, &gpt_uuid_freebsd_swap) || 4001d3aed33SMarcel Moolenaar EQUUID(&entry->ent.ent_type, &gpt_uuid_linux_swap)) ? 1 : 0); 4011d3aed33SMarcel Moolenaar } 4021d3aed33SMarcel Moolenaar 4031d3aed33SMarcel Moolenaar static int 4041d3aed33SMarcel Moolenaar g_part_gpt_modify(struct g_part_table *basetable, 4051d3aed33SMarcel Moolenaar struct g_part_entry *baseentry, struct g_part_parms *gpp) 4061d3aed33SMarcel Moolenaar { 4071d3aed33SMarcel Moolenaar struct g_part_gpt_entry *entry; 4081d3aed33SMarcel Moolenaar int error; 4091d3aed33SMarcel Moolenaar 4101d3aed33SMarcel Moolenaar entry = (struct g_part_gpt_entry *)baseentry; 411d287f590SMarcel Moolenaar if (gpp->gpp_parms & G_PART_PARM_TYPE) { 4121d3aed33SMarcel Moolenaar error = gpt_parse_type(gpp->gpp_type, &entry->ent.ent_type); 4131d3aed33SMarcel Moolenaar if (error) 4141d3aed33SMarcel Moolenaar return (error); 415d287f590SMarcel Moolenaar } 4161d3aed33SMarcel Moolenaar /* XXX label */ 4171d3aed33SMarcel Moolenaar return (0); 4181d3aed33SMarcel Moolenaar } 4191d3aed33SMarcel Moolenaar 4201d3aed33SMarcel Moolenaar static char * 4211d3aed33SMarcel Moolenaar g_part_gpt_name(struct g_part_table *table, struct g_part_entry *baseentry, 4221d3aed33SMarcel Moolenaar char *buf, size_t bufsz) 4231d3aed33SMarcel Moolenaar { 4241d3aed33SMarcel Moolenaar struct g_part_gpt_entry *entry; 4251d3aed33SMarcel Moolenaar char c; 4261d3aed33SMarcel Moolenaar 4271d3aed33SMarcel Moolenaar entry = (struct g_part_gpt_entry *)baseentry; 4281d3aed33SMarcel Moolenaar c = (EQUUID(&entry->ent.ent_type, &gpt_uuid_freebsd)) ? 's' : 'p'; 4291d3aed33SMarcel Moolenaar snprintf(buf, bufsz, "%c%d", c, baseentry->gpe_index); 4301d3aed33SMarcel Moolenaar return (buf); 4311d3aed33SMarcel Moolenaar } 4321d3aed33SMarcel Moolenaar 4331d3aed33SMarcel Moolenaar static int 4341d3aed33SMarcel Moolenaar g_part_gpt_probe(struct g_part_table *table, struct g_consumer *cp) 4351d3aed33SMarcel Moolenaar { 4361d3aed33SMarcel Moolenaar struct g_provider *pp; 4371d3aed33SMarcel Moolenaar char *buf; 4381d3aed33SMarcel Moolenaar int error, res; 4391d3aed33SMarcel Moolenaar 4401d3aed33SMarcel Moolenaar /* We don't nest, which means that our depth should be 0. */ 4411d3aed33SMarcel Moolenaar if (table->gpt_depth != 0) 4421d3aed33SMarcel Moolenaar return (ENXIO); 4431d3aed33SMarcel Moolenaar 4441d3aed33SMarcel Moolenaar pp = cp->provider; 4451d3aed33SMarcel Moolenaar 4461d3aed33SMarcel Moolenaar /* 4471d3aed33SMarcel Moolenaar * Sanity-check the provider. Since the first sector on the provider 4481d3aed33SMarcel Moolenaar * must be a PMBR and a PMBR is 512 bytes large, the sector size 4491d3aed33SMarcel Moolenaar * must be at least 512 bytes. Also, since the theoretical minimum 4501d3aed33SMarcel Moolenaar * number of sectors needed by GPT is 6, any medium that has less 4511d3aed33SMarcel Moolenaar * than 6 sectors is never going to be able to hold a GPT. The 4521d3aed33SMarcel Moolenaar * number 6 comes from: 4531d3aed33SMarcel Moolenaar * 1 sector for the PMBR 4541d3aed33SMarcel Moolenaar * 2 sectors for the GPT headers (each 1 sector) 4551d3aed33SMarcel Moolenaar * 2 sectors for the GPT tables (each 1 sector) 4561d3aed33SMarcel Moolenaar * 1 sector for an actual partition 4571d3aed33SMarcel Moolenaar * It's better to catch this pathological case early than behaving 4581d3aed33SMarcel Moolenaar * pathologically later on... 4591d3aed33SMarcel Moolenaar */ 4601d3aed33SMarcel Moolenaar if (pp->sectorsize < 512 || pp->mediasize < 6 * pp->sectorsize) 4611d3aed33SMarcel Moolenaar return (ENOSPC); 4621d3aed33SMarcel Moolenaar 4631d3aed33SMarcel Moolenaar /* Check that there's a MBR. */ 4641d3aed33SMarcel Moolenaar buf = g_read_data(cp, 0L, pp->sectorsize, &error); 4651d3aed33SMarcel Moolenaar if (buf == NULL) 4661d3aed33SMarcel Moolenaar return (error); 4671d3aed33SMarcel Moolenaar res = le16dec(buf + DOSMAGICOFFSET); 4681d3aed33SMarcel Moolenaar g_free(buf); 4691d3aed33SMarcel Moolenaar if (res != DOSMAGIC) 4701d3aed33SMarcel Moolenaar return (ENXIO); 4711d3aed33SMarcel Moolenaar 4721d3aed33SMarcel Moolenaar /* Check that there's a primary header. */ 4731d3aed33SMarcel Moolenaar buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error); 4741d3aed33SMarcel Moolenaar if (buf == NULL) 4751d3aed33SMarcel Moolenaar return (error); 4761d3aed33SMarcel Moolenaar res = memcmp(buf, GPT_HDR_SIG, 8); 4771d3aed33SMarcel Moolenaar g_free(buf); 4781d3aed33SMarcel Moolenaar if (res == 0) 4791d3aed33SMarcel Moolenaar return (G_PART_PROBE_PRI_HIGH); 4801d3aed33SMarcel Moolenaar 4811d3aed33SMarcel Moolenaar /* No primary? Check that there's a secondary. */ 4821d3aed33SMarcel Moolenaar buf = g_read_data(cp, pp->mediasize - pp->sectorsize, pp->sectorsize, 4831d3aed33SMarcel Moolenaar &error); 4841d3aed33SMarcel Moolenaar if (buf == NULL) 4851d3aed33SMarcel Moolenaar return (error); 4861d3aed33SMarcel Moolenaar res = memcmp(buf, GPT_HDR_SIG, 8); 4871d3aed33SMarcel Moolenaar g_free(buf); 4881d3aed33SMarcel Moolenaar return ((res == 0) ? G_PART_PROBE_PRI_HIGH : ENXIO); 4891d3aed33SMarcel Moolenaar } 4901d3aed33SMarcel Moolenaar 4911d3aed33SMarcel Moolenaar static int 4921d3aed33SMarcel Moolenaar g_part_gpt_read(struct g_part_table *basetable, struct g_consumer *cp) 4931d3aed33SMarcel Moolenaar { 4941d3aed33SMarcel Moolenaar struct gpt_hdr prihdr, sechdr; 4951d3aed33SMarcel Moolenaar struct gpt_ent *tbl, *pritbl, *sectbl; 4961d3aed33SMarcel Moolenaar struct g_provider *pp; 4971d3aed33SMarcel Moolenaar struct g_part_gpt_table *table; 4981d3aed33SMarcel Moolenaar struct g_part_gpt_entry *entry; 4991d3aed33SMarcel Moolenaar int index; 5001d3aed33SMarcel Moolenaar 5011d3aed33SMarcel Moolenaar table = (struct g_part_gpt_table *)basetable; 5021d3aed33SMarcel Moolenaar pp = cp->provider; 5031d3aed33SMarcel Moolenaar 5041d3aed33SMarcel Moolenaar /* Read the primary header and table. */ 5051d3aed33SMarcel Moolenaar gpt_read_hdr(table, cp, GPT_ELT_PRIHDR, &prihdr); 5061d3aed33SMarcel Moolenaar if (table->state[GPT_ELT_PRIHDR] == GPT_STATE_OK) { 5071d3aed33SMarcel Moolenaar pritbl = gpt_read_tbl(table, cp, GPT_ELT_PRITBL, &prihdr); 5081d3aed33SMarcel Moolenaar } else { 5091d3aed33SMarcel Moolenaar table->state[GPT_ELT_PRITBL] = GPT_STATE_MISSING; 5101d3aed33SMarcel Moolenaar pritbl = NULL; 5111d3aed33SMarcel Moolenaar } 5121d3aed33SMarcel Moolenaar 5131d3aed33SMarcel Moolenaar /* Read the secondary header and table. */ 5141d3aed33SMarcel Moolenaar gpt_read_hdr(table, cp, GPT_ELT_SECHDR, &sechdr); 5151d3aed33SMarcel Moolenaar if (table->state[GPT_ELT_SECHDR] == GPT_STATE_OK) { 5161d3aed33SMarcel Moolenaar sectbl = gpt_read_tbl(table, cp, GPT_ELT_SECTBL, &sechdr); 5171d3aed33SMarcel Moolenaar } else { 5181d3aed33SMarcel Moolenaar table->state[GPT_ELT_SECTBL] = GPT_STATE_MISSING; 5191d3aed33SMarcel Moolenaar sectbl = NULL; 5201d3aed33SMarcel Moolenaar } 5211d3aed33SMarcel Moolenaar 5221d3aed33SMarcel Moolenaar /* Fail if we haven't got any good tables at all. */ 5231d3aed33SMarcel Moolenaar if (table->state[GPT_ELT_PRITBL] != GPT_STATE_OK && 5241d3aed33SMarcel Moolenaar table->state[GPT_ELT_SECTBL] != GPT_STATE_OK) { 5251d3aed33SMarcel Moolenaar printf("GEOM: %s: corrupt or invalid GPT detected.\n", 5261d3aed33SMarcel Moolenaar pp->name); 5271d3aed33SMarcel Moolenaar printf("GEOM: %s: GPT rejected -- may not be recoverable.\n", 5281d3aed33SMarcel Moolenaar pp->name); 5291d3aed33SMarcel Moolenaar return (EINVAL); 5301d3aed33SMarcel Moolenaar } 5311d3aed33SMarcel Moolenaar 5321d3aed33SMarcel Moolenaar /* 5331d3aed33SMarcel Moolenaar * If both headers are good but they disagree with each other, 5341d3aed33SMarcel Moolenaar * then invalidate one. We prefer to keep the primary header, 5351d3aed33SMarcel Moolenaar * unless the primary table is corrupt. 5361d3aed33SMarcel Moolenaar */ 5371d3aed33SMarcel Moolenaar if (table->state[GPT_ELT_PRIHDR] == GPT_STATE_OK && 5381d3aed33SMarcel Moolenaar table->state[GPT_ELT_SECHDR] == GPT_STATE_OK && 5391d3aed33SMarcel Moolenaar !gpt_matched_hdrs(&prihdr, &sechdr)) { 5401d3aed33SMarcel Moolenaar if (table->state[GPT_ELT_PRITBL] == GPT_STATE_OK) 5411d3aed33SMarcel Moolenaar table->state[GPT_ELT_SECHDR] = GPT_STATE_INVALID; 5421d3aed33SMarcel Moolenaar else 5431d3aed33SMarcel Moolenaar table->state[GPT_ELT_PRIHDR] = GPT_STATE_INVALID; 5441d3aed33SMarcel Moolenaar } 5451d3aed33SMarcel Moolenaar 5461d3aed33SMarcel Moolenaar if (table->state[GPT_ELT_PRIHDR] != GPT_STATE_OK) { 5471d3aed33SMarcel Moolenaar printf("GEOM: %s: the primary GPT table is corrupt or " 5481d3aed33SMarcel Moolenaar "invalid.\n", pp->name); 5491d3aed33SMarcel Moolenaar printf("GEOM: %s: using the secondary instead -- recovery " 5501d3aed33SMarcel Moolenaar "strongly advised.\n", pp->name); 5511d3aed33SMarcel Moolenaar table->hdr = sechdr; 5521d3aed33SMarcel Moolenaar tbl = sectbl; 5531d3aed33SMarcel Moolenaar if (pritbl != NULL) 5541d3aed33SMarcel Moolenaar g_free(pritbl); 5551d3aed33SMarcel Moolenaar } else { 5561d3aed33SMarcel Moolenaar if (table->state[GPT_ELT_SECHDR] != GPT_STATE_OK) { 5571d3aed33SMarcel Moolenaar printf("GEOM: %s: the secondary GPT table is corrupt " 5581d3aed33SMarcel Moolenaar "or invalid.\n", pp->name); 5591d3aed33SMarcel Moolenaar printf("GEOM: %s: using the primary only -- recovery " 5601d3aed33SMarcel Moolenaar "suggested.\n", pp->name); 5611d3aed33SMarcel Moolenaar } 5621d3aed33SMarcel Moolenaar table->hdr = prihdr; 5631d3aed33SMarcel Moolenaar tbl = pritbl; 5641d3aed33SMarcel Moolenaar if (sectbl != NULL) 5651d3aed33SMarcel Moolenaar g_free(sectbl); 5661d3aed33SMarcel Moolenaar } 5671d3aed33SMarcel Moolenaar 5681d3aed33SMarcel Moolenaar basetable->gpt_first = table->hdr.hdr_lba_start; 5691d3aed33SMarcel Moolenaar basetable->gpt_last = table->hdr.hdr_lba_end; 5701d3aed33SMarcel Moolenaar basetable->gpt_entries = table->hdr.hdr_entries; 5711d3aed33SMarcel Moolenaar 5721d3aed33SMarcel Moolenaar for (index = basetable->gpt_entries - 1; index >= 0; index--) { 5731d3aed33SMarcel Moolenaar if (EQUUID(&tbl[index].ent_type, &gpt_uuid_unused)) 5741d3aed33SMarcel Moolenaar continue; 5751d3aed33SMarcel Moolenaar entry = (struct g_part_gpt_entry *)g_part_new_entry(basetable, 5761d3aed33SMarcel Moolenaar index+1, tbl[index].ent_lba_start, tbl[index].ent_lba_end); 5771d3aed33SMarcel Moolenaar entry->ent = tbl[index]; 5781d3aed33SMarcel Moolenaar } 5791d3aed33SMarcel Moolenaar 5801d3aed33SMarcel Moolenaar g_free(tbl); 5811d3aed33SMarcel Moolenaar return (0); 5821d3aed33SMarcel Moolenaar } 5831d3aed33SMarcel Moolenaar 5841d3aed33SMarcel Moolenaar static const char * 5851d3aed33SMarcel Moolenaar g_part_gpt_type(struct g_part_table *basetable, struct g_part_entry *baseentry, 5861d3aed33SMarcel Moolenaar char *buf, size_t bufsz) 5871d3aed33SMarcel Moolenaar { 5881d3aed33SMarcel Moolenaar struct g_part_gpt_entry *entry; 5891d3aed33SMarcel Moolenaar struct uuid *type; 5901d3aed33SMarcel Moolenaar 5911d3aed33SMarcel Moolenaar entry = (struct g_part_gpt_entry *)baseentry; 5921d3aed33SMarcel Moolenaar type = &entry->ent.ent_type; 5931d3aed33SMarcel Moolenaar if (EQUUID(type, &gpt_uuid_efi)) 5941d3aed33SMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_EFI)); 5951d3aed33SMarcel Moolenaar if (EQUUID(type, &gpt_uuid_freebsd)) 5961d3aed33SMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD)); 5971d3aed33SMarcel Moolenaar if (EQUUID(type, &gpt_uuid_freebsd_swap)) 5981d3aed33SMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_SWAP)); 5991d3aed33SMarcel Moolenaar if (EQUUID(type, &gpt_uuid_freebsd_ufs)) 6001d3aed33SMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_UFS)); 6011d3aed33SMarcel Moolenaar if (EQUUID(type, &gpt_uuid_freebsd_vinum)) 6021d3aed33SMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_FREEBSD_VINUM)); 6031d3aed33SMarcel Moolenaar if (EQUUID(type, &gpt_uuid_mbr)) 6041d3aed33SMarcel Moolenaar return (g_part_alias_name(G_PART_ALIAS_MBR)); 605cf231470SMarcel Moolenaar buf[0] = '!'; 606cf231470SMarcel Moolenaar snprintf_uuid(buf + 1, bufsz - 1, type); 6071d3aed33SMarcel Moolenaar return (buf); 6081d3aed33SMarcel Moolenaar } 6091d3aed33SMarcel Moolenaar 6101d3aed33SMarcel Moolenaar static int 6111d3aed33SMarcel Moolenaar g_part_gpt_write(struct g_part_table *basetable, struct g_consumer *cp) 6121d3aed33SMarcel Moolenaar { 6131d3aed33SMarcel Moolenaar unsigned char *buf, *bp; 6141d3aed33SMarcel Moolenaar struct g_provider *pp; 6151d3aed33SMarcel Moolenaar struct g_part_entry *baseentry; 6161d3aed33SMarcel Moolenaar struct g_part_gpt_entry *entry; 6171d3aed33SMarcel Moolenaar struct g_part_gpt_table *table; 6181d3aed33SMarcel Moolenaar size_t tlbsz; 6191d3aed33SMarcel Moolenaar uint32_t crc; 6201d3aed33SMarcel Moolenaar int error, index; 6211d3aed33SMarcel Moolenaar 6221d3aed33SMarcel Moolenaar pp = cp->provider; 6231d3aed33SMarcel Moolenaar table = (struct g_part_gpt_table *)basetable; 6241d3aed33SMarcel Moolenaar tlbsz = (table->hdr.hdr_entries * table->hdr.hdr_entsz + 6251d3aed33SMarcel Moolenaar pp->sectorsize - 1) / pp->sectorsize; 6261d3aed33SMarcel Moolenaar 6271d3aed33SMarcel Moolenaar if (basetable->gpt_created) { 6281d3aed33SMarcel Moolenaar buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO); 6291d3aed33SMarcel Moolenaar le16enc(buf + DOSMAGICOFFSET, DOSMAGIC); 6301d3aed33SMarcel Moolenaar buf[DOSPARTOFF + 1] = 0xff; /* shd */ 6311d3aed33SMarcel Moolenaar buf[DOSPARTOFF + 2] = 0xff; /* ssect */ 6321d3aed33SMarcel Moolenaar buf[DOSPARTOFF + 3] = 0xff; /* scyl */ 6331d3aed33SMarcel Moolenaar buf[DOSPARTOFF + 4] = 0xee; /* typ */ 6341d3aed33SMarcel Moolenaar buf[DOSPARTOFF + 5] = 0xff; /* ehd */ 6351d3aed33SMarcel Moolenaar buf[DOSPARTOFF + 6] = 0xff; /* esect */ 6361d3aed33SMarcel Moolenaar buf[DOSPARTOFF + 7] = 0xff; /* ecyl */ 6371d3aed33SMarcel Moolenaar le32enc(buf + DOSPARTOFF + 8, 1); /* start */ 6381d3aed33SMarcel Moolenaar le32enc(buf + DOSPARTOFF + 12, 6391d3aed33SMarcel Moolenaar MIN(pp->mediasize / pp->sectorsize - 1, 0xffffffffLL)); 6401d3aed33SMarcel Moolenaar error = g_write_data(cp, 0, buf, pp->sectorsize); 6411d3aed33SMarcel Moolenaar g_free(buf); 6421d3aed33SMarcel Moolenaar if (error) 6431d3aed33SMarcel Moolenaar return (error); 6441d3aed33SMarcel Moolenaar } 6451d3aed33SMarcel Moolenaar 6461d3aed33SMarcel Moolenaar /* Allocate space for the header and entries. */ 6471d3aed33SMarcel Moolenaar buf = g_malloc((tlbsz + 1) * pp->sectorsize, M_WAITOK | M_ZERO); 6481d3aed33SMarcel Moolenaar 6491d3aed33SMarcel Moolenaar memcpy(buf, table->hdr.hdr_sig, sizeof(table->hdr.hdr_sig)); 6501d3aed33SMarcel Moolenaar le32enc(buf + 8, table->hdr.hdr_revision); 6511d3aed33SMarcel Moolenaar le32enc(buf + 12, table->hdr.hdr_size); 6521d3aed33SMarcel Moolenaar le64enc(buf + 40, table->hdr.hdr_lba_start); 6531d3aed33SMarcel Moolenaar le64enc(buf + 48, table->hdr.hdr_lba_end); 6541d3aed33SMarcel Moolenaar le_uuid_enc(buf + 56, &table->hdr.hdr_uuid); 6551d3aed33SMarcel Moolenaar le32enc(buf + 80, table->hdr.hdr_entries); 6561d3aed33SMarcel Moolenaar le32enc(buf + 84, table->hdr.hdr_entsz); 6571d3aed33SMarcel Moolenaar 6581d3aed33SMarcel Moolenaar LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) { 659d287f590SMarcel Moolenaar if (baseentry->gpe_deleted) 660d287f590SMarcel Moolenaar continue; 6611d3aed33SMarcel Moolenaar entry = (struct g_part_gpt_entry *)baseentry; 6621d3aed33SMarcel Moolenaar index = baseentry->gpe_index - 1; 6631d3aed33SMarcel Moolenaar bp = buf + pp->sectorsize + table->hdr.hdr_entsz * index; 6641d3aed33SMarcel Moolenaar le_uuid_enc(bp, &entry->ent.ent_type); 6651d3aed33SMarcel Moolenaar le_uuid_enc(bp + 16, &entry->ent.ent_uuid); 6661d3aed33SMarcel Moolenaar le64enc(bp + 32, entry->ent.ent_lba_start); 6671d3aed33SMarcel Moolenaar le64enc(bp + 40, entry->ent.ent_lba_end); 6681d3aed33SMarcel Moolenaar le64enc(bp + 48, entry->ent.ent_attr); 6691d3aed33SMarcel Moolenaar memcpy(bp + 56, entry->ent.ent_name, 6701d3aed33SMarcel Moolenaar sizeof(entry->ent.ent_name)); 6711d3aed33SMarcel Moolenaar } 6721d3aed33SMarcel Moolenaar 6731d3aed33SMarcel Moolenaar crc = crc32(buf + pp->sectorsize, 6741d3aed33SMarcel Moolenaar table->hdr.hdr_entries * table->hdr.hdr_entsz); 6751d3aed33SMarcel Moolenaar le32enc(buf + 88, crc); 6761d3aed33SMarcel Moolenaar 6771d3aed33SMarcel Moolenaar /* Write primary meta-data. */ 6781d3aed33SMarcel Moolenaar le32enc(buf + 16, 0); /* hdr_crc_self. */ 6791d3aed33SMarcel Moolenaar le64enc(buf + 24, table->lba[GPT_ELT_PRIHDR]); /* hdr_lba_self. */ 6801d3aed33SMarcel Moolenaar le64enc(buf + 32, table->lba[GPT_ELT_SECHDR]); /* hdr_lba_alt. */ 6811d3aed33SMarcel Moolenaar le64enc(buf + 72, table->lba[GPT_ELT_PRITBL]); /* hdr_lba_table. */ 6821d3aed33SMarcel Moolenaar crc = crc32(buf, table->hdr.hdr_size); 6831d3aed33SMarcel Moolenaar le32enc(buf + 16, crc); 6841d3aed33SMarcel Moolenaar 6851d3aed33SMarcel Moolenaar error = g_write_data(cp, table->lba[GPT_ELT_PRITBL] * pp->sectorsize, 6861d3aed33SMarcel Moolenaar buf + pp->sectorsize, tlbsz * pp->sectorsize); 6871d3aed33SMarcel Moolenaar if (error) 6881d3aed33SMarcel Moolenaar goto out; 6891d3aed33SMarcel Moolenaar error = g_write_data(cp, table->lba[GPT_ELT_PRIHDR] * pp->sectorsize, 6901d3aed33SMarcel Moolenaar buf, pp->sectorsize); 6911d3aed33SMarcel Moolenaar if (error) 6921d3aed33SMarcel Moolenaar goto out; 6931d3aed33SMarcel Moolenaar 6941d3aed33SMarcel Moolenaar /* Write secondary meta-data. */ 6951d3aed33SMarcel Moolenaar le32enc(buf + 16, 0); /* hdr_crc_self. */ 6961d3aed33SMarcel Moolenaar le64enc(buf + 24, table->lba[GPT_ELT_SECHDR]); /* hdr_lba_self. */ 6971d3aed33SMarcel Moolenaar le64enc(buf + 32, table->lba[GPT_ELT_PRIHDR]); /* hdr_lba_alt. */ 6981d3aed33SMarcel Moolenaar le64enc(buf + 72, table->lba[GPT_ELT_SECTBL]); /* hdr_lba_table. */ 6991d3aed33SMarcel Moolenaar crc = crc32(buf, table->hdr.hdr_size); 7001d3aed33SMarcel Moolenaar le32enc(buf + 16, crc); 7011d3aed33SMarcel Moolenaar 7021d3aed33SMarcel Moolenaar error = g_write_data(cp, table->lba[GPT_ELT_SECTBL] * pp->sectorsize, 7031d3aed33SMarcel Moolenaar buf + pp->sectorsize, tlbsz * pp->sectorsize); 7041d3aed33SMarcel Moolenaar if (error) 7051d3aed33SMarcel Moolenaar goto out; 7061d3aed33SMarcel Moolenaar error = g_write_data(cp, table->lba[GPT_ELT_SECHDR] * pp->sectorsize, 7071d3aed33SMarcel Moolenaar buf, pp->sectorsize); 7081d3aed33SMarcel Moolenaar 7091d3aed33SMarcel Moolenaar out: 7101d3aed33SMarcel Moolenaar g_free(buf); 7111d3aed33SMarcel Moolenaar return (error); 7121d3aed33SMarcel Moolenaar } 7131d3aed33SMarcel Moolenaar 7141d3aed33SMarcel Moolenaar #if 0 7151d3aed33SMarcel Moolenaar static void 7161d3aed33SMarcel Moolenaar g_gpt_to_utf8(struct sbuf *sb, uint16_t *str, size_t len) 7171d3aed33SMarcel Moolenaar { 7181d3aed33SMarcel Moolenaar u_int bo; 7191d3aed33SMarcel Moolenaar uint32_t ch; 7201d3aed33SMarcel Moolenaar uint16_t c; 7211d3aed33SMarcel Moolenaar 7221d3aed33SMarcel Moolenaar bo = BYTE_ORDER; 7231d3aed33SMarcel Moolenaar while (len > 0 && *str != 0) { 7241d3aed33SMarcel Moolenaar ch = (bo == BIG_ENDIAN) ? be16toh(*str) : le16toh(*str); 7251d3aed33SMarcel Moolenaar str++, len--; 7261d3aed33SMarcel Moolenaar if ((ch & 0xf800) == 0xd800) { 7271d3aed33SMarcel Moolenaar if (len > 0) { 7281d3aed33SMarcel Moolenaar c = (bo == BIG_ENDIAN) ? be16toh(*str) 7291d3aed33SMarcel Moolenaar : le16toh(*str); 7301d3aed33SMarcel Moolenaar str++, len--; 7311d3aed33SMarcel Moolenaar } else 7321d3aed33SMarcel Moolenaar c = 0xfffd; 7331d3aed33SMarcel Moolenaar if ((ch & 0x400) == 0 && (c & 0xfc00) == 0xdc00) { 7341d3aed33SMarcel Moolenaar ch = ((ch & 0x3ff) << 10) + (c & 0x3ff); 7351d3aed33SMarcel Moolenaar ch += 0x10000; 7361d3aed33SMarcel Moolenaar } else 7371d3aed33SMarcel Moolenaar ch = 0xfffd; 7381d3aed33SMarcel Moolenaar } else if (ch == 0xfffe) { /* BOM (U+FEFF) swapped. */ 7391d3aed33SMarcel Moolenaar bo = (bo == BIG_ENDIAN) ? LITTLE_ENDIAN : BIG_ENDIAN; 7401d3aed33SMarcel Moolenaar continue; 7411d3aed33SMarcel Moolenaar } else if (ch == 0xfeff) /* BOM (U+FEFF) unswapped. */ 7421d3aed33SMarcel Moolenaar continue; 7431d3aed33SMarcel Moolenaar 7441d3aed33SMarcel Moolenaar if (ch < 0x80) 7451d3aed33SMarcel Moolenaar sbuf_printf(sb, "%c", ch); 7461d3aed33SMarcel Moolenaar else if (ch < 0x800) 7471d3aed33SMarcel Moolenaar sbuf_printf(sb, "%c%c", 0xc0 | (ch >> 6), 7481d3aed33SMarcel Moolenaar 0x80 | (ch & 0x3f)); 7491d3aed33SMarcel Moolenaar else if (ch < 0x10000) 7501d3aed33SMarcel Moolenaar sbuf_printf(sb, "%c%c%c", 0xe0 | (ch >> 12), 7511d3aed33SMarcel Moolenaar 0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f)); 7521d3aed33SMarcel Moolenaar else if (ch < 0x200000) 7531d3aed33SMarcel Moolenaar sbuf_printf(sb, "%c%c%c%c", 0xf0 | (ch >> 18), 7541d3aed33SMarcel Moolenaar 0x80 | ((ch >> 12) & 0x3f), 7551d3aed33SMarcel Moolenaar 0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f)); 7561d3aed33SMarcel Moolenaar } 7571d3aed33SMarcel Moolenaar } 7581d3aed33SMarcel Moolenaar #endif 759