diff options
-rw-r--r-- | sbin/geom/class/part/gpart.8 | 8 | ||||
-rw-r--r-- | sys/conf/NOTES | 1 | ||||
-rw-r--r-- | sys/conf/files | 1 | ||||
-rw-r--r-- | sys/conf/options | 1 | ||||
-rw-r--r-- | sys/geom/part/g_part.c | 9 | ||||
-rw-r--r-- | sys/geom/part/g_part.h | 9 | ||||
-rw-r--r-- | sys/geom/part/g_part_bsd.c | 45 | ||||
-rw-r--r-- | sys/geom/part/g_part_bsd64.c | 667 | ||||
-rw-r--r-- | sys/geom/part/g_part_gpt.c | 21 | ||||
-rw-r--r-- | sys/modules/geom/geom_part/Makefile | 1 | ||||
-rw-r--r-- | sys/modules/geom/geom_part/geom_part_bsd64/Makefile | 12 | ||||
-rw-r--r-- | sys/sys/disklabel.h | 6 | ||||
-rw-r--r-- | sys/sys/gpt.h | 19 |
13 files changed, 772 insertions, 28 deletions
diff --git a/sbin/geom/class/part/gpart.8 b/sbin/geom/class/part/gpart.8 index f1428ac..8714eed 100644 --- a/sbin/geom/class/part/gpart.8 +++ b/sbin/geom/class/part/gpart.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 2, 2014 +.Dd June 11, 2014 .Dt GPART 8 .Os .Sh NAME @@ -491,6 +491,12 @@ called Requires the .Cm GEOM_PART_BSD kernel option. +.It Cm BSD64 +64-bit implementation of BSD disklabel used in DragonFlyBSD to subdivide MBR +or GPT partitions. +Requires the +.Cm GEOM_PART_BSD64 +kernel option. .It Cm LDM The Logical Disk Manager is an implementation of volume manager for Microsoft Windows NT. diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 95237a6..9002000 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -162,6 +162,7 @@ options GEOM_MULTIPATH # Disk multipath options GEOM_NOP # Test class. options GEOM_PART_APM # Apple partitioning options GEOM_PART_BSD # BSD disklabel +options GEOM_PART_BSD64 # BSD disklabel64 options GEOM_PART_EBR # Extended Boot Records options GEOM_PART_EBR_COMPAT # Backward compatible partition names options GEOM_PART_GPT # GPT partitioning diff --git a/sys/conf/files b/sys/conf/files index 0f89d6e..34efb43 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2764,6 +2764,7 @@ geom/part/g_part.c standard geom/part/g_part_if.m standard geom/part/g_part_apm.c optional geom_part_apm geom/part/g_part_bsd.c optional geom_part_bsd +geom/part/g_part_bsd64.c optional geom_part_bsd64 geom/part/g_part_ebr.c optional geom_part_ebr geom/part/g_part_gpt.c optional geom_part_gpt geom/part/g_part_ldm.c optional geom_part_ldm diff --git a/sys/conf/options b/sys/conf/options index 8b2b1e9..4a62aa8 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -109,6 +109,7 @@ GEOM_MULTIPATH opt_geom.h GEOM_NOP opt_geom.h GEOM_PART_APM opt_geom.h GEOM_PART_BSD opt_geom.h +GEOM_PART_BSD64 opt_geom.h GEOM_PART_EBR opt_geom.h GEOM_PART_EBR_COMPAT opt_geom.h GEOM_PART_GPT opt_geom.h diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c index d5862a0..8429fa0 100644 --- a/sys/geom/part/g_part.c +++ b/sys/geom/part/g_part.c @@ -108,6 +108,15 @@ struct g_part_alias_list { { "vmware-vmkdiag", G_PART_ALIAS_VMKDIAG }, { "vmware-reserved", G_PART_ALIAS_VMRESERVED }, { "vmware-vsanhdr", G_PART_ALIAS_VMVSANHDR }, + { "dragonfly-label32", G_PART_ALIAS_DFBSD }, + { "dragonfly-label64", G_PART_ALIAS_DFBSD64 }, + { "dragonfly-swap", G_PART_ALIAS_DFBSD_SWAP }, + { "dragonfly-ufs", G_PART_ALIAS_DFBSD_UFS }, + { "dragonfly-vinum", G_PART_ALIAS_DFBSD_VINUM }, + { "dragonfly-ccd", G_PART_ALIAS_DFBSD_CCD }, + { "dragonfly-legacy", G_PART_ALIAS_DFBSD_LEGACY }, + { "dragonfly-hammer", G_PART_ALIAS_DFBSD_HAMMER }, + { "dragonfly-hammer2", G_PART_ALIAS_DFBSD_HAMMER2 }, }; SYSCTL_DECL(_kern_geom); diff --git a/sys/geom/part/g_part.h b/sys/geom/part/g_part.h index a578735..06522f5 100644 --- a/sys/geom/part/g_part.h +++ b/sys/geom/part/g_part.h @@ -75,6 +75,15 @@ enum g_part_alias { G_PART_ALIAS_VMKDIAG, /* A VMware vmkDiagnostic partition entry */ G_PART_ALIAS_VMRESERVED, /* A VMware reserved partition entry */ G_PART_ALIAS_VMVSANHDR, /* A VMware vSAN header partition entry */ + G_PART_ALIAS_DFBSD, /* A DfBSD label32 partition entry */ + G_PART_ALIAS_DFBSD64, /* A DfBSD label64 partition entry */ + G_PART_ALIAS_DFBSD_SWAP, /* A DfBSD swap partition entry */ + G_PART_ALIAS_DFBSD_UFS, /* A DfBSD UFS partition entry */ + G_PART_ALIAS_DFBSD_VINUM, /* A DfBSD Vinum partition entry */ + G_PART_ALIAS_DFBSD_CCD, /* A DfBSD CCD partition entry */ + G_PART_ALIAS_DFBSD_LEGACY, /* A DfBSD legacy partition entry */ + G_PART_ALIAS_DFBSD_HAMMER, /* A DfBSD HAMMER FS partition entry */ + G_PART_ALIAS_DFBSD_HAMMER2, /* A DfBSD HAMMER2 FS partition entry */ /* Keep the following last */ G_PART_ALIAS_COUNT }; diff --git a/sys/geom/part/g_part_bsd.c b/sys/geom/part/g_part_bsd.c index 487bf23..5a5eabd 100644 --- a/sys/geom/part/g_part_bsd.c +++ b/sys/geom/part/g_part_bsd.c @@ -112,12 +112,26 @@ static struct g_part_scheme g_part_bsd_scheme = { }; G_PART_SCHEME_DECLARE(g_part_bsd); +static struct g_part_bsd_alias { + uint8_t type; + int alias; +} bsd_alias_match[] = { + { FS_BSDFFS, G_PART_ALIAS_FREEBSD_UFS }, + { FS_SWAP, G_PART_ALIAS_FREEBSD_SWAP }, + { FS_ZFS, G_PART_ALIAS_FREEBSD_ZFS }, + { FS_VINUM, G_PART_ALIAS_FREEBSD_VINUM }, + { FS_NANDFS, G_PART_ALIAS_FREEBSD_NANDFS }, + { FS_HAMMER, G_PART_ALIAS_DFBSD_HAMMER }, + { FS_HAMMER2, G_PART_ALIAS_DFBSD_HAMMER2 }, +}; + static int bsd_parse_type(const char *type, uint8_t *fstype) { const char *alias; char *endp; long lt; + int i; if (type[0] == '!') { lt = strtol(type + 1, &endp, 0); @@ -126,30 +140,13 @@ bsd_parse_type(const char *type, uint8_t *fstype) *fstype = (u_int)lt; return (0); } - alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_NANDFS); - if (!strcasecmp(type, alias)) { - *fstype = FS_NANDFS; - return (0); - } - alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_SWAP); - if (!strcasecmp(type, alias)) { - *fstype = FS_SWAP; - return (0); - } - alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_UFS); - if (!strcasecmp(type, alias)) { - *fstype = FS_BSDFFS; - return (0); - } - alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_VINUM); - if (!strcasecmp(type, alias)) { - *fstype = FS_VINUM; - return (0); - } - alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_ZFS); - if (!strcasecmp(type, alias)) { - *fstype = FS_ZFS; - return (0); + for (i = 0; + i < sizeof(bsd_alias_match) / sizeof(bsd_alias_match[0]); i++) { + alias = g_part_alias_name(bsd_alias_match[i].alias); + if (strcasecmp(type, alias) == 0) { + *fstype = bsd_alias_match[i].type; + return (0); + } } return (EINVAL); } diff --git a/sys/geom/part/g_part_bsd64.c b/sys/geom/part/g_part_bsd64.c new file mode 100644 index 0000000..7586c94 --- /dev/null +++ b/sys/geom/part/g_part_bsd64.c @@ -0,0 +1,667 @@ +/*- + * Copyright (c) 2014 Andrey V. Elsukov <ae@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bio.h> +#include <sys/disklabel.h> +#include <sys/endian.h> +#include <sys/gpt.h> +#include <sys/kernel.h> +#include <sys/kobj.h> +#include <sys/limits.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/queue.h> +#include <sys/sbuf.h> +#include <sys/systm.h> +#include <sys/sysctl.h> +#include <geom/geom.h> +#include <geom/geom_int.h> +#include <geom/part/g_part.h> + +#include "g_part_if.h" + +FEATURE(geom_part_bsd64, "GEOM partitioning class for 64-bit BSD disklabels"); + +/* XXX: move this to sys/disklabel64.h */ +#define DISKMAGIC64 ((uint32_t)0xc4464c59) +#define MAXPARTITIONS64 16 +#define RESPARTITIONS64 32 + +struct disklabel64 { + char d_reserved0[512]; /* reserved or unused */ + u_int32_t d_magic; /* the magic number */ + u_int32_t d_crc; /* crc32() d_magic thru last part */ + u_int32_t d_align; /* partition alignment requirement */ + u_int32_t d_npartitions; /* number of partitions */ + struct uuid d_stor_uuid; /* unique uuid for label */ + + u_int64_t d_total_size; /* total size incl everything (bytes) */ + u_int64_t d_bbase; /* boot area base offset (bytes) */ + /* boot area is pbase - bbase */ + u_int64_t d_pbase; /* first allocatable offset (bytes) */ + u_int64_t d_pstop; /* last allocatable offset+1 (bytes) */ + u_int64_t d_abase; /* location of backup copy if not 0 */ + + u_char d_packname[64]; + u_char d_reserved[64]; + + /* + * Note: offsets are relative to the base of the slice, NOT to + * d_pbase. Unlike 32 bit disklabels the on-disk format for + * a 64 bit disklabel remains slice-relative. + * + * An uninitialized partition has a p_boffset and p_bsize of 0. + * + * If p_fstype is not supported for a live partition it is set + * to FS_OTHER. This is typically the case when the filesystem + * is identified by its uuid. + */ + struct partition64 { /* the partition table */ + u_int64_t p_boffset; /* slice relative offset, in bytes */ + u_int64_t p_bsize; /* size of partition, in bytes */ + u_int8_t p_fstype; + u_int8_t p_unused01; /* reserved, must be 0 */ + u_int8_t p_unused02; /* reserved, must be 0 */ + u_int8_t p_unused03; /* reserved, must be 0 */ + u_int32_t p_unused04; /* reserved, must be 0 */ + u_int32_t p_unused05; /* reserved, must be 0 */ + u_int32_t p_unused06; /* reserved, must be 0 */ + struct uuid p_type_uuid;/* mount type as UUID */ + struct uuid p_stor_uuid;/* unique uuid for storage */ + } d_partitions[MAXPARTITIONS64];/* actually may be more */ +}; + +struct g_part_bsd64_table { + struct g_part_table base; + + uint32_t d_align; + uint64_t d_bbase; + uint64_t d_abase; + struct uuid d_stor_uuid; + char d_reserved0[512]; + u_char d_packname[64]; + u_char d_reserved[64]; +}; + +struct g_part_bsd64_entry { + struct g_part_entry base; + + uint8_t fstype; + struct uuid type_uuid; + struct uuid stor_uuid; +}; + +static int g_part_bsd64_add(struct g_part_table *, struct g_part_entry *, + struct g_part_parms *); +static int g_part_bsd64_bootcode(struct g_part_table *, struct g_part_parms *); +static int g_part_bsd64_create(struct g_part_table *, struct g_part_parms *); +static int g_part_bsd64_destroy(struct g_part_table *, struct g_part_parms *); +static void g_part_bsd64_dumpconf(struct g_part_table *, struct g_part_entry *, + struct sbuf *, const char *); +static int g_part_bsd64_dumpto(struct g_part_table *, struct g_part_entry *); +static int g_part_bsd64_modify(struct g_part_table *, struct g_part_entry *, + struct g_part_parms *); +static const char *g_part_bsd64_name(struct g_part_table *, struct g_part_entry *, + char *, size_t); +static int g_part_bsd64_probe(struct g_part_table *, struct g_consumer *); +static int g_part_bsd64_read(struct g_part_table *, struct g_consumer *); +static const char *g_part_bsd64_type(struct g_part_table *, struct g_part_entry *, + char *, size_t); +static int g_part_bsd64_write(struct g_part_table *, struct g_consumer *); +static int g_part_bsd64_resize(struct g_part_table *, struct g_part_entry *, + struct g_part_parms *); + +static kobj_method_t g_part_bsd64_methods[] = { + KOBJMETHOD(g_part_add, g_part_bsd64_add), + KOBJMETHOD(g_part_bootcode, g_part_bsd64_bootcode), + KOBJMETHOD(g_part_create, g_part_bsd64_create), + KOBJMETHOD(g_part_destroy, g_part_bsd64_destroy), + KOBJMETHOD(g_part_dumpconf, g_part_bsd64_dumpconf), + KOBJMETHOD(g_part_dumpto, g_part_bsd64_dumpto), + KOBJMETHOD(g_part_modify, g_part_bsd64_modify), + KOBJMETHOD(g_part_resize, g_part_bsd64_resize), + KOBJMETHOD(g_part_name, g_part_bsd64_name), + KOBJMETHOD(g_part_probe, g_part_bsd64_probe), + KOBJMETHOD(g_part_read, g_part_bsd64_read), + KOBJMETHOD(g_part_type, g_part_bsd64_type), + KOBJMETHOD(g_part_write, g_part_bsd64_write), + { 0, 0 } +}; + +static struct g_part_scheme g_part_bsd64_scheme = { + "BSD64", + g_part_bsd64_methods, + sizeof(struct g_part_bsd64_table), + .gps_entrysz = sizeof(struct g_part_bsd64_entry), + .gps_minent = MAXPARTITIONS64, + .gps_maxent = MAXPARTITIONS64 +}; +G_PART_SCHEME_DECLARE(g_part_bsd64); + +#define EQUUID(a, b) (memcmp(a, b, sizeof(struct uuid)) == 0) +static struct uuid bsd64_uuid_unused = GPT_ENT_TYPE_UNUSED; +static struct uuid bsd64_uuid_dfbsd_swap = GPT_ENT_TYPE_DRAGONFLY_SWAP; +static struct uuid bsd64_uuid_dfbsd_ufs1 = GPT_ENT_TYPE_DRAGONFLY_UFS1; +static struct uuid bsd64_uuid_dfbsd_vinum = GPT_ENT_TYPE_DRAGONFLY_VINUM; +static struct uuid bsd64_uuid_dfbsd_ccd = GPT_ENT_TYPE_DRAGONFLY_CCD; +static struct uuid bsd64_uuid_dfbsd_legacy = GPT_ENT_TYPE_DRAGONFLY_LEGACY; +static struct uuid bsd64_uuid_dfbsd_hammer = GPT_ENT_TYPE_DRAGONFLY_HAMMER; +static struct uuid bsd64_uuid_dfbsd_hammer2 = GPT_ENT_TYPE_DRAGONFLY_HAMMER2; +static struct uuid bsd64_uuid_freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT; +static struct uuid bsd64_uuid_freebsd_nandfs = GPT_ENT_TYPE_FREEBSD_NANDFS; +static struct uuid bsd64_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; +static struct uuid bsd64_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS; +static struct uuid bsd64_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM; +static struct uuid bsd64_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS; + +struct bsd64_uuid_alias { + struct uuid *uuid; + uint8_t fstype; + int alias; +}; +static struct bsd64_uuid_alias dfbsd_alias_match[] = { + { &bsd64_uuid_dfbsd_swap, FS_SWAP, G_PART_ALIAS_DFBSD_SWAP }, + { &bsd64_uuid_dfbsd_ufs1, FS_BSDFFS, G_PART_ALIAS_DFBSD_UFS }, + { &bsd64_uuid_dfbsd_vinum, FS_VINUM, G_PART_ALIAS_DFBSD_VINUM }, + { &bsd64_uuid_dfbsd_ccd, FS_CCD, G_PART_ALIAS_DFBSD_CCD }, + { &bsd64_uuid_dfbsd_legacy, FS_OTHER, G_PART_ALIAS_DFBSD_LEGACY }, + { &bsd64_uuid_dfbsd_hammer, FS_HAMMER, G_PART_ALIAS_DFBSD_HAMMER }, + { &bsd64_uuid_dfbsd_hammer2, FS_HAMMER2, G_PART_ALIAS_DFBSD_HAMMER2 }, + { NULL, 0, 0} +}; +static struct bsd64_uuid_alias fbsd_alias_match[] = { + { &bsd64_uuid_freebsd_boot, FS_OTHER, G_PART_ALIAS_FREEBSD_BOOT }, + { &bsd64_uuid_freebsd_swap, FS_OTHER, G_PART_ALIAS_FREEBSD_SWAP }, + { &bsd64_uuid_freebsd_ufs, FS_OTHER, G_PART_ALIAS_FREEBSD_UFS }, + { &bsd64_uuid_freebsd_zfs, FS_OTHER, G_PART_ALIAS_FREEBSD_ZFS }, + { &bsd64_uuid_freebsd_vinum, FS_OTHER, G_PART_ALIAS_FREEBSD_VINUM }, + { &bsd64_uuid_freebsd_nandfs, FS_OTHER, G_PART_ALIAS_FREEBSD_NANDFS }, + { NULL, 0, 0} +}; + +static int +bsd64_parse_type(const char *type, struct g_part_bsd64_entry *entry) +{ + struct uuid tmp; + const struct bsd64_uuid_alias *uap; + const char *alias; + char *p; + long lt; + int error; + + if (type[0] == '!') { + if (type[1] == '\0') + return (EINVAL); + lt = strtol(type + 1, &p, 0); + /* The type specified as number */ + if (*p == '\0') { + if (lt <= 0 || lt > 255) + return (EINVAL); + entry->fstype = lt; + entry->type_uuid = bsd64_uuid_unused; + return (0); + } + /* The type specified as uuid */ + error = parse_uuid(type + 1, &tmp); + if (error != 0) + return (error); + if (EQUUID(&tmp, &bsd64_uuid_unused)) + return (EINVAL); + for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) { + if (EQUUID(&tmp, uap->uuid)) { + /* Prefer fstype for known uuids */ + entry->type_uuid = bsd64_uuid_unused; + entry->fstype = uap->fstype; + return (0); + } + } + entry->type_uuid = tmp; + entry->fstype = FS_OTHER; + return (0); + } + /* The type specified as symbolic alias name */ + for (uap = &fbsd_alias_match[0]; uap->uuid != NULL; uap++) { + alias = g_part_alias_name(uap->alias); + if (!strcasecmp(type, alias)) { + entry->type_uuid = *uap->uuid; + entry->fstype = uap->fstype; + return (0); + } + } + for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) { + alias = g_part_alias_name(uap->alias); + if (!strcasecmp(type, alias)) { + entry->type_uuid = bsd64_uuid_unused; + entry->fstype = uap->fstype; + return (0); + } + } + return (EINVAL); +} + +static int +g_part_bsd64_add(struct g_part_table *basetable, struct g_part_entry *baseentry, + struct g_part_parms *gpp) +{ + struct g_part_bsd64_entry *entry; + + if (gpp->gpp_parms & G_PART_PARM_LABEL) + return (EINVAL); + + entry = (struct g_part_bsd64_entry *)baseentry; + if (bsd64_parse_type(gpp->gpp_type, entry) != 0) + return (EINVAL); + kern_uuidgen(&entry->stor_uuid, 1); + return (0); +} + +static int +g_part_bsd64_bootcode(struct g_part_table *basetable, struct g_part_parms *gpp) +{ + + return (EOPNOTSUPP); +} + +#define PALIGN_SIZE (1024 * 1024) +#define PALIGN_MASK (PALIGN_SIZE - 1) +#define BLKSIZE (4 * 1024) +#define BOOTSIZE (32 * 1024) +#define DALIGN_SIZE (32 * 1024) +static int +g_part_bsd64_create(struct g_part_table *basetable, struct g_part_parms *gpp) +{ + struct g_part_bsd64_table *table; + struct g_part_entry *baseentry; + struct g_provider *pp; + uint64_t blkmask, pbase; + uint32_t blksize, ressize; + + pp = gpp->gpp_provider; + if (pp->mediasize < 2* PALIGN_SIZE) + return (ENOSPC); + + /* + * Use at least 4KB block size. Blksize is stored in the d_align. + * XXX: Actually it is used just for calculate d_bbase and used + * for better alignment in bsdlabel64(8). + */ + blksize = pp->sectorsize < BLKSIZE ? BLKSIZE: pp->sectorsize; + blkmask = blksize - 1; + /* Reserve enough space for RESPARTITIONS64 partitions. */ + ressize = offsetof(struct disklabel64, d_partitions[RESPARTITIONS64]); + ressize = (ressize + blkmask) & ~blkmask; + /* + * Reserve enough space for bootcode and align first allocatable + * offset to PALIGN_SIZE. + * XXX: Currently DragonFlyBSD has 32KB bootcode, but the size could + * be bigger, because it is possible change it (it is equal pbase-bbase) + * in the bsdlabel64(8). + */ + pbase = ressize + ((BOOTSIZE + blkmask) & ~blkmask); + pbase = (pbase + PALIGN_MASK) & ~PALIGN_MASK; + /* + * Take physical offset into account and make first allocatable + * offset 32KB aligned to the start of the physical disk. + * XXX: Actually there are no such restrictions, this is how + * DragonFlyBSD behaves. + */ + pbase += DALIGN_SIZE - pp->stripeoffset % DALIGN_SIZE; + + table = (struct g_part_bsd64_table *)basetable; + table->d_align = blksize; + table->d_bbase = ressize / pp->sectorsize; + table->d_abase = ((pp->mediasize - ressize) & + ~blkmask) / pp->sectorsize; + kern_uuidgen(&table->d_stor_uuid, 1); + basetable->gpt_first = pbase / pp->sectorsize; + basetable->gpt_last = table->d_abase - 1; /* XXX */ + /* + * Create 'c' partition and make it internal, so user will not be + * able use it. + */ + baseentry = g_part_new_entry(basetable, RAW_PART + 1, 0, 0); + baseentry->gpe_internal = 1; + return (0); +} + +static int +g_part_bsd64_destroy(struct g_part_table *basetable, struct g_part_parms *gpp) +{ + struct g_provider *pp; + + pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider; + if (pp->sectorsize > offsetof(struct disklabel64, d_magic)) + basetable->gpt_smhead |= 1; + else + basetable->gpt_smhead |= 3; + return (0); +} + +static void +g_part_bsd64_dumpconf(struct g_part_table *basetable, + struct g_part_entry *baseentry, struct sbuf *sb, const char *indent) +{ + struct g_part_bsd64_table *table; + struct g_part_bsd64_entry *entry; + char buf[sizeof(table->d_packname)]; + + entry = (struct g_part_bsd64_entry *)baseentry; + if (indent == NULL) { + /* conftxt: libdisk compatibility */ + sbuf_printf(sb, " xs BSD64 xt %u", entry->fstype); + } else if (entry != NULL) { + /* confxml: partition entry information */ + sbuf_printf(sb, "%s<rawtype>%u</rawtype>\n", indent, + entry->fstype); + if (!EQUUID(&bsd64_uuid_unused, &entry->type_uuid)) { + sbuf_printf(sb, "%s<type_uuid>", indent); + sbuf_printf_uuid(sb, &entry->type_uuid); + sbuf_printf(sb, "</type_uuid>\n"); + } + sbuf_printf(sb, "%s<stor_uuid>", indent); + sbuf_printf_uuid(sb, &entry->stor_uuid); + sbuf_printf(sb, "</stor_uuid>\n"); + } else { + /* confxml: scheme information */ + table = (struct g_part_bsd64_table *)basetable; + sbuf_printf(sb, "%s<bootbase>%ju</bootbase>\n", indent, + (uintmax_t)table->d_bbase); + if (table->d_abase) + sbuf_printf(sb, "%s<backupbase>%ju</backupbase>\n", + indent, (uintmax_t)table->d_abase); + sbuf_printf(sb, "%s<stor_uuid>", indent); + sbuf_printf_uuid(sb, &table->d_stor_uuid); + sbuf_printf(sb, "</stor_uuid>\n"); + sbuf_printf(sb, "%s<label>", indent); + strncpy(buf, table->d_packname, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + g_conf_printf_escaped(sb, "%s", buf); + sbuf_printf(sb, "</label>\n"); + } +} + +static int +g_part_bsd64_dumpto(struct g_part_table *table, struct g_part_entry *baseentry) +{ + struct g_part_bsd64_entry *entry; + + /* Allow dumping to a swap partition. */ + entry = (struct g_part_bsd64_entry *)baseentry; + if (entry->fstype == FS_SWAP || + EQUUID(&entry->type_uuid, &bsd64_uuid_dfbsd_swap) || + EQUUID(&entry->type_uuid, &bsd64_uuid_freebsd_swap)) + return (1); + return (0); +} + +static int +g_part_bsd64_modify(struct g_part_table *basetable, + struct g_part_entry *baseentry, struct g_part_parms *gpp) +{ + struct g_part_bsd64_entry *entry; + + if (gpp->gpp_parms & G_PART_PARM_LABEL) + return (EINVAL); + + entry = (struct g_part_bsd64_entry *)baseentry; + if (gpp->gpp_parms & G_PART_PARM_TYPE) + return (bsd64_parse_type(gpp->gpp_type, entry)); + return (0); +} + +static int +g_part_bsd64_resize(struct g_part_table *basetable, + struct g_part_entry *baseentry, struct g_part_parms *gpp) +{ + struct g_part_bsd64_table *table; + struct g_provider *pp; + + if (baseentry == NULL) { + pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider; + table = (struct g_part_bsd64_table *)basetable; + table->d_abase = ((pp->mediasize - + table->d_bbase * pp->sectorsize) & ~(table->d_align - 1)) / + pp->sectorsize; + basetable->gpt_last = table->d_abase - 1; + return (0); + } + baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1; + return (0); +} + +static const char * +g_part_bsd64_name(struct g_part_table *table, struct g_part_entry *baseentry, + char *buf, size_t bufsz) +{ + + snprintf(buf, bufsz, "%c", 'a' + baseentry->gpe_index - 1); + return (buf); +} + +static int +g_part_bsd64_probe(struct g_part_table *table, struct g_consumer *cp) +{ + struct g_provider *pp; + uint32_t v; + int error; + u_char *buf; + + pp = cp->provider; + if (pp->mediasize < 2 * PALIGN_SIZE) + return (ENOSPC); + v = (pp->sectorsize + + offsetof(struct disklabel64, d_magic)) & ~(pp->sectorsize - 1); + buf = g_read_data(cp, 0, v, &error); + if (buf == NULL) + return (error); + v = le32dec(buf + offsetof(struct disklabel64, d_magic)); + g_free(buf); + return (v == DISKMAGIC64 ? G_PART_PROBE_PRI_HIGH: ENXIO); +} + +static int +g_part_bsd64_read(struct g_part_table *basetable, struct g_consumer *cp) +{ + struct g_part_bsd64_table *table; + struct g_part_bsd64_entry *entry; + struct g_part_entry *baseentry; + struct g_provider *pp; + struct disklabel64 *dlp; + uint64_t v64, sz; + uint32_t v32; + int error, index; + u_char *buf; + + pp = cp->provider; + table = (struct g_part_bsd64_table *)basetable; + v32 = (pp->sectorsize + + sizeof(struct disklabel64) - 1) & ~(pp->sectorsize - 1); + buf = g_read_data(cp, 0, v32, &error); + if (buf == NULL) + return (error); + + dlp = (struct disklabel64 *)buf; + basetable->gpt_entries = le32toh(dlp->d_npartitions); + if (basetable->gpt_entries > MAXPARTITIONS64) + goto invalid_label; + v32 = le32toh(dlp->d_crc); + dlp->d_crc = 0; + if (crc32(&dlp->d_magic, offsetof(struct disklabel64, + d_partitions[basetable->gpt_entries]) - + offsetof(struct disklabel64, d_magic)) != v32) + goto invalid_label; + table->d_align = le32toh(dlp->d_align); + if (table->d_align == 0 || (table->d_align & (pp->sectorsize - 1))) + goto invalid_label; + if (le64toh(dlp->d_total_size) > pp->mediasize) + goto invalid_label; + v64 = le64toh(dlp->d_pbase); + if (v64 % pp->sectorsize) + goto invalid_label; + basetable->gpt_first = v64 / pp->sectorsize; + v64 = le64toh(dlp->d_pstop); + if (v64 % pp->sectorsize) + goto invalid_label; + basetable->gpt_last = v64 / pp->sectorsize; + basetable->gpt_isleaf = 1; + v64 = le64toh(dlp->d_bbase); + if (v64 % pp->sectorsize) + goto invalid_label; + table->d_bbase = v64 / pp->sectorsize; + v64 = le64toh(dlp->d_abase); + if (v64 % pp->sectorsize) + goto invalid_label; + table->d_abase = v64 / pp->sectorsize; + le_uuid_dec(&dlp->d_stor_uuid, &table->d_stor_uuid); + for (index = basetable->gpt_entries - 1; index >= 0; index--) { + if (index == RAW_PART) { + /* Skip 'c' partition. */ + baseentry = g_part_new_entry(basetable, + index + 1, 0, 0); + baseentry->gpe_internal = 1; + continue; + } + v64 = le64toh(dlp->d_partitions[index].p_boffset); + sz = le64toh(dlp->d_partitions[index].p_bsize); + if (sz == 0 && v64 == 0) + continue; + if (sz == 0 || (v64 % pp->sectorsize) || (sz % pp->sectorsize)) + goto invalid_label; + baseentry = g_part_new_entry(basetable, index + 1, + v64 / pp->sectorsize, (v64 + sz) / pp->sectorsize - 1); + entry = (struct g_part_bsd64_entry *)baseentry; + le_uuid_dec(&dlp->d_partitions[index].p_type_uuid, + &entry->type_uuid); + le_uuid_dec(&dlp->d_partitions[index].p_stor_uuid, + &entry->stor_uuid); + entry->fstype = dlp->d_partitions[index].p_fstype; + if (index == RAW_PART) + baseentry->gpe_internal = 1; + } + bcopy(dlp->d_reserved0, table->d_reserved0, + sizeof(table->d_reserved0)); + bcopy(dlp->d_packname, table->d_packname, sizeof(table->d_packname)); + bcopy(dlp->d_reserved, table->d_reserved, sizeof(table->d_reserved)); + g_free(buf); + return (0); + +invalid_label: + g_free(buf); + return (EINVAL); +} + +static const char * +g_part_bsd64_type(struct g_part_table *basetable, struct g_part_entry *baseentry, + char *buf, size_t bufsz) +{ + struct g_part_bsd64_entry *entry; + struct bsd64_uuid_alias *uap; + + entry = (struct g_part_bsd64_entry *)baseentry; + if (entry->fstype != FS_OTHER) { + for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) + if (uap->fstype == entry->fstype) + return (g_part_alias_name(uap->alias)); + } else { + for (uap = &fbsd_alias_match[0]; uap->uuid != NULL; uap++) + if (EQUUID(uap->uuid, &entry->type_uuid)) + return (g_part_alias_name(uap->alias)); + for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) + if (EQUUID(uap->uuid, &entry->type_uuid)) + return (g_part_alias_name(uap->alias)); + } + if (EQUUID(&bsd64_uuid_unused, &entry->type_uuid)) + snprintf(buf, bufsz, "!%d", entry->fstype); + else { + buf[0] = '!'; + snprintf_uuid(buf + 1, bufsz - 1, &entry->type_uuid); + } + return (buf); +} + +static int +g_part_bsd64_write(struct g_part_table *basetable, struct g_consumer *cp) +{ + struct g_provider *pp; + struct g_part_entry *baseentry; + struct g_part_bsd64_entry *entry; + struct g_part_bsd64_table *table; + struct disklabel64 *dlp; + uint32_t v, sz; + int error, index; + + pp = cp->provider; + table = (struct g_part_bsd64_table *)basetable; + sz = (pp->sectorsize + + sizeof(struct disklabel64) - 1) & ~(pp->sectorsize - 1); + dlp = g_malloc(sz, M_WAITOK | M_ZERO); + + memcpy(dlp->d_reserved0, table->d_reserved0, + sizeof(table->d_reserved0)); + memcpy(dlp->d_packname, table->d_packname, sizeof(table->d_packname)); + memcpy(dlp->d_reserved, table->d_reserved, sizeof(table->d_reserved)); + le32enc(&dlp->d_magic, DISKMAGIC64); + le32enc(&dlp->d_align, table->d_align); + le32enc(&dlp->d_npartitions, basetable->gpt_entries); + le_uuid_enc(&dlp->d_stor_uuid, &table->d_stor_uuid); + le64enc(&dlp->d_total_size, pp->mediasize); + le64enc(&dlp->d_bbase, table->d_bbase * pp->sectorsize); + le64enc(&dlp->d_pbase, basetable->gpt_first * pp->sectorsize); + le64enc(&dlp->d_pstop, basetable->gpt_last * pp->sectorsize); + le64enc(&dlp->d_abase, table->d_abase * pp->sectorsize); + + LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) { + if (baseentry->gpe_deleted) + continue; + index = baseentry->gpe_index - 1; + entry = (struct g_part_bsd64_entry *)baseentry; + if (index == RAW_PART) + continue; + le64enc(&dlp->d_partitions[index].p_boffset, + baseentry->gpe_start * pp->sectorsize); + le64enc(&dlp->d_partitions[index].p_bsize, pp->sectorsize * + (baseentry->gpe_end - baseentry->gpe_start + 1)); + dlp->d_partitions[index].p_fstype = entry->fstype; + le_uuid_enc(&dlp->d_partitions[index].p_type_uuid, + &entry->type_uuid); + le_uuid_enc(&dlp->d_partitions[index].p_stor_uuid, + &entry->stor_uuid); + } + /* Calculate checksum. */ + v = offsetof(struct disklabel64, + d_partitions[basetable->gpt_entries]) - + offsetof(struct disklabel64, d_magic); + le32enc(&dlp->d_crc, crc32(&dlp->d_magic, v)); + error = g_write_data(cp, 0, dlp, sz); + g_free(dlp); + return (error); +} + diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c index 4af2868..46841f4 100644 --- a/sys/geom/part/g_part_gpt.c +++ b/sys/geom/part/g_part_gpt.c @@ -181,6 +181,15 @@ static struct uuid gpt_uuid_netbsd_raid = GPT_ENT_TYPE_NETBSD_RAID; static struct uuid gpt_uuid_netbsd_swap = GPT_ENT_TYPE_NETBSD_SWAP; static struct uuid gpt_uuid_mbr = GPT_ENT_TYPE_MBR; static struct uuid gpt_uuid_unused = GPT_ENT_TYPE_UNUSED; +static struct uuid gpt_uuid_dfbsd_swap = GPT_ENT_TYPE_DRAGONFLY_SWAP; +static struct uuid gpt_uuid_dfbsd_ufs1 = GPT_ENT_TYPE_DRAGONFLY_UFS1; +static struct uuid gpt_uuid_dfbsd_vinum = GPT_ENT_TYPE_DRAGONFLY_VINUM; +static struct uuid gpt_uuid_dfbsd_ccd = GPT_ENT_TYPE_DRAGONFLY_CCD; +static struct uuid gpt_uuid_dfbsd_legacy = GPT_ENT_TYPE_DRAGONFLY_LEGACY; +static struct uuid gpt_uuid_dfbsd_hammer = GPT_ENT_TYPE_DRAGONFLY_HAMMER; +static struct uuid gpt_uuid_dfbsd_hammer2 = GPT_ENT_TYPE_DRAGONFLY_HAMMER2; +static struct uuid gpt_uuid_dfbsd_label32 = GPT_ENT_TYPE_DRAGONFLY_LABEL32; +static struct uuid gpt_uuid_dfbsd_label64 = GPT_ENT_TYPE_DRAGONFLY_LABEL64; static struct g_part_uuid_alias { struct uuid *uuid; @@ -222,6 +231,15 @@ static struct g_part_uuid_alias { { &gpt_uuid_netbsd_lfs, G_PART_ALIAS_NETBSD_LFS, 0 }, { &gpt_uuid_netbsd_raid, G_PART_ALIAS_NETBSD_RAID, 0 }, { &gpt_uuid_netbsd_swap, G_PART_ALIAS_NETBSD_SWAP, 0 }, + { &gpt_uuid_dfbsd_swap, G_PART_ALIAS_DFBSD_SWAP, 0 }, + { &gpt_uuid_dfbsd_ufs1, G_PART_ALIAS_DFBSD_UFS, 0 }, + { &gpt_uuid_dfbsd_vinum, G_PART_ALIAS_DFBSD_VINUM, 0 }, + { &gpt_uuid_dfbsd_ccd, G_PART_ALIAS_DFBSD_CCD, 0 }, + { &gpt_uuid_dfbsd_legacy, G_PART_ALIAS_DFBSD_LEGACY, 0 }, + { &gpt_uuid_dfbsd_hammer, G_PART_ALIAS_DFBSD_HAMMER, 0 }, + { &gpt_uuid_dfbsd_hammer2, G_PART_ALIAS_DFBSD_HAMMER2, 0 }, + { &gpt_uuid_dfbsd_label32, G_PART_ALIAS_DFBSD, 0xa5 }, + { &gpt_uuid_dfbsd_label64, G_PART_ALIAS_DFBSD64, 0xa5 }, { NULL, 0, 0 } }; @@ -706,7 +724,8 @@ g_part_gpt_dumpto(struct g_part_table *table, struct g_part_entry *baseentry) entry = (struct g_part_gpt_entry *)baseentry; return ((EQUUID(&entry->ent.ent_type, &gpt_uuid_freebsd_swap) || - EQUUID(&entry->ent.ent_type, &gpt_uuid_linux_swap)) ? 1 : 0); + EQUUID(&entry->ent.ent_type, &gpt_uuid_linux_swap) || + EQUUID(&entry->ent.ent_type, &gpt_uuid_dfbsd_swap)) ? 1 : 0); } static int diff --git a/sys/modules/geom/geom_part/Makefile b/sys/modules/geom/geom_part/Makefile index b198bb8..aa6059c 100644 --- a/sys/modules/geom/geom_part/Makefile +++ b/sys/modules/geom/geom_part/Makefile @@ -2,6 +2,7 @@ SUBDIR= geom_part_apm \ geom_part_bsd \ + geom_part_bsd64 \ geom_part_ebr \ geom_part_gpt \ geom_part_ldm \ diff --git a/sys/modules/geom/geom_part/geom_part_bsd64/Makefile b/sys/modules/geom/geom_part/geom_part_bsd64/Makefile new file mode 100644 index 0000000..bc1bb55 --- /dev/null +++ b/sys/modules/geom/geom_part/geom_part_bsd64/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../../geom/part + +KMOD= geom_part_bsd64 +SRCS= g_part_bsd64.c + +SRCS+= bus_if.h device_if.h g_part_if.h + +MFILES= kern/bus_if.m kern/device_if.m geom/part/g_part_if.m + +.include <bsd.kmod.mk> diff --git a/sys/sys/disklabel.h b/sys/sys/disklabel.h index d135afa..c3501e0 100644 --- a/sys/sys/disklabel.h +++ b/sys/sys/disklabel.h @@ -229,6 +229,8 @@ static const char *dktypenames[] = { #define FS_NTFS 18 /* Windows/NT file system */ #define FS_CCD 20 /* concatenated disk component */ #define FS_JFS2 21 /* IBM JFS2 */ +#define FS_HAMMER 22 /* DragonFlyBSD Hammer FS */ +#define FS_HAMMER2 23 /* DragonFlyBSD Hammer2 FS */ #define FS_UDF 24 /* UDF */ #define FS_EFS 26 /* SGI's Extent File system */ #define FS_ZFS 27 /* Sun's ZFS */ @@ -258,8 +260,8 @@ static const char *fstypenames[] = { "?", "ccd", "jfs", - "?", - "?", + "HAMMER", + "HAMMER2", "UDF", "?", "EFS", diff --git a/sys/sys/gpt.h b/sys/sys/gpt.h index 82924e7..0f14f39 100644 --- a/sys/sys/gpt.h +++ b/sys/sys/gpt.h @@ -161,6 +161,25 @@ struct gpt_ent { #define GPT_ENT_TYPE_NETBSD_CGD \ {0x2db519ec,0xb10f,0x11dc,0xb9,0x9b,{0x00,0x19,0xd1,0x87,0x96,0x48}} +#define GPT_ENT_TYPE_DRAGONFLY_LABEL32 \ + {0x9d087404,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_SWAP \ + {0x9d58fdbd,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_UFS1 \ + {0x9d94ce7c,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_VINUM \ + {0x9dd4478f,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_CCD \ + {0xdbd5211b,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_LABEL64 \ + {0x3d48ce54,0x1d16,0x11dc,0x86,0x96,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_LEGACY \ + {0xbd215ab2,0x1d16,0x11dc,0x86,0x96,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_HAMMER \ + {0x61dc63ac,0x6e38,0x11dc,0x85,0x13,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_HAMMER2 \ + {0x5cbb9ad1,0x862d,0x11dc,0xa9,0x4d,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} + /* * Boot partition used by GRUB 2. */ |