The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/geom/part/g_part_bsd64.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2014 Andrey V. Elsukov <ae@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  *
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/bio.h>
   32 #include <sys/gsb_crc32.h>
   33 #include <sys/disklabel.h>
   34 #include <sys/endian.h>
   35 #include <sys/gpt.h>
   36 #include <sys/kernel.h>
   37 #include <sys/kobj.h>
   38 #include <sys/limits.h>
   39 #include <sys/lock.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mutex.h>
   42 #include <sys/queue.h>
   43 #include <sys/sbuf.h>
   44 #include <sys/systm.h>
   45 #include <sys/sysctl.h>
   46 #include <geom/geom.h>
   47 #include <geom/geom_int.h>
   48 #include <geom/part/g_part.h>
   49 
   50 #include "g_part_if.h"
   51 
   52 FEATURE(geom_part_bsd64, "GEOM partitioning class for 64-bit BSD disklabels");
   53 
   54 /* XXX: move this to sys/disklabel64.h */
   55 #define DISKMAGIC64     ((uint32_t)0xc4464c59)
   56 #define MAXPARTITIONS64 16
   57 #define RESPARTITIONS64 32
   58 
   59 struct disklabel64 {
   60         char      d_reserved0[512];     /* reserved or unused */
   61         uint32_t d_magic;               /* the magic number */
   62         uint32_t d_crc;         /* crc32() d_magic through last part */
   63         uint32_t d_align;               /* partition alignment requirement */
   64         uint32_t d_npartitions; /* number of partitions */
   65         struct uuid d_stor_uuid;        /* unique uuid for label */
   66 
   67         uint64_t d_total_size;          /* total size incl everything (bytes) */
   68         uint64_t d_bbase;               /* boot area base offset (bytes) */
   69                                         /* boot area is pbase - bbase */
   70         uint64_t d_pbase;               /* first allocatable offset (bytes) */
   71         uint64_t d_pstop;               /* last allocatable offset+1 (bytes) */
   72         uint64_t d_abase;               /* location of backup copy if not 0 */
   73 
   74         u_char    d_packname[64];
   75         u_char    d_reserved[64];
   76 
   77         /*
   78          * Note: offsets are relative to the base of the slice, NOT to
   79          * d_pbase.  Unlike 32 bit disklabels the on-disk format for
   80          * a 64 bit disklabel remains slice-relative.
   81          *
   82          * An uninitialized partition has a p_boffset and p_bsize of 0.
   83          *
   84          * If p_fstype is not supported for a live partition it is set
   85          * to FS_OTHER.  This is typically the case when the filesystem
   86          * is identified by its uuid.
   87          */
   88         struct partition64 {            /* the partition table */
   89                 uint64_t p_boffset;     /* slice relative offset, in bytes */
   90                 uint64_t p_bsize;       /* size of partition, in bytes */
   91                 uint8_t  p_fstype;
   92                 uint8_t  p_unused01;    /* reserved, must be 0 */
   93                 uint8_t  p_unused02;    /* reserved, must be 0 */
   94                 uint8_t  p_unused03;    /* reserved, must be 0 */
   95                 uint32_t p_unused04;    /* reserved, must be 0 */
   96                 uint32_t p_unused05;    /* reserved, must be 0 */
   97                 uint32_t p_unused06;    /* reserved, must be 0 */
   98                 struct uuid p_type_uuid;/* mount type as UUID */
   99                 struct uuid p_stor_uuid;/* unique uuid for storage */
  100         } d_partitions[MAXPARTITIONS64];/* actually may be more */
  101 };
  102 
  103 struct g_part_bsd64_table {
  104         struct g_part_table     base;
  105 
  106         uint32_t                d_align;
  107         uint64_t                d_bbase;
  108         uint64_t                d_abase;
  109         struct uuid             d_stor_uuid;
  110         char                    d_reserved0[512];
  111         u_char                  d_packname[64];
  112         u_char                  d_reserved[64];
  113 };
  114 
  115 struct g_part_bsd64_entry {
  116         struct g_part_entry     base;
  117 
  118         uint8_t                 fstype;
  119         struct uuid             type_uuid;
  120         struct uuid             stor_uuid;
  121 };
  122 
  123 static int g_part_bsd64_add(struct g_part_table *, struct g_part_entry *,
  124     struct g_part_parms *);
  125 static int g_part_bsd64_bootcode(struct g_part_table *, struct g_part_parms *);
  126 static int g_part_bsd64_create(struct g_part_table *, struct g_part_parms *);
  127 static int g_part_bsd64_destroy(struct g_part_table *, struct g_part_parms *);
  128 static void g_part_bsd64_dumpconf(struct g_part_table *, struct g_part_entry *,
  129     struct sbuf *, const char *);
  130 static int g_part_bsd64_dumpto(struct g_part_table *, struct g_part_entry *);
  131 static int g_part_bsd64_modify(struct g_part_table *, struct g_part_entry *,
  132     struct g_part_parms *);
  133 static const char *g_part_bsd64_name(struct g_part_table *, struct g_part_entry *,
  134     char *, size_t);
  135 static int g_part_bsd64_probe(struct g_part_table *, struct g_consumer *);
  136 static int g_part_bsd64_read(struct g_part_table *, struct g_consumer *);
  137 static const char *g_part_bsd64_type(struct g_part_table *, struct g_part_entry *,
  138     char *, size_t);
  139 static int g_part_bsd64_write(struct g_part_table *, struct g_consumer *);
  140 static int g_part_bsd64_resize(struct g_part_table *, struct g_part_entry *,
  141     struct g_part_parms *);
  142 
  143 static kobj_method_t g_part_bsd64_methods[] = {
  144         KOBJMETHOD(g_part_add,          g_part_bsd64_add),
  145         KOBJMETHOD(g_part_bootcode,     g_part_bsd64_bootcode),
  146         KOBJMETHOD(g_part_create,       g_part_bsd64_create),
  147         KOBJMETHOD(g_part_destroy,      g_part_bsd64_destroy),
  148         KOBJMETHOD(g_part_dumpconf,     g_part_bsd64_dumpconf),
  149         KOBJMETHOD(g_part_dumpto,       g_part_bsd64_dumpto),
  150         KOBJMETHOD(g_part_modify,       g_part_bsd64_modify),
  151         KOBJMETHOD(g_part_resize,       g_part_bsd64_resize),
  152         KOBJMETHOD(g_part_name,         g_part_bsd64_name),
  153         KOBJMETHOD(g_part_probe,        g_part_bsd64_probe),
  154         KOBJMETHOD(g_part_read,         g_part_bsd64_read),
  155         KOBJMETHOD(g_part_type,         g_part_bsd64_type),
  156         KOBJMETHOD(g_part_write,        g_part_bsd64_write),
  157         { 0, 0 }
  158 };
  159 
  160 static struct g_part_scheme g_part_bsd64_scheme = {
  161         "BSD64",
  162         g_part_bsd64_methods,
  163         sizeof(struct g_part_bsd64_table),
  164         .gps_entrysz = sizeof(struct g_part_bsd64_entry),
  165         .gps_minent = MAXPARTITIONS64,
  166         .gps_maxent = MAXPARTITIONS64
  167 };
  168 G_PART_SCHEME_DECLARE(g_part_bsd64);
  169 MODULE_VERSION(geom_part_bsd64, 0);
  170 
  171 #define EQUUID(a, b)    (memcmp(a, b, sizeof(struct uuid)) == 0)
  172 static struct uuid bsd64_uuid_unused = GPT_ENT_TYPE_UNUSED;
  173 static struct uuid bsd64_uuid_dfbsd_swap = GPT_ENT_TYPE_DRAGONFLY_SWAP;
  174 static struct uuid bsd64_uuid_dfbsd_ufs1 = GPT_ENT_TYPE_DRAGONFLY_UFS1;
  175 static struct uuid bsd64_uuid_dfbsd_vinum = GPT_ENT_TYPE_DRAGONFLY_VINUM;
  176 static struct uuid bsd64_uuid_dfbsd_ccd = GPT_ENT_TYPE_DRAGONFLY_CCD;
  177 static struct uuid bsd64_uuid_dfbsd_legacy = GPT_ENT_TYPE_DRAGONFLY_LEGACY;
  178 static struct uuid bsd64_uuid_dfbsd_hammer = GPT_ENT_TYPE_DRAGONFLY_HAMMER;
  179 static struct uuid bsd64_uuid_dfbsd_hammer2 = GPT_ENT_TYPE_DRAGONFLY_HAMMER2;
  180 static struct uuid bsd64_uuid_freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT;
  181 static struct uuid bsd64_uuid_freebsd_nandfs = GPT_ENT_TYPE_FREEBSD_NANDFS;
  182 static struct uuid bsd64_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP;
  183 static struct uuid bsd64_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS;
  184 static struct uuid bsd64_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM;
  185 static struct uuid bsd64_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS;
  186 
  187 struct bsd64_uuid_alias {
  188         struct uuid *uuid;
  189         uint8_t fstype;
  190         int alias;
  191 };
  192 static struct bsd64_uuid_alias dfbsd_alias_match[] = {
  193         { &bsd64_uuid_dfbsd_swap, FS_SWAP, G_PART_ALIAS_DFBSD_SWAP },
  194         { &bsd64_uuid_dfbsd_ufs1, FS_BSDFFS, G_PART_ALIAS_DFBSD_UFS },
  195         { &bsd64_uuid_dfbsd_vinum, FS_VINUM, G_PART_ALIAS_DFBSD_VINUM },
  196         { &bsd64_uuid_dfbsd_ccd, FS_CCD, G_PART_ALIAS_DFBSD_CCD },
  197         { &bsd64_uuid_dfbsd_legacy, FS_OTHER, G_PART_ALIAS_DFBSD_LEGACY },
  198         { &bsd64_uuid_dfbsd_hammer, FS_HAMMER, G_PART_ALIAS_DFBSD_HAMMER },
  199         { &bsd64_uuid_dfbsd_hammer2, FS_HAMMER2, G_PART_ALIAS_DFBSD_HAMMER2 },
  200         { NULL, 0, 0}
  201 };
  202 static struct bsd64_uuid_alias fbsd_alias_match[] = {
  203         { &bsd64_uuid_freebsd_boot, FS_OTHER, G_PART_ALIAS_FREEBSD_BOOT },
  204         { &bsd64_uuid_freebsd_swap, FS_OTHER, G_PART_ALIAS_FREEBSD_SWAP },
  205         { &bsd64_uuid_freebsd_ufs, FS_OTHER, G_PART_ALIAS_FREEBSD_UFS },
  206         { &bsd64_uuid_freebsd_zfs, FS_OTHER, G_PART_ALIAS_FREEBSD_ZFS },
  207         { &bsd64_uuid_freebsd_vinum, FS_OTHER, G_PART_ALIAS_FREEBSD_VINUM },
  208         { &bsd64_uuid_freebsd_nandfs, FS_OTHER, G_PART_ALIAS_FREEBSD_NANDFS },
  209         { NULL, 0, 0}
  210 };
  211 
  212 static int
  213 bsd64_parse_type(const char *type, struct g_part_bsd64_entry *entry)
  214 {
  215         struct uuid tmp;
  216         const struct bsd64_uuid_alias *uap;
  217         const char *alias;
  218         char *p;
  219         long lt;
  220         int error;
  221 
  222         if (type[0] == '!') {
  223                 if (type[1] == '\0')
  224                         return (EINVAL);
  225                 lt = strtol(type + 1, &p, 0);
  226                 /* The type specified as number */
  227                 if (*p == '\0') {
  228                         if (lt <= 0 || lt > 255)
  229                                 return (EINVAL);
  230                         entry->fstype = lt;
  231                         entry->type_uuid = bsd64_uuid_unused;
  232                         return (0);
  233                 }
  234                 /* The type specified as uuid */
  235                 error = parse_uuid(type + 1, &tmp);
  236                 if (error != 0)
  237                         return (error);
  238                 if (EQUUID(&tmp, &bsd64_uuid_unused))
  239                         return (EINVAL);
  240                 for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) {
  241                         if (EQUUID(&tmp, uap->uuid)) {
  242                                 /* Prefer fstype for known uuids */
  243                                 entry->type_uuid = bsd64_uuid_unused;
  244                                 entry->fstype = uap->fstype;
  245                                 return (0);
  246                         }
  247                 }
  248                 entry->type_uuid = tmp;
  249                 entry->fstype = FS_OTHER;
  250                 return (0);
  251         }
  252         /* The type specified as symbolic alias name */
  253         for (uap = &fbsd_alias_match[0]; uap->uuid != NULL; uap++) {
  254                 alias = g_part_alias_name(uap->alias);
  255                 if (!strcasecmp(type, alias)) {
  256                         entry->type_uuid = *uap->uuid;
  257                         entry->fstype = uap->fstype;
  258                         return (0);
  259                 }
  260         }
  261         for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) {
  262                 alias = g_part_alias_name(uap->alias);
  263                 if (!strcasecmp(type, alias)) {
  264                         entry->type_uuid = bsd64_uuid_unused;
  265                         entry->fstype = uap->fstype;
  266                         return (0);
  267                 }
  268         }
  269         return (EINVAL);
  270 }
  271 
  272 static int
  273 g_part_bsd64_add(struct g_part_table *basetable, struct g_part_entry *baseentry,
  274     struct g_part_parms *gpp)
  275 {
  276         struct g_part_bsd64_entry *entry;
  277 
  278         if (gpp->gpp_parms & G_PART_PARM_LABEL)
  279                 return (EINVAL);
  280 
  281         entry = (struct g_part_bsd64_entry *)baseentry;
  282         if (bsd64_parse_type(gpp->gpp_type, entry) != 0)
  283                 return (EINVAL);
  284         kern_uuidgen(&entry->stor_uuid, 1);
  285         return (0);
  286 }
  287 
  288 static int
  289 g_part_bsd64_bootcode(struct g_part_table *basetable, struct g_part_parms *gpp)
  290 {
  291 
  292         return (EOPNOTSUPP);
  293 }
  294 
  295 #define PALIGN_SIZE     (1024 * 1024)
  296 #define PALIGN_MASK     (PALIGN_SIZE - 1)
  297 #define BLKSIZE         (4 * 1024)
  298 #define BOOTSIZE        (32 * 1024)
  299 #define DALIGN_SIZE     (32 * 1024)
  300 static int
  301 g_part_bsd64_create(struct g_part_table *basetable, struct g_part_parms *gpp)
  302 {
  303         struct g_part_bsd64_table *table;
  304         struct g_part_entry *baseentry;
  305         struct g_provider *pp;
  306         uint64_t blkmask, pbase;
  307         uint32_t blksize, ressize;
  308 
  309         pp = gpp->gpp_provider;
  310         if (pp->mediasize < 2* PALIGN_SIZE)
  311                 return (ENOSPC);
  312 
  313         /*
  314          * Use at least 4KB block size. Blksize is stored in the d_align.
  315          * XXX: Actually it is used just for calculate d_bbase and used
  316          * for better alignment in bsdlabel64(8).
  317          */
  318         blksize = pp->sectorsize < BLKSIZE ? BLKSIZE: pp->sectorsize;
  319         blkmask = blksize - 1;
  320         /* Reserve enough space for RESPARTITIONS64 partitions. */
  321         ressize = offsetof(struct disklabel64, d_partitions[RESPARTITIONS64]);
  322         ressize = (ressize + blkmask) & ~blkmask;
  323         /*
  324          * Reserve enough space for bootcode and align first allocatable
  325          * offset to PALIGN_SIZE.
  326          * XXX: Currently DragonFlyBSD has 32KB bootcode, but the size could
  327          * be bigger, because it is possible change it (it is equal pbase-bbase)
  328          * in the bsdlabel64(8).
  329          */
  330         pbase = ressize + ((BOOTSIZE + blkmask) & ~blkmask);
  331         pbase = (pbase + PALIGN_MASK) & ~PALIGN_MASK;
  332         /*
  333          * Take physical offset into account and make first allocatable
  334          * offset 32KB aligned to the start of the physical disk.
  335          * XXX: Actually there are no such restrictions, this is how
  336          * DragonFlyBSD behaves.
  337          */
  338         pbase += DALIGN_SIZE - pp->stripeoffset % DALIGN_SIZE;
  339 
  340         table = (struct g_part_bsd64_table *)basetable;
  341         table->d_align = blksize;
  342         table->d_bbase = ressize / pp->sectorsize;
  343         table->d_abase = ((pp->mediasize - ressize) &
  344             ~blkmask) / pp->sectorsize;
  345         kern_uuidgen(&table->d_stor_uuid, 1);
  346         basetable->gpt_first = pbase / pp->sectorsize;
  347         basetable->gpt_last = table->d_abase - 1; /* XXX */
  348         /*
  349          * Create 'c' partition and make it internal, so user will not be
  350          * able use it.
  351          */
  352         baseentry = g_part_new_entry(basetable, RAW_PART + 1, 0, 0);
  353         baseentry->gpe_internal = 1;
  354         return (0);
  355 }
  356 
  357 static int
  358 g_part_bsd64_destroy(struct g_part_table *basetable, struct g_part_parms *gpp)
  359 {
  360         struct g_provider *pp;
  361 
  362         pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
  363         if (pp->sectorsize > offsetof(struct disklabel64, d_magic))
  364                 basetable->gpt_smhead |= 1;
  365         else
  366                 basetable->gpt_smhead |= 3;
  367         return (0);
  368 }
  369 
  370 static void
  371 g_part_bsd64_dumpconf(struct g_part_table *basetable,
  372     struct g_part_entry *baseentry, struct sbuf *sb, const char *indent)
  373 {
  374         struct g_part_bsd64_table *table;
  375         struct g_part_bsd64_entry *entry;
  376         char buf[sizeof(table->d_packname)];
  377 
  378         entry = (struct g_part_bsd64_entry *)baseentry;
  379         if (indent == NULL) {
  380                 /* conftxt: libdisk compatibility */
  381                 sbuf_printf(sb, " xs BSD64 xt %u", entry->fstype);
  382         } else if (entry != NULL) {
  383                 /* confxml: partition entry information */
  384                 sbuf_printf(sb, "%s<rawtype>%u</rawtype>\n", indent,
  385                     entry->fstype);
  386                 if (!EQUUID(&bsd64_uuid_unused, &entry->type_uuid)) {
  387                         sbuf_printf(sb, "%s<type_uuid>", indent);
  388                         sbuf_printf_uuid(sb, &entry->type_uuid);
  389                         sbuf_cat(sb, "</type_uuid>\n");
  390                 }
  391                 sbuf_printf(sb, "%s<stor_uuid>", indent);
  392                 sbuf_printf_uuid(sb, &entry->stor_uuid);
  393                 sbuf_cat(sb, "</stor_uuid>\n");
  394         } else {
  395                 /* confxml: scheme information */
  396                 table = (struct g_part_bsd64_table *)basetable;
  397                 sbuf_printf(sb, "%s<bootbase>%ju</bootbase>\n", indent,
  398                     (uintmax_t)table->d_bbase);
  399                 if (table->d_abase)
  400                         sbuf_printf(sb, "%s<backupbase>%ju</backupbase>\n",
  401                             indent, (uintmax_t)table->d_abase);
  402                 sbuf_printf(sb, "%s<stor_uuid>", indent);
  403                 sbuf_printf_uuid(sb, &table->d_stor_uuid);
  404                 sbuf_cat(sb, "</stor_uuid>\n");
  405                 sbuf_printf(sb, "%s<label>", indent);
  406                 strncpy(buf, table->d_packname, sizeof(buf) - 1);
  407                 buf[sizeof(buf) - 1] = '\0';
  408                 g_conf_cat_escaped(sb, buf);
  409                 sbuf_cat(sb, "</label>\n");
  410         }
  411 }
  412 
  413 static int
  414 g_part_bsd64_dumpto(struct g_part_table *table, struct g_part_entry *baseentry)
  415 {
  416         struct g_part_bsd64_entry *entry;
  417 
  418         /* Allow dumping to a swap partition. */
  419         entry = (struct g_part_bsd64_entry *)baseentry;
  420         if (entry->fstype == FS_SWAP ||
  421             EQUUID(&entry->type_uuid, &bsd64_uuid_dfbsd_swap) ||
  422             EQUUID(&entry->type_uuid, &bsd64_uuid_freebsd_swap))
  423                 return (1);
  424         return (0);
  425 }
  426 
  427 static int
  428 g_part_bsd64_modify(struct g_part_table *basetable,
  429     struct g_part_entry *baseentry, struct g_part_parms *gpp)
  430 {
  431         struct g_part_bsd64_entry *entry;
  432 
  433         if (gpp->gpp_parms & G_PART_PARM_LABEL)
  434                 return (EINVAL);
  435 
  436         entry = (struct g_part_bsd64_entry *)baseentry;
  437         if (gpp->gpp_parms & G_PART_PARM_TYPE)
  438                 return (bsd64_parse_type(gpp->gpp_type, entry));
  439         return (0);
  440 }
  441 
  442 static int
  443 g_part_bsd64_resize(struct g_part_table *basetable,
  444     struct g_part_entry *baseentry, struct g_part_parms *gpp)
  445 {
  446         struct g_part_bsd64_table *table;
  447         struct g_provider *pp;
  448 
  449         if (baseentry == NULL) {
  450                 pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
  451                 table = (struct g_part_bsd64_table *)basetable;
  452                 table->d_abase =
  453                     rounddown2(pp->mediasize - table->d_bbase * pp->sectorsize,
  454                         table->d_align) / pp->sectorsize;
  455                 basetable->gpt_last = table->d_abase - 1;
  456                 return (0);
  457         }
  458         baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
  459         return (0);
  460 }
  461 
  462 static const char *
  463 g_part_bsd64_name(struct g_part_table *table, struct g_part_entry *baseentry,
  464     char *buf, size_t bufsz)
  465 {
  466 
  467         snprintf(buf, bufsz, "%c", 'a' + baseentry->gpe_index - 1);
  468         return (buf);
  469 }
  470 
  471 static int
  472 g_part_bsd64_probe(struct g_part_table *table, struct g_consumer *cp)
  473 {
  474         struct g_provider *pp;
  475         uint32_t v;
  476         int error;
  477         u_char *buf;
  478 
  479         pp = cp->provider;
  480         if (pp->mediasize < 2 * PALIGN_SIZE)
  481                 return (ENOSPC);
  482         v = rounddown2(pp->sectorsize + offsetof(struct disklabel64, d_magic),
  483                        pp->sectorsize);
  484         buf = g_read_data(cp, 0, v, &error);
  485         if (buf == NULL)
  486                 return (error);
  487         v = le32dec(buf + offsetof(struct disklabel64, d_magic));
  488         g_free(buf);
  489         return (v == DISKMAGIC64 ? G_PART_PROBE_PRI_HIGH: ENXIO);
  490 }
  491 
  492 static int
  493 g_part_bsd64_read(struct g_part_table *basetable, struct g_consumer *cp)
  494 {
  495         struct g_part_bsd64_table *table;
  496         struct g_part_bsd64_entry *entry;
  497         struct g_part_entry *baseentry;
  498         struct g_provider *pp;
  499         struct disklabel64 *dlp;
  500         uint64_t v64, sz;
  501         uint32_t v32;
  502         int error, index;
  503         u_char *buf;
  504 
  505         pp = cp->provider;
  506         table = (struct g_part_bsd64_table *)basetable;
  507         v32 = roundup2(sizeof(struct disklabel64), pp->sectorsize);
  508         buf = g_read_data(cp, 0, v32, &error);
  509         if (buf == NULL)
  510                 return (error);
  511 
  512         dlp = (struct disklabel64 *)buf;
  513         basetable->gpt_entries = le32toh(dlp->d_npartitions);
  514         if (basetable->gpt_entries > MAXPARTITIONS64 ||
  515             basetable->gpt_entries < 1)
  516                 goto invalid_label;
  517         v32 = le32toh(dlp->d_crc);
  518         dlp->d_crc = 0;
  519         if (crc32(&dlp->d_magic, offsetof(struct disklabel64,
  520             d_partitions[basetable->gpt_entries]) -
  521             offsetof(struct disklabel64, d_magic)) != v32)
  522                 goto invalid_label;
  523         table->d_align = le32toh(dlp->d_align);
  524         if (table->d_align == 0 || (table->d_align & (pp->sectorsize - 1)))
  525                 goto invalid_label;
  526         if (le64toh(dlp->d_total_size) > pp->mediasize)
  527                 goto invalid_label;
  528         v64 = le64toh(dlp->d_pbase);
  529         if (v64 % pp->sectorsize)
  530                 goto invalid_label;
  531         basetable->gpt_first = v64 / pp->sectorsize;
  532         v64 = le64toh(dlp->d_pstop);
  533         if (v64 % pp->sectorsize)
  534                 goto invalid_label;
  535         basetable->gpt_last = v64 / pp->sectorsize;
  536         basetable->gpt_isleaf = 1;
  537         v64 = le64toh(dlp->d_bbase);
  538         if (v64 % pp->sectorsize)
  539                 goto invalid_label;
  540         table->d_bbase = v64 / pp->sectorsize;
  541         v64 = le64toh(dlp->d_abase);
  542         if (v64 % pp->sectorsize)
  543                 goto invalid_label;
  544         table->d_abase = v64 / pp->sectorsize;
  545         le_uuid_dec(&dlp->d_stor_uuid, &table->d_stor_uuid);
  546         for (index = basetable->gpt_entries - 1; index >= 0; index--) {
  547                 if (index == RAW_PART) {
  548                         /* Skip 'c' partition. */
  549                         baseentry = g_part_new_entry(basetable,
  550                             index + 1, 0, 0);
  551                         baseentry->gpe_internal = 1;
  552                         continue;
  553                 }
  554                 v64 = le64toh(dlp->d_partitions[index].p_boffset);
  555                 sz = le64toh(dlp->d_partitions[index].p_bsize);
  556                 if (sz == 0 && v64 == 0)
  557                         continue;
  558                 if (sz == 0 || (v64 % pp->sectorsize) || (sz % pp->sectorsize))
  559                         goto invalid_label;
  560                 baseentry = g_part_new_entry(basetable, index + 1,
  561                     v64 / pp->sectorsize, (v64 + sz) / pp->sectorsize - 1);
  562                 entry = (struct g_part_bsd64_entry *)baseentry;
  563                 le_uuid_dec(&dlp->d_partitions[index].p_type_uuid,
  564                     &entry->type_uuid);
  565                 le_uuid_dec(&dlp->d_partitions[index].p_stor_uuid,
  566                     &entry->stor_uuid);
  567                 entry->fstype = dlp->d_partitions[index].p_fstype;
  568         }
  569         bcopy(dlp->d_reserved0, table->d_reserved0,
  570             sizeof(table->d_reserved0));
  571         bcopy(dlp->d_packname, table->d_packname, sizeof(table->d_packname));
  572         bcopy(dlp->d_reserved, table->d_reserved, sizeof(table->d_reserved));
  573         g_free(buf);
  574         return (0);
  575 
  576 invalid_label:
  577         g_free(buf);
  578         return (EINVAL);
  579 }
  580 
  581 static const char *
  582 g_part_bsd64_type(struct g_part_table *basetable, struct g_part_entry *baseentry,
  583     char *buf, size_t bufsz)
  584 {
  585         struct g_part_bsd64_entry *entry;
  586         struct bsd64_uuid_alias *uap;
  587 
  588         entry = (struct g_part_bsd64_entry *)baseentry;
  589         if (entry->fstype != FS_OTHER) {
  590                 for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++)
  591                         if (uap->fstype == entry->fstype)
  592                                 return (g_part_alias_name(uap->alias));
  593         } else {
  594                 for (uap = &fbsd_alias_match[0]; uap->uuid != NULL; uap++)
  595                         if (EQUUID(uap->uuid, &entry->type_uuid))
  596                                 return (g_part_alias_name(uap->alias));
  597                 for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++)
  598                         if (EQUUID(uap->uuid, &entry->type_uuid))
  599                                 return (g_part_alias_name(uap->alias));
  600         }
  601         if (EQUUID(&bsd64_uuid_unused, &entry->type_uuid))
  602                 snprintf(buf, bufsz, "!%d", entry->fstype);
  603         else {
  604                 buf[0] = '!';
  605                 snprintf_uuid(buf + 1, bufsz - 1, &entry->type_uuid);
  606         }
  607         return (buf);
  608 }
  609 
  610 static int
  611 g_part_bsd64_write(struct g_part_table *basetable, struct g_consumer *cp)
  612 {
  613         struct g_provider *pp;
  614         struct g_part_entry *baseentry;
  615         struct g_part_bsd64_entry *entry;
  616         struct g_part_bsd64_table *table;
  617         struct disklabel64 *dlp;
  618         uint32_t v, sz;
  619         int error, index;
  620 
  621         pp = cp->provider;
  622         table = (struct g_part_bsd64_table *)basetable;
  623         sz = roundup2(sizeof(struct disklabel64), pp->sectorsize);
  624         dlp = g_malloc(sz, M_WAITOK | M_ZERO);
  625 
  626         memcpy(dlp->d_reserved0, table->d_reserved0,
  627             sizeof(table->d_reserved0));
  628         memcpy(dlp->d_packname, table->d_packname, sizeof(table->d_packname));
  629         memcpy(dlp->d_reserved, table->d_reserved, sizeof(table->d_reserved));
  630         le32enc(&dlp->d_magic, DISKMAGIC64);
  631         le32enc(&dlp->d_align, table->d_align);
  632         le32enc(&dlp->d_npartitions, basetable->gpt_entries);
  633         le_uuid_enc(&dlp->d_stor_uuid, &table->d_stor_uuid);
  634         le64enc(&dlp->d_total_size, pp->mediasize);
  635         le64enc(&dlp->d_bbase, table->d_bbase * pp->sectorsize);
  636         le64enc(&dlp->d_pbase, basetable->gpt_first * pp->sectorsize);
  637         le64enc(&dlp->d_pstop, basetable->gpt_last * pp->sectorsize);
  638         le64enc(&dlp->d_abase, table->d_abase * pp->sectorsize);
  639 
  640         LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) {
  641                 if (baseentry->gpe_deleted)
  642                         continue;
  643                 index = baseentry->gpe_index - 1;
  644                 entry = (struct g_part_bsd64_entry *)baseentry;
  645                 if (index == RAW_PART)
  646                         continue;
  647                 le64enc(&dlp->d_partitions[index].p_boffset,
  648                     baseentry->gpe_start * pp->sectorsize);
  649                 le64enc(&dlp->d_partitions[index].p_bsize, pp->sectorsize *
  650                     (baseentry->gpe_end - baseentry->gpe_start + 1));
  651                 dlp->d_partitions[index].p_fstype = entry->fstype;
  652                 le_uuid_enc(&dlp->d_partitions[index].p_type_uuid,
  653                     &entry->type_uuid);
  654                 le_uuid_enc(&dlp->d_partitions[index].p_stor_uuid,
  655                     &entry->stor_uuid);
  656         }
  657         /* Calculate checksum. */
  658         v = offsetof(struct disklabel64,
  659             d_partitions[basetable->gpt_entries]) -
  660             offsetof(struct disklabel64, d_magic);
  661         le32enc(&dlp->d_crc, crc32(&dlp->d_magic, v));
  662         error = g_write_data(cp, 0, dlp, sz);
  663         g_free(dlp);
  664         return (error);
  665 }

Cache object: 36b4e3db575a0af3014ad23e7f5a61c6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.