191ca76a5SAndrey V. Elsukov /*- 291ca76a5SAndrey V. Elsukov * Copyright (c) 2014 Andrey V. Elsukov <ae@FreeBSD.org> 391ca76a5SAndrey V. Elsukov * All rights reserved. 491ca76a5SAndrey V. Elsukov * 591ca76a5SAndrey V. Elsukov * Redistribution and use in source and binary forms, with or without 691ca76a5SAndrey V. Elsukov * modification, are permitted provided that the following conditions 791ca76a5SAndrey V. Elsukov * are met: 891ca76a5SAndrey V. Elsukov * 991ca76a5SAndrey V. Elsukov * 1. Redistributions of source code must retain the above copyright 1091ca76a5SAndrey V. Elsukov * notice, this list of conditions and the following disclaimer. 1191ca76a5SAndrey V. Elsukov * 2. Redistributions in binary form must reproduce the above copyright 1291ca76a5SAndrey V. Elsukov * notice, this list of conditions and the following disclaimer in the 1391ca76a5SAndrey V. Elsukov * documentation and/or other materials provided with the distribution. 1491ca76a5SAndrey V. Elsukov * 1591ca76a5SAndrey V. Elsukov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1691ca76a5SAndrey V. Elsukov * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1791ca76a5SAndrey V. Elsukov * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1891ca76a5SAndrey V. Elsukov * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1991ca76a5SAndrey V. Elsukov * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2091ca76a5SAndrey V. Elsukov * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2191ca76a5SAndrey V. Elsukov * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2291ca76a5SAndrey V. Elsukov * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2391ca76a5SAndrey V. Elsukov * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2491ca76a5SAndrey V. Elsukov * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2591ca76a5SAndrey V. Elsukov */ 2691ca76a5SAndrey V. Elsukov 2791ca76a5SAndrey V. Elsukov #include <sys/param.h> 2891ca76a5SAndrey V. Elsukov #include <sys/bio.h> 29f89d2072SXin LI #include <sys/gsb_crc32.h> 3091ca76a5SAndrey V. Elsukov #include <sys/disklabel.h> 3191ca76a5SAndrey V. Elsukov #include <sys/endian.h> 3291ca76a5SAndrey V. Elsukov #include <sys/gpt.h> 3391ca76a5SAndrey V. Elsukov #include <sys/kernel.h> 3491ca76a5SAndrey V. Elsukov #include <sys/kobj.h> 3591ca76a5SAndrey V. Elsukov #include <sys/limits.h> 3691ca76a5SAndrey V. Elsukov #include <sys/lock.h> 3791ca76a5SAndrey V. Elsukov #include <sys/malloc.h> 3891ca76a5SAndrey V. Elsukov #include <sys/mutex.h> 3991ca76a5SAndrey V. Elsukov #include <sys/queue.h> 4091ca76a5SAndrey V. Elsukov #include <sys/sbuf.h> 4191ca76a5SAndrey V. Elsukov #include <sys/systm.h> 4291ca76a5SAndrey V. Elsukov #include <sys/sysctl.h> 4391ca76a5SAndrey V. Elsukov #include <geom/geom.h> 4491ca76a5SAndrey V. Elsukov #include <geom/geom_int.h> 4591ca76a5SAndrey V. Elsukov #include <geom/part/g_part.h> 4691ca76a5SAndrey V. Elsukov 4791ca76a5SAndrey V. Elsukov #include "g_part_if.h" 4891ca76a5SAndrey V. Elsukov 4991ca76a5SAndrey V. Elsukov FEATURE(geom_part_bsd64, "GEOM partitioning class for 64-bit BSD disklabels"); 5091ca76a5SAndrey V. Elsukov 5191ca76a5SAndrey V. Elsukov /* XXX: move this to sys/disklabel64.h */ 5291ca76a5SAndrey V. Elsukov #define DISKMAGIC64 ((uint32_t)0xc4464c59) 5391ca76a5SAndrey V. Elsukov #define MAXPARTITIONS64 16 5491ca76a5SAndrey V. Elsukov #define RESPARTITIONS64 32 5591ca76a5SAndrey V. Elsukov 5691ca76a5SAndrey V. Elsukov struct disklabel64 { 5791ca76a5SAndrey V. Elsukov char d_reserved0[512]; /* reserved or unused */ 580ff783dcSJohn Baldwin uint32_t d_magic; /* the magic number */ 590ff783dcSJohn Baldwin uint32_t d_crc; /* crc32() d_magic through last part */ 600ff783dcSJohn Baldwin uint32_t d_align; /* partition alignment requirement */ 610ff783dcSJohn Baldwin uint32_t d_npartitions; /* number of partitions */ 6291ca76a5SAndrey V. Elsukov struct uuid d_stor_uuid; /* unique uuid for label */ 6391ca76a5SAndrey V. Elsukov 640ff783dcSJohn Baldwin uint64_t d_total_size; /* total size incl everything (bytes) */ 650ff783dcSJohn Baldwin uint64_t d_bbase; /* boot area base offset (bytes) */ 6691ca76a5SAndrey V. Elsukov /* boot area is pbase - bbase */ 670ff783dcSJohn Baldwin uint64_t d_pbase; /* first allocatable offset (bytes) */ 680ff783dcSJohn Baldwin uint64_t d_pstop; /* last allocatable offset+1 (bytes) */ 690ff783dcSJohn Baldwin uint64_t d_abase; /* location of backup copy if not 0 */ 7091ca76a5SAndrey V. Elsukov 7191ca76a5SAndrey V. Elsukov u_char d_packname[64]; 7291ca76a5SAndrey V. Elsukov u_char d_reserved[64]; 7391ca76a5SAndrey V. Elsukov 7491ca76a5SAndrey V. Elsukov /* 7591ca76a5SAndrey V. Elsukov * Note: offsets are relative to the base of the slice, NOT to 7691ca76a5SAndrey V. Elsukov * d_pbase. Unlike 32 bit disklabels the on-disk format for 7791ca76a5SAndrey V. Elsukov * a 64 bit disklabel remains slice-relative. 7891ca76a5SAndrey V. Elsukov * 7991ca76a5SAndrey V. Elsukov * An uninitialized partition has a p_boffset and p_bsize of 0. 8091ca76a5SAndrey V. Elsukov * 8191ca76a5SAndrey V. Elsukov * If p_fstype is not supported for a live partition it is set 8291ca76a5SAndrey V. Elsukov * to FS_OTHER. This is typically the case when the filesystem 8391ca76a5SAndrey V. Elsukov * is identified by its uuid. 8491ca76a5SAndrey V. Elsukov */ 8591ca76a5SAndrey V. Elsukov struct partition64 { /* the partition table */ 860ff783dcSJohn Baldwin uint64_t p_boffset; /* slice relative offset, in bytes */ 870ff783dcSJohn Baldwin uint64_t p_bsize; /* size of partition, in bytes */ 880ff783dcSJohn Baldwin uint8_t p_fstype; 890ff783dcSJohn Baldwin uint8_t p_unused01; /* reserved, must be 0 */ 900ff783dcSJohn Baldwin uint8_t p_unused02; /* reserved, must be 0 */ 910ff783dcSJohn Baldwin uint8_t p_unused03; /* reserved, must be 0 */ 920ff783dcSJohn Baldwin uint32_t p_unused04; /* reserved, must be 0 */ 930ff783dcSJohn Baldwin uint32_t p_unused05; /* reserved, must be 0 */ 940ff783dcSJohn Baldwin uint32_t p_unused06; /* reserved, must be 0 */ 9591ca76a5SAndrey V. Elsukov struct uuid p_type_uuid;/* mount type as UUID */ 9691ca76a5SAndrey V. Elsukov struct uuid p_stor_uuid;/* unique uuid for storage */ 9791ca76a5SAndrey V. Elsukov } d_partitions[MAXPARTITIONS64];/* actually may be more */ 9891ca76a5SAndrey V. Elsukov }; 9991ca76a5SAndrey V. Elsukov 10091ca76a5SAndrey V. Elsukov struct g_part_bsd64_table { 10191ca76a5SAndrey V. Elsukov struct g_part_table base; 10291ca76a5SAndrey V. Elsukov 10391ca76a5SAndrey V. Elsukov uint32_t d_align; 10491ca76a5SAndrey V. Elsukov uint64_t d_bbase; 10591ca76a5SAndrey V. Elsukov uint64_t d_abase; 10691ca76a5SAndrey V. Elsukov struct uuid d_stor_uuid; 10791ca76a5SAndrey V. Elsukov char d_reserved0[512]; 10891ca76a5SAndrey V. Elsukov u_char d_packname[64]; 10991ca76a5SAndrey V. Elsukov u_char d_reserved[64]; 11091ca76a5SAndrey V. Elsukov }; 11191ca76a5SAndrey V. Elsukov 11291ca76a5SAndrey V. Elsukov struct g_part_bsd64_entry { 11391ca76a5SAndrey V. Elsukov struct g_part_entry base; 11491ca76a5SAndrey V. Elsukov 11591ca76a5SAndrey V. Elsukov uint8_t fstype; 11691ca76a5SAndrey V. Elsukov struct uuid type_uuid; 11791ca76a5SAndrey V. Elsukov struct uuid stor_uuid; 11891ca76a5SAndrey V. Elsukov }; 11991ca76a5SAndrey V. Elsukov 12091ca76a5SAndrey V. Elsukov static int g_part_bsd64_add(struct g_part_table *, struct g_part_entry *, 12191ca76a5SAndrey V. Elsukov struct g_part_parms *); 12291ca76a5SAndrey V. Elsukov static int g_part_bsd64_bootcode(struct g_part_table *, struct g_part_parms *); 12391ca76a5SAndrey V. Elsukov static int g_part_bsd64_create(struct g_part_table *, struct g_part_parms *); 12491ca76a5SAndrey V. Elsukov static int g_part_bsd64_destroy(struct g_part_table *, struct g_part_parms *); 12591ca76a5SAndrey V. Elsukov static void g_part_bsd64_dumpconf(struct g_part_table *, struct g_part_entry *, 12691ca76a5SAndrey V. Elsukov struct sbuf *, const char *); 12791ca76a5SAndrey V. Elsukov static int g_part_bsd64_dumpto(struct g_part_table *, struct g_part_entry *); 12891ca76a5SAndrey V. Elsukov static int g_part_bsd64_modify(struct g_part_table *, struct g_part_entry *, 12991ca76a5SAndrey V. Elsukov struct g_part_parms *); 13091ca76a5SAndrey V. Elsukov static const char *g_part_bsd64_name(struct g_part_table *, struct g_part_entry *, 13191ca76a5SAndrey V. Elsukov char *, size_t); 13291ca76a5SAndrey V. Elsukov static int g_part_bsd64_probe(struct g_part_table *, struct g_consumer *); 13391ca76a5SAndrey V. Elsukov static int g_part_bsd64_read(struct g_part_table *, struct g_consumer *); 13491ca76a5SAndrey V. Elsukov static const char *g_part_bsd64_type(struct g_part_table *, struct g_part_entry *, 13591ca76a5SAndrey V. Elsukov char *, size_t); 13691ca76a5SAndrey V. Elsukov static int g_part_bsd64_write(struct g_part_table *, struct g_consumer *); 13791ca76a5SAndrey V. Elsukov static int g_part_bsd64_resize(struct g_part_table *, struct g_part_entry *, 13891ca76a5SAndrey V. Elsukov struct g_part_parms *); 13991ca76a5SAndrey V. Elsukov 14091ca76a5SAndrey V. Elsukov static kobj_method_t g_part_bsd64_methods[] = { 14191ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_add, g_part_bsd64_add), 14291ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_bootcode, g_part_bsd64_bootcode), 14391ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_create, g_part_bsd64_create), 14491ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_destroy, g_part_bsd64_destroy), 14591ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_dumpconf, g_part_bsd64_dumpconf), 14691ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_dumpto, g_part_bsd64_dumpto), 14791ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_modify, g_part_bsd64_modify), 14891ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_resize, g_part_bsd64_resize), 14991ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_name, g_part_bsd64_name), 15091ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_probe, g_part_bsd64_probe), 15191ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_read, g_part_bsd64_read), 15291ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_type, g_part_bsd64_type), 15391ca76a5SAndrey V. Elsukov KOBJMETHOD(g_part_write, g_part_bsd64_write), 15491ca76a5SAndrey V. Elsukov { 0, 0 } 15591ca76a5SAndrey V. Elsukov }; 15691ca76a5SAndrey V. Elsukov 15791ca76a5SAndrey V. Elsukov static struct g_part_scheme g_part_bsd64_scheme = { 15891ca76a5SAndrey V. Elsukov "BSD64", 15991ca76a5SAndrey V. Elsukov g_part_bsd64_methods, 16091ca76a5SAndrey V. Elsukov sizeof(struct g_part_bsd64_table), 16191ca76a5SAndrey V. Elsukov .gps_entrysz = sizeof(struct g_part_bsd64_entry), 16291ca76a5SAndrey V. Elsukov .gps_minent = MAXPARTITIONS64, 163*09c999b1SWarner Losh .gps_defent = MAXPARTITIONS64, 16491ca76a5SAndrey V. Elsukov .gps_maxent = MAXPARTITIONS64 16591ca76a5SAndrey V. Elsukov }; 16691ca76a5SAndrey V. Elsukov G_PART_SCHEME_DECLARE(g_part_bsd64); 16774d6c131SKyle Evans MODULE_VERSION(geom_part_bsd64, 0); 16891ca76a5SAndrey V. Elsukov 16991ca76a5SAndrey V. Elsukov #define EQUUID(a, b) (memcmp(a, b, sizeof(struct uuid)) == 0) 17091ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_unused = GPT_ENT_TYPE_UNUSED; 17191ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_dfbsd_swap = GPT_ENT_TYPE_DRAGONFLY_SWAP; 17291ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_dfbsd_ufs1 = GPT_ENT_TYPE_DRAGONFLY_UFS1; 17391ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_dfbsd_vinum = GPT_ENT_TYPE_DRAGONFLY_VINUM; 17491ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_dfbsd_ccd = GPT_ENT_TYPE_DRAGONFLY_CCD; 17591ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_dfbsd_legacy = GPT_ENT_TYPE_DRAGONFLY_LEGACY; 17691ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_dfbsd_hammer = GPT_ENT_TYPE_DRAGONFLY_HAMMER; 17791ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_dfbsd_hammer2 = GPT_ENT_TYPE_DRAGONFLY_HAMMER2; 17891ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT; 17991ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_freebsd_nandfs = GPT_ENT_TYPE_FREEBSD_NANDFS; 18091ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; 18191ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS; 18291ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM; 18391ca76a5SAndrey V. Elsukov static struct uuid bsd64_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS; 18491ca76a5SAndrey V. Elsukov 18591ca76a5SAndrey V. Elsukov struct bsd64_uuid_alias { 18691ca76a5SAndrey V. Elsukov struct uuid *uuid; 18791ca76a5SAndrey V. Elsukov uint8_t fstype; 18891ca76a5SAndrey V. Elsukov int alias; 18991ca76a5SAndrey V. Elsukov }; 19091ca76a5SAndrey V. Elsukov static struct bsd64_uuid_alias dfbsd_alias_match[] = { 19191ca76a5SAndrey V. Elsukov { &bsd64_uuid_dfbsd_swap, FS_SWAP, G_PART_ALIAS_DFBSD_SWAP }, 19291ca76a5SAndrey V. Elsukov { &bsd64_uuid_dfbsd_ufs1, FS_BSDFFS, G_PART_ALIAS_DFBSD_UFS }, 19391ca76a5SAndrey V. Elsukov { &bsd64_uuid_dfbsd_vinum, FS_VINUM, G_PART_ALIAS_DFBSD_VINUM }, 19491ca76a5SAndrey V. Elsukov { &bsd64_uuid_dfbsd_ccd, FS_CCD, G_PART_ALIAS_DFBSD_CCD }, 19591ca76a5SAndrey V. Elsukov { &bsd64_uuid_dfbsd_legacy, FS_OTHER, G_PART_ALIAS_DFBSD_LEGACY }, 19691ca76a5SAndrey V. Elsukov { &bsd64_uuid_dfbsd_hammer, FS_HAMMER, G_PART_ALIAS_DFBSD_HAMMER }, 19791ca76a5SAndrey V. Elsukov { &bsd64_uuid_dfbsd_hammer2, FS_HAMMER2, G_PART_ALIAS_DFBSD_HAMMER2 }, 19891ca76a5SAndrey V. Elsukov { NULL, 0, 0} 19991ca76a5SAndrey V. Elsukov }; 20091ca76a5SAndrey V. Elsukov static struct bsd64_uuid_alias fbsd_alias_match[] = { 20191ca76a5SAndrey V. Elsukov { &bsd64_uuid_freebsd_boot, FS_OTHER, G_PART_ALIAS_FREEBSD_BOOT }, 20291ca76a5SAndrey V. Elsukov { &bsd64_uuid_freebsd_swap, FS_OTHER, G_PART_ALIAS_FREEBSD_SWAP }, 20391ca76a5SAndrey V. Elsukov { &bsd64_uuid_freebsd_ufs, FS_OTHER, G_PART_ALIAS_FREEBSD_UFS }, 20491ca76a5SAndrey V. Elsukov { &bsd64_uuid_freebsd_zfs, FS_OTHER, G_PART_ALIAS_FREEBSD_ZFS }, 20591ca76a5SAndrey V. Elsukov { &bsd64_uuid_freebsd_vinum, FS_OTHER, G_PART_ALIAS_FREEBSD_VINUM }, 20691ca76a5SAndrey V. Elsukov { &bsd64_uuid_freebsd_nandfs, FS_OTHER, G_PART_ALIAS_FREEBSD_NANDFS }, 20791ca76a5SAndrey V. Elsukov { NULL, 0, 0} 20891ca76a5SAndrey V. Elsukov }; 20991ca76a5SAndrey V. Elsukov 21091ca76a5SAndrey V. Elsukov static int 21191ca76a5SAndrey V. Elsukov bsd64_parse_type(const char *type, struct g_part_bsd64_entry *entry) 21291ca76a5SAndrey V. Elsukov { 21391ca76a5SAndrey V. Elsukov struct uuid tmp; 21491ca76a5SAndrey V. Elsukov const struct bsd64_uuid_alias *uap; 21591ca76a5SAndrey V. Elsukov const char *alias; 21691ca76a5SAndrey V. Elsukov char *p; 21791ca76a5SAndrey V. Elsukov long lt; 21891ca76a5SAndrey V. Elsukov int error; 21991ca76a5SAndrey V. Elsukov 22091ca76a5SAndrey V. Elsukov if (type[0] == '!') { 22191ca76a5SAndrey V. Elsukov if (type[1] == '\0') 22291ca76a5SAndrey V. Elsukov return (EINVAL); 22391ca76a5SAndrey V. Elsukov lt = strtol(type + 1, &p, 0); 22491ca76a5SAndrey V. Elsukov /* The type specified as number */ 22591ca76a5SAndrey V. Elsukov if (*p == '\0') { 22691ca76a5SAndrey V. Elsukov if (lt <= 0 || lt > 255) 22791ca76a5SAndrey V. Elsukov return (EINVAL); 22891ca76a5SAndrey V. Elsukov entry->fstype = lt; 22991ca76a5SAndrey V. Elsukov entry->type_uuid = bsd64_uuid_unused; 23091ca76a5SAndrey V. Elsukov return (0); 23191ca76a5SAndrey V. Elsukov } 23291ca76a5SAndrey V. Elsukov /* The type specified as uuid */ 23391ca76a5SAndrey V. Elsukov error = parse_uuid(type + 1, &tmp); 23491ca76a5SAndrey V. Elsukov if (error != 0) 23591ca76a5SAndrey V. Elsukov return (error); 23691ca76a5SAndrey V. Elsukov if (EQUUID(&tmp, &bsd64_uuid_unused)) 23791ca76a5SAndrey V. Elsukov return (EINVAL); 23891ca76a5SAndrey V. Elsukov for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) { 23991ca76a5SAndrey V. Elsukov if (EQUUID(&tmp, uap->uuid)) { 24091ca76a5SAndrey V. Elsukov /* Prefer fstype for known uuids */ 24191ca76a5SAndrey V. Elsukov entry->type_uuid = bsd64_uuid_unused; 24291ca76a5SAndrey V. Elsukov entry->fstype = uap->fstype; 24391ca76a5SAndrey V. Elsukov return (0); 24491ca76a5SAndrey V. Elsukov } 24591ca76a5SAndrey V. Elsukov } 24691ca76a5SAndrey V. Elsukov entry->type_uuid = tmp; 24791ca76a5SAndrey V. Elsukov entry->fstype = FS_OTHER; 24891ca76a5SAndrey V. Elsukov return (0); 24991ca76a5SAndrey V. Elsukov } 25091ca76a5SAndrey V. Elsukov /* The type specified as symbolic alias name */ 25191ca76a5SAndrey V. Elsukov for (uap = &fbsd_alias_match[0]; uap->uuid != NULL; uap++) { 25291ca76a5SAndrey V. Elsukov alias = g_part_alias_name(uap->alias); 25391ca76a5SAndrey V. Elsukov if (!strcasecmp(type, alias)) { 25491ca76a5SAndrey V. Elsukov entry->type_uuid = *uap->uuid; 25591ca76a5SAndrey V. Elsukov entry->fstype = uap->fstype; 25691ca76a5SAndrey V. Elsukov return (0); 25791ca76a5SAndrey V. Elsukov } 25891ca76a5SAndrey V. Elsukov } 25991ca76a5SAndrey V. Elsukov for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) { 26091ca76a5SAndrey V. Elsukov alias = g_part_alias_name(uap->alias); 26191ca76a5SAndrey V. Elsukov if (!strcasecmp(type, alias)) { 26291ca76a5SAndrey V. Elsukov entry->type_uuid = bsd64_uuid_unused; 26391ca76a5SAndrey V. Elsukov entry->fstype = uap->fstype; 26491ca76a5SAndrey V. Elsukov return (0); 26591ca76a5SAndrey V. Elsukov } 26691ca76a5SAndrey V. Elsukov } 26791ca76a5SAndrey V. Elsukov return (EINVAL); 26891ca76a5SAndrey V. Elsukov } 26991ca76a5SAndrey V. Elsukov 27091ca76a5SAndrey V. Elsukov static int 27191ca76a5SAndrey V. Elsukov g_part_bsd64_add(struct g_part_table *basetable, struct g_part_entry *baseentry, 27291ca76a5SAndrey V. Elsukov struct g_part_parms *gpp) 27391ca76a5SAndrey V. Elsukov { 27491ca76a5SAndrey V. Elsukov struct g_part_bsd64_entry *entry; 27591ca76a5SAndrey V. Elsukov 27691ca76a5SAndrey V. Elsukov if (gpp->gpp_parms & G_PART_PARM_LABEL) 27791ca76a5SAndrey V. Elsukov return (EINVAL); 27891ca76a5SAndrey V. Elsukov 27991ca76a5SAndrey V. Elsukov entry = (struct g_part_bsd64_entry *)baseentry; 28091ca76a5SAndrey V. Elsukov if (bsd64_parse_type(gpp->gpp_type, entry) != 0) 28191ca76a5SAndrey V. Elsukov return (EINVAL); 28291ca76a5SAndrey V. Elsukov kern_uuidgen(&entry->stor_uuid, 1); 28391ca76a5SAndrey V. Elsukov return (0); 28491ca76a5SAndrey V. Elsukov } 28591ca76a5SAndrey V. Elsukov 28691ca76a5SAndrey V. Elsukov static int 28791ca76a5SAndrey V. Elsukov g_part_bsd64_bootcode(struct g_part_table *basetable, struct g_part_parms *gpp) 28891ca76a5SAndrey V. Elsukov { 28991ca76a5SAndrey V. Elsukov 29091ca76a5SAndrey V. Elsukov return (EOPNOTSUPP); 29191ca76a5SAndrey V. Elsukov } 29291ca76a5SAndrey V. Elsukov 29391ca76a5SAndrey V. Elsukov #define PALIGN_SIZE (1024 * 1024) 29491ca76a5SAndrey V. Elsukov #define PALIGN_MASK (PALIGN_SIZE - 1) 29591ca76a5SAndrey V. Elsukov #define BLKSIZE (4 * 1024) 29691ca76a5SAndrey V. Elsukov #define BOOTSIZE (32 * 1024) 29791ca76a5SAndrey V. Elsukov #define DALIGN_SIZE (32 * 1024) 29891ca76a5SAndrey V. Elsukov static int 29991ca76a5SAndrey V. Elsukov g_part_bsd64_create(struct g_part_table *basetable, struct g_part_parms *gpp) 30091ca76a5SAndrey V. Elsukov { 30191ca76a5SAndrey V. Elsukov struct g_part_bsd64_table *table; 30291ca76a5SAndrey V. Elsukov struct g_part_entry *baseentry; 30391ca76a5SAndrey V. Elsukov struct g_provider *pp; 30491ca76a5SAndrey V. Elsukov uint64_t blkmask, pbase; 30591ca76a5SAndrey V. Elsukov uint32_t blksize, ressize; 30691ca76a5SAndrey V. Elsukov 30791ca76a5SAndrey V. Elsukov pp = gpp->gpp_provider; 30891ca76a5SAndrey V. Elsukov if (pp->mediasize < 2* PALIGN_SIZE) 30991ca76a5SAndrey V. Elsukov return (ENOSPC); 31091ca76a5SAndrey V. Elsukov 31191ca76a5SAndrey V. Elsukov /* 31291ca76a5SAndrey V. Elsukov * Use at least 4KB block size. Blksize is stored in the d_align. 31391ca76a5SAndrey V. Elsukov * XXX: Actually it is used just for calculate d_bbase and used 31491ca76a5SAndrey V. Elsukov * for better alignment in bsdlabel64(8). 31591ca76a5SAndrey V. Elsukov */ 31691ca76a5SAndrey V. Elsukov blksize = pp->sectorsize < BLKSIZE ? BLKSIZE: pp->sectorsize; 31791ca76a5SAndrey V. Elsukov blkmask = blksize - 1; 31891ca76a5SAndrey V. Elsukov /* Reserve enough space for RESPARTITIONS64 partitions. */ 31991ca76a5SAndrey V. Elsukov ressize = offsetof(struct disklabel64, d_partitions[RESPARTITIONS64]); 32091ca76a5SAndrey V. Elsukov ressize = (ressize + blkmask) & ~blkmask; 32191ca76a5SAndrey V. Elsukov /* 32291ca76a5SAndrey V. Elsukov * Reserve enough space for bootcode and align first allocatable 32391ca76a5SAndrey V. Elsukov * offset to PALIGN_SIZE. 32491ca76a5SAndrey V. Elsukov * XXX: Currently DragonFlyBSD has 32KB bootcode, but the size could 32591ca76a5SAndrey V. Elsukov * be bigger, because it is possible change it (it is equal pbase-bbase) 32691ca76a5SAndrey V. Elsukov * in the bsdlabel64(8). 32791ca76a5SAndrey V. Elsukov */ 32891ca76a5SAndrey V. Elsukov pbase = ressize + ((BOOTSIZE + blkmask) & ~blkmask); 32991ca76a5SAndrey V. Elsukov pbase = (pbase + PALIGN_MASK) & ~PALIGN_MASK; 33091ca76a5SAndrey V. Elsukov /* 33191ca76a5SAndrey V. Elsukov * Take physical offset into account and make first allocatable 33291ca76a5SAndrey V. Elsukov * offset 32KB aligned to the start of the physical disk. 33391ca76a5SAndrey V. Elsukov * XXX: Actually there are no such restrictions, this is how 33491ca76a5SAndrey V. Elsukov * DragonFlyBSD behaves. 33591ca76a5SAndrey V. Elsukov */ 33691ca76a5SAndrey V. Elsukov pbase += DALIGN_SIZE - pp->stripeoffset % DALIGN_SIZE; 33791ca76a5SAndrey V. Elsukov 33891ca76a5SAndrey V. Elsukov table = (struct g_part_bsd64_table *)basetable; 33991ca76a5SAndrey V. Elsukov table->d_align = blksize; 34091ca76a5SAndrey V. Elsukov table->d_bbase = ressize / pp->sectorsize; 34191ca76a5SAndrey V. Elsukov table->d_abase = ((pp->mediasize - ressize) & 34291ca76a5SAndrey V. Elsukov ~blkmask) / pp->sectorsize; 34391ca76a5SAndrey V. Elsukov kern_uuidgen(&table->d_stor_uuid, 1); 34491ca76a5SAndrey V. Elsukov basetable->gpt_first = pbase / pp->sectorsize; 34591ca76a5SAndrey V. Elsukov basetable->gpt_last = table->d_abase - 1; /* XXX */ 34691ca76a5SAndrey V. Elsukov /* 34791ca76a5SAndrey V. Elsukov * Create 'c' partition and make it internal, so user will not be 34891ca76a5SAndrey V. Elsukov * able use it. 34991ca76a5SAndrey V. Elsukov */ 35091ca76a5SAndrey V. Elsukov baseentry = g_part_new_entry(basetable, RAW_PART + 1, 0, 0); 35191ca76a5SAndrey V. Elsukov baseentry->gpe_internal = 1; 35291ca76a5SAndrey V. Elsukov return (0); 35391ca76a5SAndrey V. Elsukov } 35491ca76a5SAndrey V. Elsukov 35591ca76a5SAndrey V. Elsukov static int 35691ca76a5SAndrey V. Elsukov g_part_bsd64_destroy(struct g_part_table *basetable, struct g_part_parms *gpp) 35791ca76a5SAndrey V. Elsukov { 35891ca76a5SAndrey V. Elsukov struct g_provider *pp; 35991ca76a5SAndrey V. Elsukov 36091ca76a5SAndrey V. Elsukov pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider; 36191ca76a5SAndrey V. Elsukov if (pp->sectorsize > offsetof(struct disklabel64, d_magic)) 36291ca76a5SAndrey V. Elsukov basetable->gpt_smhead |= 1; 36391ca76a5SAndrey V. Elsukov else 36491ca76a5SAndrey V. Elsukov basetable->gpt_smhead |= 3; 36591ca76a5SAndrey V. Elsukov return (0); 36691ca76a5SAndrey V. Elsukov } 36791ca76a5SAndrey V. Elsukov 36891ca76a5SAndrey V. Elsukov static void 36991ca76a5SAndrey V. Elsukov g_part_bsd64_dumpconf(struct g_part_table *basetable, 37091ca76a5SAndrey V. Elsukov struct g_part_entry *baseentry, struct sbuf *sb, const char *indent) 37191ca76a5SAndrey V. Elsukov { 37291ca76a5SAndrey V. Elsukov struct g_part_bsd64_table *table; 37391ca76a5SAndrey V. Elsukov struct g_part_bsd64_entry *entry; 37491ca76a5SAndrey V. Elsukov char buf[sizeof(table->d_packname)]; 37591ca76a5SAndrey V. Elsukov 37691ca76a5SAndrey V. Elsukov entry = (struct g_part_bsd64_entry *)baseentry; 37791ca76a5SAndrey V. Elsukov if (indent == NULL) { 37891ca76a5SAndrey V. Elsukov /* conftxt: libdisk compatibility */ 37991ca76a5SAndrey V. Elsukov sbuf_printf(sb, " xs BSD64 xt %u", entry->fstype); 38091ca76a5SAndrey V. Elsukov } else if (entry != NULL) { 38191ca76a5SAndrey V. Elsukov /* confxml: partition entry information */ 38291ca76a5SAndrey V. Elsukov sbuf_printf(sb, "%s<rawtype>%u</rawtype>\n", indent, 38391ca76a5SAndrey V. Elsukov entry->fstype); 38491ca76a5SAndrey V. Elsukov if (!EQUUID(&bsd64_uuid_unused, &entry->type_uuid)) { 38591ca76a5SAndrey V. Elsukov sbuf_printf(sb, "%s<type_uuid>", indent); 38691ca76a5SAndrey V. Elsukov sbuf_printf_uuid(sb, &entry->type_uuid); 38749ee0fceSAlexander Motin sbuf_cat(sb, "</type_uuid>\n"); 38891ca76a5SAndrey V. Elsukov } 38991ca76a5SAndrey V. Elsukov sbuf_printf(sb, "%s<stor_uuid>", indent); 39091ca76a5SAndrey V. Elsukov sbuf_printf_uuid(sb, &entry->stor_uuid); 39149ee0fceSAlexander Motin sbuf_cat(sb, "</stor_uuid>\n"); 39291ca76a5SAndrey V. Elsukov } else { 39391ca76a5SAndrey V. Elsukov /* confxml: scheme information */ 39491ca76a5SAndrey V. Elsukov table = (struct g_part_bsd64_table *)basetable; 39591ca76a5SAndrey V. Elsukov sbuf_printf(sb, "%s<bootbase>%ju</bootbase>\n", indent, 39691ca76a5SAndrey V. Elsukov (uintmax_t)table->d_bbase); 39791ca76a5SAndrey V. Elsukov if (table->d_abase) 39891ca76a5SAndrey V. Elsukov sbuf_printf(sb, "%s<backupbase>%ju</backupbase>\n", 39991ca76a5SAndrey V. Elsukov indent, (uintmax_t)table->d_abase); 40091ca76a5SAndrey V. Elsukov sbuf_printf(sb, "%s<stor_uuid>", indent); 40191ca76a5SAndrey V. Elsukov sbuf_printf_uuid(sb, &table->d_stor_uuid); 40249ee0fceSAlexander Motin sbuf_cat(sb, "</stor_uuid>\n"); 40391ca76a5SAndrey V. Elsukov sbuf_printf(sb, "%s<label>", indent); 40491ca76a5SAndrey V. Elsukov strncpy(buf, table->d_packname, sizeof(buf) - 1); 40591ca76a5SAndrey V. Elsukov buf[sizeof(buf) - 1] = '\0'; 40649ee0fceSAlexander Motin g_conf_cat_escaped(sb, buf); 40749ee0fceSAlexander Motin sbuf_cat(sb, "</label>\n"); 40891ca76a5SAndrey V. Elsukov } 40991ca76a5SAndrey V. Elsukov } 41091ca76a5SAndrey V. Elsukov 41191ca76a5SAndrey V. Elsukov static int 41291ca76a5SAndrey V. Elsukov g_part_bsd64_dumpto(struct g_part_table *table, struct g_part_entry *baseentry) 41391ca76a5SAndrey V. Elsukov { 41491ca76a5SAndrey V. Elsukov struct g_part_bsd64_entry *entry; 41591ca76a5SAndrey V. Elsukov 41691ca76a5SAndrey V. Elsukov /* Allow dumping to a swap partition. */ 41791ca76a5SAndrey V. Elsukov entry = (struct g_part_bsd64_entry *)baseentry; 41891ca76a5SAndrey V. Elsukov if (entry->fstype == FS_SWAP || 41991ca76a5SAndrey V. Elsukov EQUUID(&entry->type_uuid, &bsd64_uuid_dfbsd_swap) || 42091ca76a5SAndrey V. Elsukov EQUUID(&entry->type_uuid, &bsd64_uuid_freebsd_swap)) 42191ca76a5SAndrey V. Elsukov return (1); 42291ca76a5SAndrey V. Elsukov return (0); 42391ca76a5SAndrey V. Elsukov } 42491ca76a5SAndrey V. Elsukov 42591ca76a5SAndrey V. Elsukov static int 42691ca76a5SAndrey V. Elsukov g_part_bsd64_modify(struct g_part_table *basetable, 42791ca76a5SAndrey V. Elsukov struct g_part_entry *baseentry, struct g_part_parms *gpp) 42891ca76a5SAndrey V. Elsukov { 42991ca76a5SAndrey V. Elsukov struct g_part_bsd64_entry *entry; 43091ca76a5SAndrey V. Elsukov 43191ca76a5SAndrey V. Elsukov if (gpp->gpp_parms & G_PART_PARM_LABEL) 43291ca76a5SAndrey V. Elsukov return (EINVAL); 43391ca76a5SAndrey V. Elsukov 43491ca76a5SAndrey V. Elsukov entry = (struct g_part_bsd64_entry *)baseentry; 43591ca76a5SAndrey V. Elsukov if (gpp->gpp_parms & G_PART_PARM_TYPE) 43691ca76a5SAndrey V. Elsukov return (bsd64_parse_type(gpp->gpp_type, entry)); 43791ca76a5SAndrey V. Elsukov return (0); 43891ca76a5SAndrey V. Elsukov } 43991ca76a5SAndrey V. Elsukov 44091ca76a5SAndrey V. Elsukov static int 44191ca76a5SAndrey V. Elsukov g_part_bsd64_resize(struct g_part_table *basetable, 44291ca76a5SAndrey V. Elsukov struct g_part_entry *baseentry, struct g_part_parms *gpp) 44391ca76a5SAndrey V. Elsukov { 44491ca76a5SAndrey V. Elsukov struct g_part_bsd64_table *table; 44591ca76a5SAndrey V. Elsukov struct g_provider *pp; 44691ca76a5SAndrey V. Elsukov 44791ca76a5SAndrey V. Elsukov if (baseentry == NULL) { 44891ca76a5SAndrey V. Elsukov pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider; 44991ca76a5SAndrey V. Elsukov table = (struct g_part_bsd64_table *)basetable; 450d9c9c81cSPedro F. Giffuni table->d_abase = 451d9c9c81cSPedro F. Giffuni rounddown2(pp->mediasize - table->d_bbase * pp->sectorsize, 452d9c9c81cSPedro F. Giffuni table->d_align) / pp->sectorsize; 45391ca76a5SAndrey V. Elsukov basetable->gpt_last = table->d_abase - 1; 45491ca76a5SAndrey V. Elsukov return (0); 45591ca76a5SAndrey V. Elsukov } 45691ca76a5SAndrey V. Elsukov baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1; 45791ca76a5SAndrey V. Elsukov return (0); 45891ca76a5SAndrey V. Elsukov } 45991ca76a5SAndrey V. Elsukov 46091ca76a5SAndrey V. Elsukov static const char * 46191ca76a5SAndrey V. Elsukov g_part_bsd64_name(struct g_part_table *table, struct g_part_entry *baseentry, 46291ca76a5SAndrey V. Elsukov char *buf, size_t bufsz) 46391ca76a5SAndrey V. Elsukov { 46491ca76a5SAndrey V. Elsukov 46591ca76a5SAndrey V. Elsukov snprintf(buf, bufsz, "%c", 'a' + baseentry->gpe_index - 1); 46691ca76a5SAndrey V. Elsukov return (buf); 46791ca76a5SAndrey V. Elsukov } 46891ca76a5SAndrey V. Elsukov 46991ca76a5SAndrey V. Elsukov static int 47091ca76a5SAndrey V. Elsukov g_part_bsd64_probe(struct g_part_table *table, struct g_consumer *cp) 47191ca76a5SAndrey V. Elsukov { 47291ca76a5SAndrey V. Elsukov struct g_provider *pp; 47391ca76a5SAndrey V. Elsukov uint32_t v; 47491ca76a5SAndrey V. Elsukov int error; 47591ca76a5SAndrey V. Elsukov u_char *buf; 47691ca76a5SAndrey V. Elsukov 47791ca76a5SAndrey V. Elsukov pp = cp->provider; 47891ca76a5SAndrey V. Elsukov if (pp->mediasize < 2 * PALIGN_SIZE) 47991ca76a5SAndrey V. Elsukov return (ENOSPC); 480d9c9c81cSPedro F. Giffuni v = rounddown2(pp->sectorsize + offsetof(struct disklabel64, d_magic), 481d9c9c81cSPedro F. Giffuni pp->sectorsize); 48291ca76a5SAndrey V. Elsukov buf = g_read_data(cp, 0, v, &error); 48391ca76a5SAndrey V. Elsukov if (buf == NULL) 48491ca76a5SAndrey V. Elsukov return (error); 48591ca76a5SAndrey V. Elsukov v = le32dec(buf + offsetof(struct disklabel64, d_magic)); 48691ca76a5SAndrey V. Elsukov g_free(buf); 48791ca76a5SAndrey V. Elsukov return (v == DISKMAGIC64 ? G_PART_PROBE_PRI_HIGH: ENXIO); 48891ca76a5SAndrey V. Elsukov } 48991ca76a5SAndrey V. Elsukov 49091ca76a5SAndrey V. Elsukov static int 49191ca76a5SAndrey V. Elsukov g_part_bsd64_read(struct g_part_table *basetable, struct g_consumer *cp) 49291ca76a5SAndrey V. Elsukov { 49391ca76a5SAndrey V. Elsukov struct g_part_bsd64_table *table; 49491ca76a5SAndrey V. Elsukov struct g_part_bsd64_entry *entry; 49591ca76a5SAndrey V. Elsukov struct g_part_entry *baseentry; 49691ca76a5SAndrey V. Elsukov struct g_provider *pp; 49791ca76a5SAndrey V. Elsukov struct disklabel64 *dlp; 49891ca76a5SAndrey V. Elsukov uint64_t v64, sz; 49991ca76a5SAndrey V. Elsukov uint32_t v32; 50091ca76a5SAndrey V. Elsukov int error, index; 50191ca76a5SAndrey V. Elsukov u_char *buf; 50291ca76a5SAndrey V. Elsukov 50391ca76a5SAndrey V. Elsukov pp = cp->provider; 50491ca76a5SAndrey V. Elsukov table = (struct g_part_bsd64_table *)basetable; 505d9c9c81cSPedro F. Giffuni v32 = roundup2(sizeof(struct disklabel64), pp->sectorsize); 50691ca76a5SAndrey V. Elsukov buf = g_read_data(cp, 0, v32, &error); 50791ca76a5SAndrey V. Elsukov if (buf == NULL) 50891ca76a5SAndrey V. Elsukov return (error); 50991ca76a5SAndrey V. Elsukov 51091ca76a5SAndrey V. Elsukov dlp = (struct disklabel64 *)buf; 51191ca76a5SAndrey V. Elsukov basetable->gpt_entries = le32toh(dlp->d_npartitions); 5125ad33e77SConrad Meyer if (basetable->gpt_entries > MAXPARTITIONS64 || 5135ad33e77SConrad Meyer basetable->gpt_entries < 1) 51491ca76a5SAndrey V. Elsukov goto invalid_label; 51591ca76a5SAndrey V. Elsukov v32 = le32toh(dlp->d_crc); 51691ca76a5SAndrey V. Elsukov dlp->d_crc = 0; 51791ca76a5SAndrey V. Elsukov if (crc32(&dlp->d_magic, offsetof(struct disklabel64, 51891ca76a5SAndrey V. Elsukov d_partitions[basetable->gpt_entries]) - 51991ca76a5SAndrey V. Elsukov offsetof(struct disklabel64, d_magic)) != v32) 52091ca76a5SAndrey V. Elsukov goto invalid_label; 52191ca76a5SAndrey V. Elsukov table->d_align = le32toh(dlp->d_align); 52291ca76a5SAndrey V. Elsukov if (table->d_align == 0 || (table->d_align & (pp->sectorsize - 1))) 52391ca76a5SAndrey V. Elsukov goto invalid_label; 52491ca76a5SAndrey V. Elsukov if (le64toh(dlp->d_total_size) > pp->mediasize) 52591ca76a5SAndrey V. Elsukov goto invalid_label; 52691ca76a5SAndrey V. Elsukov v64 = le64toh(dlp->d_pbase); 52791ca76a5SAndrey V. Elsukov if (v64 % pp->sectorsize) 52891ca76a5SAndrey V. Elsukov goto invalid_label; 52991ca76a5SAndrey V. Elsukov basetable->gpt_first = v64 / pp->sectorsize; 53091ca76a5SAndrey V. Elsukov v64 = le64toh(dlp->d_pstop); 53191ca76a5SAndrey V. Elsukov if (v64 % pp->sectorsize) 53291ca76a5SAndrey V. Elsukov goto invalid_label; 53391ca76a5SAndrey V. Elsukov basetable->gpt_last = v64 / pp->sectorsize; 53491ca76a5SAndrey V. Elsukov basetable->gpt_isleaf = 1; 53591ca76a5SAndrey V. Elsukov v64 = le64toh(dlp->d_bbase); 53691ca76a5SAndrey V. Elsukov if (v64 % pp->sectorsize) 53791ca76a5SAndrey V. Elsukov goto invalid_label; 53891ca76a5SAndrey V. Elsukov table->d_bbase = v64 / pp->sectorsize; 53991ca76a5SAndrey V. Elsukov v64 = le64toh(dlp->d_abase); 54091ca76a5SAndrey V. Elsukov if (v64 % pp->sectorsize) 54191ca76a5SAndrey V. Elsukov goto invalid_label; 54291ca76a5SAndrey V. Elsukov table->d_abase = v64 / pp->sectorsize; 54391ca76a5SAndrey V. Elsukov le_uuid_dec(&dlp->d_stor_uuid, &table->d_stor_uuid); 54491ca76a5SAndrey V. Elsukov for (index = basetable->gpt_entries - 1; index >= 0; index--) { 54591ca76a5SAndrey V. Elsukov if (index == RAW_PART) { 54691ca76a5SAndrey V. Elsukov /* Skip 'c' partition. */ 54791ca76a5SAndrey V. Elsukov baseentry = g_part_new_entry(basetable, 54891ca76a5SAndrey V. Elsukov index + 1, 0, 0); 54991ca76a5SAndrey V. Elsukov baseentry->gpe_internal = 1; 55091ca76a5SAndrey V. Elsukov continue; 55191ca76a5SAndrey V. Elsukov } 55291ca76a5SAndrey V. Elsukov v64 = le64toh(dlp->d_partitions[index].p_boffset); 55391ca76a5SAndrey V. Elsukov sz = le64toh(dlp->d_partitions[index].p_bsize); 55491ca76a5SAndrey V. Elsukov if (sz == 0 && v64 == 0) 55591ca76a5SAndrey V. Elsukov continue; 55691ca76a5SAndrey V. Elsukov if (sz == 0 || (v64 % pp->sectorsize) || (sz % pp->sectorsize)) 55791ca76a5SAndrey V. Elsukov goto invalid_label; 55891ca76a5SAndrey V. Elsukov baseentry = g_part_new_entry(basetable, index + 1, 55991ca76a5SAndrey V. Elsukov v64 / pp->sectorsize, (v64 + sz) / pp->sectorsize - 1); 56091ca76a5SAndrey V. Elsukov entry = (struct g_part_bsd64_entry *)baseentry; 56191ca76a5SAndrey V. Elsukov le_uuid_dec(&dlp->d_partitions[index].p_type_uuid, 56291ca76a5SAndrey V. Elsukov &entry->type_uuid); 56391ca76a5SAndrey V. Elsukov le_uuid_dec(&dlp->d_partitions[index].p_stor_uuid, 56491ca76a5SAndrey V. Elsukov &entry->stor_uuid); 56591ca76a5SAndrey V. Elsukov entry->fstype = dlp->d_partitions[index].p_fstype; 56691ca76a5SAndrey V. Elsukov } 56791ca76a5SAndrey V. Elsukov bcopy(dlp->d_reserved0, table->d_reserved0, 56891ca76a5SAndrey V. Elsukov sizeof(table->d_reserved0)); 56991ca76a5SAndrey V. Elsukov bcopy(dlp->d_packname, table->d_packname, sizeof(table->d_packname)); 57091ca76a5SAndrey V. Elsukov bcopy(dlp->d_reserved, table->d_reserved, sizeof(table->d_reserved)); 57191ca76a5SAndrey V. Elsukov g_free(buf); 57291ca76a5SAndrey V. Elsukov return (0); 57391ca76a5SAndrey V. Elsukov 57491ca76a5SAndrey V. Elsukov invalid_label: 57591ca76a5SAndrey V. Elsukov g_free(buf); 57691ca76a5SAndrey V. Elsukov return (EINVAL); 57791ca76a5SAndrey V. Elsukov } 57891ca76a5SAndrey V. Elsukov 57991ca76a5SAndrey V. Elsukov static const char * 58091ca76a5SAndrey V. Elsukov g_part_bsd64_type(struct g_part_table *basetable, struct g_part_entry *baseentry, 58191ca76a5SAndrey V. Elsukov char *buf, size_t bufsz) 58291ca76a5SAndrey V. Elsukov { 58391ca76a5SAndrey V. Elsukov struct g_part_bsd64_entry *entry; 58491ca76a5SAndrey V. Elsukov struct bsd64_uuid_alias *uap; 58591ca76a5SAndrey V. Elsukov 58691ca76a5SAndrey V. Elsukov entry = (struct g_part_bsd64_entry *)baseentry; 58791ca76a5SAndrey V. Elsukov if (entry->fstype != FS_OTHER) { 58891ca76a5SAndrey V. Elsukov for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) 58991ca76a5SAndrey V. Elsukov if (uap->fstype == entry->fstype) 59091ca76a5SAndrey V. Elsukov return (g_part_alias_name(uap->alias)); 59191ca76a5SAndrey V. Elsukov } else { 59291ca76a5SAndrey V. Elsukov for (uap = &fbsd_alias_match[0]; uap->uuid != NULL; uap++) 59391ca76a5SAndrey V. Elsukov if (EQUUID(uap->uuid, &entry->type_uuid)) 59491ca76a5SAndrey V. Elsukov return (g_part_alias_name(uap->alias)); 59591ca76a5SAndrey V. Elsukov for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) 59691ca76a5SAndrey V. Elsukov if (EQUUID(uap->uuid, &entry->type_uuid)) 59791ca76a5SAndrey V. Elsukov return (g_part_alias_name(uap->alias)); 59891ca76a5SAndrey V. Elsukov } 59991ca76a5SAndrey V. Elsukov if (EQUUID(&bsd64_uuid_unused, &entry->type_uuid)) 60091ca76a5SAndrey V. Elsukov snprintf(buf, bufsz, "!%d", entry->fstype); 60191ca76a5SAndrey V. Elsukov else { 60291ca76a5SAndrey V. Elsukov buf[0] = '!'; 60391ca76a5SAndrey V. Elsukov snprintf_uuid(buf + 1, bufsz - 1, &entry->type_uuid); 60491ca76a5SAndrey V. Elsukov } 60591ca76a5SAndrey V. Elsukov return (buf); 60691ca76a5SAndrey V. Elsukov } 60791ca76a5SAndrey V. Elsukov 60891ca76a5SAndrey V. Elsukov static int 60991ca76a5SAndrey V. Elsukov g_part_bsd64_write(struct g_part_table *basetable, struct g_consumer *cp) 61091ca76a5SAndrey V. Elsukov { 61191ca76a5SAndrey V. Elsukov struct g_provider *pp; 61291ca76a5SAndrey V. Elsukov struct g_part_entry *baseentry; 61391ca76a5SAndrey V. Elsukov struct g_part_bsd64_entry *entry; 61491ca76a5SAndrey V. Elsukov struct g_part_bsd64_table *table; 61591ca76a5SAndrey V. Elsukov struct disklabel64 *dlp; 61691ca76a5SAndrey V. Elsukov uint32_t v, sz; 61791ca76a5SAndrey V. Elsukov int error, index; 61891ca76a5SAndrey V. Elsukov 61991ca76a5SAndrey V. Elsukov pp = cp->provider; 62091ca76a5SAndrey V. Elsukov table = (struct g_part_bsd64_table *)basetable; 621d9c9c81cSPedro F. Giffuni sz = roundup2(sizeof(struct disklabel64), pp->sectorsize); 62291ca76a5SAndrey V. Elsukov dlp = g_malloc(sz, M_WAITOK | M_ZERO); 62391ca76a5SAndrey V. Elsukov 62491ca76a5SAndrey V. Elsukov memcpy(dlp->d_reserved0, table->d_reserved0, 62591ca76a5SAndrey V. Elsukov sizeof(table->d_reserved0)); 62691ca76a5SAndrey V. Elsukov memcpy(dlp->d_packname, table->d_packname, sizeof(table->d_packname)); 62791ca76a5SAndrey V. Elsukov memcpy(dlp->d_reserved, table->d_reserved, sizeof(table->d_reserved)); 62891ca76a5SAndrey V. Elsukov le32enc(&dlp->d_magic, DISKMAGIC64); 62991ca76a5SAndrey V. Elsukov le32enc(&dlp->d_align, table->d_align); 63091ca76a5SAndrey V. Elsukov le32enc(&dlp->d_npartitions, basetable->gpt_entries); 63191ca76a5SAndrey V. Elsukov le_uuid_enc(&dlp->d_stor_uuid, &table->d_stor_uuid); 63291ca76a5SAndrey V. Elsukov le64enc(&dlp->d_total_size, pp->mediasize); 63391ca76a5SAndrey V. Elsukov le64enc(&dlp->d_bbase, table->d_bbase * pp->sectorsize); 63491ca76a5SAndrey V. Elsukov le64enc(&dlp->d_pbase, basetable->gpt_first * pp->sectorsize); 63591ca76a5SAndrey V. Elsukov le64enc(&dlp->d_pstop, basetable->gpt_last * pp->sectorsize); 63691ca76a5SAndrey V. Elsukov le64enc(&dlp->d_abase, table->d_abase * pp->sectorsize); 63791ca76a5SAndrey V. Elsukov 63891ca76a5SAndrey V. Elsukov LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) { 63991ca76a5SAndrey V. Elsukov if (baseentry->gpe_deleted) 64091ca76a5SAndrey V. Elsukov continue; 64191ca76a5SAndrey V. Elsukov index = baseentry->gpe_index - 1; 64291ca76a5SAndrey V. Elsukov entry = (struct g_part_bsd64_entry *)baseentry; 64391ca76a5SAndrey V. Elsukov if (index == RAW_PART) 64491ca76a5SAndrey V. Elsukov continue; 64591ca76a5SAndrey V. Elsukov le64enc(&dlp->d_partitions[index].p_boffset, 64691ca76a5SAndrey V. Elsukov baseentry->gpe_start * pp->sectorsize); 64791ca76a5SAndrey V. Elsukov le64enc(&dlp->d_partitions[index].p_bsize, pp->sectorsize * 64891ca76a5SAndrey V. Elsukov (baseentry->gpe_end - baseentry->gpe_start + 1)); 64991ca76a5SAndrey V. Elsukov dlp->d_partitions[index].p_fstype = entry->fstype; 65091ca76a5SAndrey V. Elsukov le_uuid_enc(&dlp->d_partitions[index].p_type_uuid, 65191ca76a5SAndrey V. Elsukov &entry->type_uuid); 65291ca76a5SAndrey V. Elsukov le_uuid_enc(&dlp->d_partitions[index].p_stor_uuid, 65391ca76a5SAndrey V. Elsukov &entry->stor_uuid); 65491ca76a5SAndrey V. Elsukov } 65591ca76a5SAndrey V. Elsukov /* Calculate checksum. */ 65691ca76a5SAndrey V. Elsukov v = offsetof(struct disklabel64, 65791ca76a5SAndrey V. Elsukov d_partitions[basetable->gpt_entries]) - 65891ca76a5SAndrey V. Elsukov offsetof(struct disklabel64, d_magic); 65991ca76a5SAndrey V. Elsukov le32enc(&dlp->d_crc, crc32(&dlp->d_magic, v)); 66091ca76a5SAndrey V. Elsukov error = g_write_data(cp, 0, dlp, sz); 66191ca76a5SAndrey V. Elsukov g_free(dlp); 66291ca76a5SAndrey V. Elsukov return (error); 66391ca76a5SAndrey V. Elsukov } 664