2 * Copyright (c) 2014 Andrey V. Elsukov <ae@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
32 #include <sys/disklabel.h>
33 #include <sys/endian.h>
35 #include <sys/kernel.h>
37 #include <sys/limits.h>
39 #include <sys/malloc.h>
40 #include <sys/mutex.h>
41 #include <sys/queue.h>
43 #include <sys/systm.h>
44 #include <sys/sysctl.h>
45 #include <geom/geom.h>
46 #include <geom/geom_int.h>
47 #include <geom/part/g_part.h>
49 #include "g_part_if.h"
51 FEATURE(geom_part_bsd64, "GEOM partitioning class for 64-bit BSD disklabels");
53 /* XXX: move this to sys/disklabel64.h */
54 #define DISKMAGIC64 ((uint32_t)0xc4464c59)
55 #define MAXPARTITIONS64 16
56 #define RESPARTITIONS64 32
59 char d_reserved0[512]; /* reserved or unused */
60 u_int32_t d_magic; /* the magic number */
61 u_int32_t d_crc; /* crc32() d_magic thru last part */
62 u_int32_t d_align; /* partition alignment requirement */
63 u_int32_t d_npartitions; /* number of partitions */
64 struct uuid d_stor_uuid; /* unique uuid for label */
66 u_int64_t d_total_size; /* total size incl everything (bytes) */
67 u_int64_t d_bbase; /* boot area base offset (bytes) */
68 /* boot area is pbase - bbase */
69 u_int64_t d_pbase; /* first allocatable offset (bytes) */
70 u_int64_t d_pstop; /* last allocatable offset+1 (bytes) */
71 u_int64_t d_abase; /* location of backup copy if not 0 */
73 u_char d_packname[64];
74 u_char d_reserved[64];
77 * Note: offsets are relative to the base of the slice, NOT to
78 * d_pbase. Unlike 32 bit disklabels the on-disk format for
79 * a 64 bit disklabel remains slice-relative.
81 * An uninitialized partition has a p_boffset and p_bsize of 0.
83 * If p_fstype is not supported for a live partition it is set
84 * to FS_OTHER. This is typically the case when the filesystem
85 * is identified by its uuid.
87 struct partition64 { /* the partition table */
88 u_int64_t p_boffset; /* slice relative offset, in bytes */
89 u_int64_t p_bsize; /* size of partition, in bytes */
91 u_int8_t p_unused01; /* reserved, must be 0 */
92 u_int8_t p_unused02; /* reserved, must be 0 */
93 u_int8_t p_unused03; /* reserved, must be 0 */
94 u_int32_t p_unused04; /* reserved, must be 0 */
95 u_int32_t p_unused05; /* reserved, must be 0 */
96 u_int32_t p_unused06; /* reserved, must be 0 */
97 struct uuid p_type_uuid;/* mount type as UUID */
98 struct uuid p_stor_uuid;/* unique uuid for storage */
99 } d_partitions[MAXPARTITIONS64];/* actually may be more */
102 struct g_part_bsd64_table {
103 struct g_part_table base;
108 struct uuid d_stor_uuid;
109 char d_reserved0[512];
110 u_char d_packname[64];
111 u_char d_reserved[64];
114 struct g_part_bsd64_entry {
115 struct g_part_entry base;
118 struct uuid type_uuid;
119 struct uuid stor_uuid;
122 static int g_part_bsd64_add(struct g_part_table *, struct g_part_entry *,
123 struct g_part_parms *);
124 static int g_part_bsd64_bootcode(struct g_part_table *, struct g_part_parms *);
125 static int g_part_bsd64_create(struct g_part_table *, struct g_part_parms *);
126 static int g_part_bsd64_destroy(struct g_part_table *, struct g_part_parms *);
127 static void g_part_bsd64_dumpconf(struct g_part_table *, struct g_part_entry *,
128 struct sbuf *, const char *);
129 static int g_part_bsd64_dumpto(struct g_part_table *, struct g_part_entry *);
130 static int g_part_bsd64_modify(struct g_part_table *, struct g_part_entry *,
131 struct g_part_parms *);
132 static const char *g_part_bsd64_name(struct g_part_table *, struct g_part_entry *,
134 static int g_part_bsd64_probe(struct g_part_table *, struct g_consumer *);
135 static int g_part_bsd64_read(struct g_part_table *, struct g_consumer *);
136 static const char *g_part_bsd64_type(struct g_part_table *, struct g_part_entry *,
138 static int g_part_bsd64_write(struct g_part_table *, struct g_consumer *);
139 static int g_part_bsd64_resize(struct g_part_table *, struct g_part_entry *,
140 struct g_part_parms *);
142 static kobj_method_t g_part_bsd64_methods[] = {
143 KOBJMETHOD(g_part_add, g_part_bsd64_add),
144 KOBJMETHOD(g_part_bootcode, g_part_bsd64_bootcode),
145 KOBJMETHOD(g_part_create, g_part_bsd64_create),
146 KOBJMETHOD(g_part_destroy, g_part_bsd64_destroy),
147 KOBJMETHOD(g_part_dumpconf, g_part_bsd64_dumpconf),
148 KOBJMETHOD(g_part_dumpto, g_part_bsd64_dumpto),
149 KOBJMETHOD(g_part_modify, g_part_bsd64_modify),
150 KOBJMETHOD(g_part_resize, g_part_bsd64_resize),
151 KOBJMETHOD(g_part_name, g_part_bsd64_name),
152 KOBJMETHOD(g_part_probe, g_part_bsd64_probe),
153 KOBJMETHOD(g_part_read, g_part_bsd64_read),
154 KOBJMETHOD(g_part_type, g_part_bsd64_type),
155 KOBJMETHOD(g_part_write, g_part_bsd64_write),
159 static struct g_part_scheme g_part_bsd64_scheme = {
161 g_part_bsd64_methods,
162 sizeof(struct g_part_bsd64_table),
163 .gps_entrysz = sizeof(struct g_part_bsd64_entry),
164 .gps_minent = MAXPARTITIONS64,
165 .gps_maxent = MAXPARTITIONS64
167 G_PART_SCHEME_DECLARE(g_part_bsd64);
169 #define EQUUID(a, b) (memcmp(a, b, sizeof(struct uuid)) == 0)
170 static struct uuid bsd64_uuid_unused = GPT_ENT_TYPE_UNUSED;
171 static struct uuid bsd64_uuid_dfbsd_swap = GPT_ENT_TYPE_DRAGONFLY_SWAP;
172 static struct uuid bsd64_uuid_dfbsd_ufs1 = GPT_ENT_TYPE_DRAGONFLY_UFS1;
173 static struct uuid bsd64_uuid_dfbsd_vinum = GPT_ENT_TYPE_DRAGONFLY_VINUM;
174 static struct uuid bsd64_uuid_dfbsd_ccd = GPT_ENT_TYPE_DRAGONFLY_CCD;
175 static struct uuid bsd64_uuid_dfbsd_legacy = GPT_ENT_TYPE_DRAGONFLY_LEGACY;
176 static struct uuid bsd64_uuid_dfbsd_hammer = GPT_ENT_TYPE_DRAGONFLY_HAMMER;
177 static struct uuid bsd64_uuid_dfbsd_hammer2 = GPT_ENT_TYPE_DRAGONFLY_HAMMER2;
178 static struct uuid bsd64_uuid_freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT;
179 static struct uuid bsd64_uuid_freebsd_nandfs = GPT_ENT_TYPE_FREEBSD_NANDFS;
180 static struct uuid bsd64_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP;
181 static struct uuid bsd64_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS;
182 static struct uuid bsd64_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM;
183 static struct uuid bsd64_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS;
185 struct bsd64_uuid_alias {
190 static struct bsd64_uuid_alias dfbsd_alias_match[] = {
191 { &bsd64_uuid_dfbsd_swap, FS_SWAP, G_PART_ALIAS_DFBSD_SWAP },
192 { &bsd64_uuid_dfbsd_ufs1, FS_BSDFFS, G_PART_ALIAS_DFBSD_UFS },
193 { &bsd64_uuid_dfbsd_vinum, FS_VINUM, G_PART_ALIAS_DFBSD_VINUM },
194 { &bsd64_uuid_dfbsd_ccd, FS_CCD, G_PART_ALIAS_DFBSD_CCD },
195 { &bsd64_uuid_dfbsd_legacy, FS_OTHER, G_PART_ALIAS_DFBSD_LEGACY },
196 { &bsd64_uuid_dfbsd_hammer, FS_HAMMER, G_PART_ALIAS_DFBSD_HAMMER },
197 { &bsd64_uuid_dfbsd_hammer2, FS_HAMMER2, G_PART_ALIAS_DFBSD_HAMMER2 },
200 static struct bsd64_uuid_alias fbsd_alias_match[] = {
201 { &bsd64_uuid_freebsd_boot, FS_OTHER, G_PART_ALIAS_FREEBSD_BOOT },
202 { &bsd64_uuid_freebsd_swap, FS_OTHER, G_PART_ALIAS_FREEBSD_SWAP },
203 { &bsd64_uuid_freebsd_ufs, FS_OTHER, G_PART_ALIAS_FREEBSD_UFS },
204 { &bsd64_uuid_freebsd_zfs, FS_OTHER, G_PART_ALIAS_FREEBSD_ZFS },
205 { &bsd64_uuid_freebsd_vinum, FS_OTHER, G_PART_ALIAS_FREEBSD_VINUM },
206 { &bsd64_uuid_freebsd_nandfs, FS_OTHER, G_PART_ALIAS_FREEBSD_NANDFS },
211 bsd64_parse_type(const char *type, struct g_part_bsd64_entry *entry)
214 const struct bsd64_uuid_alias *uap;
220 if (type[0] == '!') {
223 lt = strtol(type + 1, &p, 0);
224 /* The type specified as number */
226 if (lt <= 0 || lt > 255)
229 entry->type_uuid = bsd64_uuid_unused;
232 /* The type specified as uuid */
233 error = parse_uuid(type + 1, &tmp);
236 if (EQUUID(&tmp, &bsd64_uuid_unused))
238 for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) {
239 if (EQUUID(&tmp, uap->uuid)) {
240 /* Prefer fstype for known uuids */
241 entry->type_uuid = bsd64_uuid_unused;
242 entry->fstype = uap->fstype;
246 entry->type_uuid = tmp;
247 entry->fstype = FS_OTHER;
250 /* The type specified as symbolic alias name */
251 for (uap = &fbsd_alias_match[0]; uap->uuid != NULL; uap++) {
252 alias = g_part_alias_name(uap->alias);
253 if (!strcasecmp(type, alias)) {
254 entry->type_uuid = *uap->uuid;
255 entry->fstype = uap->fstype;
259 for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) {
260 alias = g_part_alias_name(uap->alias);
261 if (!strcasecmp(type, alias)) {
262 entry->type_uuid = bsd64_uuid_unused;
263 entry->fstype = uap->fstype;
271 g_part_bsd64_add(struct g_part_table *basetable, struct g_part_entry *baseentry,
272 struct g_part_parms *gpp)
274 struct g_part_bsd64_entry *entry;
276 if (gpp->gpp_parms & G_PART_PARM_LABEL)
279 entry = (struct g_part_bsd64_entry *)baseentry;
280 if (bsd64_parse_type(gpp->gpp_type, entry) != 0)
282 kern_uuidgen(&entry->stor_uuid, 1);
287 g_part_bsd64_bootcode(struct g_part_table *basetable, struct g_part_parms *gpp)
293 #define PALIGN_SIZE (1024 * 1024)
294 #define PALIGN_MASK (PALIGN_SIZE - 1)
295 #define BLKSIZE (4 * 1024)
296 #define BOOTSIZE (32 * 1024)
297 #define DALIGN_SIZE (32 * 1024)
299 g_part_bsd64_create(struct g_part_table *basetable, struct g_part_parms *gpp)
301 struct g_part_bsd64_table *table;
302 struct g_part_entry *baseentry;
303 struct g_provider *pp;
304 uint64_t blkmask, pbase;
305 uint32_t blksize, ressize;
307 pp = gpp->gpp_provider;
308 if (pp->mediasize < 2* PALIGN_SIZE)
312 * Use at least 4KB block size. Blksize is stored in the d_align.
313 * XXX: Actually it is used just for calculate d_bbase and used
314 * for better alignment in bsdlabel64(8).
316 blksize = pp->sectorsize < BLKSIZE ? BLKSIZE: pp->sectorsize;
317 blkmask = blksize - 1;
318 /* Reserve enough space for RESPARTITIONS64 partitions. */
319 ressize = offsetof(struct disklabel64, d_partitions[RESPARTITIONS64]);
320 ressize = (ressize + blkmask) & ~blkmask;
322 * Reserve enough space for bootcode and align first allocatable
323 * offset to PALIGN_SIZE.
324 * XXX: Currently DragonFlyBSD has 32KB bootcode, but the size could
325 * be bigger, because it is possible change it (it is equal pbase-bbase)
326 * in the bsdlabel64(8).
328 pbase = ressize + ((BOOTSIZE + blkmask) & ~blkmask);
329 pbase = (pbase + PALIGN_MASK) & ~PALIGN_MASK;
331 * Take physical offset into account and make first allocatable
332 * offset 32KB aligned to the start of the physical disk.
333 * XXX: Actually there are no such restrictions, this is how
334 * DragonFlyBSD behaves.
336 pbase += DALIGN_SIZE - pp->stripeoffset % DALIGN_SIZE;
338 table = (struct g_part_bsd64_table *)basetable;
339 table->d_align = blksize;
340 table->d_bbase = ressize / pp->sectorsize;
341 table->d_abase = ((pp->mediasize - ressize) &
342 ~blkmask) / pp->sectorsize;
343 kern_uuidgen(&table->d_stor_uuid, 1);
344 basetable->gpt_first = pbase / pp->sectorsize;
345 basetable->gpt_last = table->d_abase - 1; /* XXX */
347 * Create 'c' partition and make it internal, so user will not be
350 baseentry = g_part_new_entry(basetable, RAW_PART + 1, 0, 0);
351 baseentry->gpe_internal = 1;
356 g_part_bsd64_destroy(struct g_part_table *basetable, struct g_part_parms *gpp)
358 struct g_provider *pp;
360 pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
361 if (pp->sectorsize > offsetof(struct disklabel64, d_magic))
362 basetable->gpt_smhead |= 1;
364 basetable->gpt_smhead |= 3;
369 g_part_bsd64_dumpconf(struct g_part_table *basetable,
370 struct g_part_entry *baseentry, struct sbuf *sb, const char *indent)
372 struct g_part_bsd64_table *table;
373 struct g_part_bsd64_entry *entry;
374 char buf[sizeof(table->d_packname)];
376 entry = (struct g_part_bsd64_entry *)baseentry;
377 if (indent == NULL) {
378 /* conftxt: libdisk compatibility */
379 sbuf_printf(sb, " xs BSD64 xt %u", entry->fstype);
380 } else if (entry != NULL) {
381 /* confxml: partition entry information */
382 sbuf_printf(sb, "%s<rawtype>%u</rawtype>\n", indent,
384 if (!EQUUID(&bsd64_uuid_unused, &entry->type_uuid)) {
385 sbuf_printf(sb, "%s<type_uuid>", indent);
386 sbuf_printf_uuid(sb, &entry->type_uuid);
387 sbuf_printf(sb, "</type_uuid>\n");
389 sbuf_printf(sb, "%s<stor_uuid>", indent);
390 sbuf_printf_uuid(sb, &entry->stor_uuid);
391 sbuf_printf(sb, "</stor_uuid>\n");
393 /* confxml: scheme information */
394 table = (struct g_part_bsd64_table *)basetable;
395 sbuf_printf(sb, "%s<bootbase>%ju</bootbase>\n", indent,
396 (uintmax_t)table->d_bbase);
398 sbuf_printf(sb, "%s<backupbase>%ju</backupbase>\n",
399 indent, (uintmax_t)table->d_abase);
400 sbuf_printf(sb, "%s<stor_uuid>", indent);
401 sbuf_printf_uuid(sb, &table->d_stor_uuid);
402 sbuf_printf(sb, "</stor_uuid>\n");
403 sbuf_printf(sb, "%s<label>", indent);
404 strncpy(buf, table->d_packname, sizeof(buf) - 1);
405 buf[sizeof(buf) - 1] = '\0';
406 g_conf_printf_escaped(sb, "%s", buf);
407 sbuf_printf(sb, "</label>\n");
412 g_part_bsd64_dumpto(struct g_part_table *table, struct g_part_entry *baseentry)
414 struct g_part_bsd64_entry *entry;
416 /* Allow dumping to a swap partition. */
417 entry = (struct g_part_bsd64_entry *)baseentry;
418 if (entry->fstype == FS_SWAP ||
419 EQUUID(&entry->type_uuid, &bsd64_uuid_dfbsd_swap) ||
420 EQUUID(&entry->type_uuid, &bsd64_uuid_freebsd_swap))
426 g_part_bsd64_modify(struct g_part_table *basetable,
427 struct g_part_entry *baseentry, struct g_part_parms *gpp)
429 struct g_part_bsd64_entry *entry;
431 if (gpp->gpp_parms & G_PART_PARM_LABEL)
434 entry = (struct g_part_bsd64_entry *)baseentry;
435 if (gpp->gpp_parms & G_PART_PARM_TYPE)
436 return (bsd64_parse_type(gpp->gpp_type, entry));
441 g_part_bsd64_resize(struct g_part_table *basetable,
442 struct g_part_entry *baseentry, struct g_part_parms *gpp)
444 struct g_part_bsd64_table *table;
445 struct g_provider *pp;
447 if (baseentry == NULL) {
448 pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
449 table = (struct g_part_bsd64_table *)basetable;
450 table->d_abase = ((pp->mediasize -
451 table->d_bbase * pp->sectorsize) & ~(table->d_align - 1)) /
453 basetable->gpt_last = table->d_abase - 1;
456 baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
461 g_part_bsd64_name(struct g_part_table *table, struct g_part_entry *baseentry,
462 char *buf, size_t bufsz)
465 snprintf(buf, bufsz, "%c", 'a' + baseentry->gpe_index - 1);
470 g_part_bsd64_probe(struct g_part_table *table, struct g_consumer *cp)
472 struct g_provider *pp;
478 if (pp->mediasize < 2 * PALIGN_SIZE)
480 v = (pp->sectorsize +
481 offsetof(struct disklabel64, d_magic)) & ~(pp->sectorsize - 1);
482 buf = g_read_data(cp, 0, v, &error);
485 v = le32dec(buf + offsetof(struct disklabel64, d_magic));
487 return (v == DISKMAGIC64 ? G_PART_PROBE_PRI_HIGH: ENXIO);
491 g_part_bsd64_read(struct g_part_table *basetable, struct g_consumer *cp)
493 struct g_part_bsd64_table *table;
494 struct g_part_bsd64_entry *entry;
495 struct g_part_entry *baseentry;
496 struct g_provider *pp;
497 struct disklabel64 *dlp;
504 table = (struct g_part_bsd64_table *)basetable;
505 v32 = (pp->sectorsize +
506 sizeof(struct disklabel64) - 1) & ~(pp->sectorsize - 1);
507 buf = g_read_data(cp, 0, v32, &error);
511 dlp = (struct disklabel64 *)buf;
512 basetable->gpt_entries = le32toh(dlp->d_npartitions);
513 if (basetable->gpt_entries > MAXPARTITIONS64)
515 v32 = le32toh(dlp->d_crc);
517 if (crc32(&dlp->d_magic, offsetof(struct disklabel64,
518 d_partitions[basetable->gpt_entries]) -
519 offsetof(struct disklabel64, d_magic)) != v32)
521 table->d_align = le32toh(dlp->d_align);
522 if (table->d_align == 0 || (table->d_align & (pp->sectorsize - 1)))
524 if (le64toh(dlp->d_total_size) > pp->mediasize)
526 v64 = le64toh(dlp->d_pbase);
527 if (v64 % pp->sectorsize)
529 basetable->gpt_first = v64 / pp->sectorsize;
530 v64 = le64toh(dlp->d_pstop);
531 if (v64 % pp->sectorsize)
533 basetable->gpt_last = v64 / pp->sectorsize;
534 basetable->gpt_isleaf = 1;
535 v64 = le64toh(dlp->d_bbase);
536 if (v64 % pp->sectorsize)
538 table->d_bbase = v64 / pp->sectorsize;
539 v64 = le64toh(dlp->d_abase);
540 if (v64 % pp->sectorsize)
542 table->d_abase = v64 / pp->sectorsize;
543 le_uuid_dec(&dlp->d_stor_uuid, &table->d_stor_uuid);
544 for (index = basetable->gpt_entries - 1; index >= 0; index--) {
545 if (index == RAW_PART) {
546 /* Skip 'c' partition. */
547 baseentry = g_part_new_entry(basetable,
549 baseentry->gpe_internal = 1;
552 v64 = le64toh(dlp->d_partitions[index].p_boffset);
553 sz = le64toh(dlp->d_partitions[index].p_bsize);
554 if (sz == 0 && v64 == 0)
556 if (sz == 0 || (v64 % pp->sectorsize) || (sz % pp->sectorsize))
558 baseentry = g_part_new_entry(basetable, index + 1,
559 v64 / pp->sectorsize, (v64 + sz) / pp->sectorsize - 1);
560 entry = (struct g_part_bsd64_entry *)baseentry;
561 le_uuid_dec(&dlp->d_partitions[index].p_type_uuid,
563 le_uuid_dec(&dlp->d_partitions[index].p_stor_uuid,
565 entry->fstype = dlp->d_partitions[index].p_fstype;
566 if (index == RAW_PART)
567 baseentry->gpe_internal = 1;
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));
582 g_part_bsd64_type(struct g_part_table *basetable, struct g_part_entry *baseentry,
583 char *buf, size_t bufsz)
585 struct g_part_bsd64_entry *entry;
586 struct bsd64_uuid_alias *uap;
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));
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));
601 if (EQUUID(&bsd64_uuid_unused, &entry->type_uuid))
602 snprintf(buf, bufsz, "!%d", entry->fstype);
605 snprintf_uuid(buf + 1, bufsz - 1, &entry->type_uuid);
611 g_part_bsd64_write(struct g_part_table *basetable, struct g_consumer *cp)
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;
622 table = (struct g_part_bsd64_table *)basetable;
623 sz = (pp->sectorsize +
624 sizeof(struct disklabel64) - 1) & ~(pp->sectorsize - 1);
625 dlp = g_malloc(sz, M_WAITOK | M_ZERO);
627 memcpy(dlp->d_reserved0, table->d_reserved0,
628 sizeof(table->d_reserved0));
629 memcpy(dlp->d_packname, table->d_packname, sizeof(table->d_packname));
630 memcpy(dlp->d_reserved, table->d_reserved, sizeof(table->d_reserved));
631 le32enc(&dlp->d_magic, DISKMAGIC64);
632 le32enc(&dlp->d_align, table->d_align);
633 le32enc(&dlp->d_npartitions, basetable->gpt_entries);
634 le_uuid_enc(&dlp->d_stor_uuid, &table->d_stor_uuid);
635 le64enc(&dlp->d_total_size, pp->mediasize);
636 le64enc(&dlp->d_bbase, table->d_bbase * pp->sectorsize);
637 le64enc(&dlp->d_pbase, basetable->gpt_first * pp->sectorsize);
638 le64enc(&dlp->d_pstop, basetable->gpt_last * pp->sectorsize);
639 le64enc(&dlp->d_abase, table->d_abase * pp->sectorsize);
641 LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) {
642 if (baseentry->gpe_deleted)
644 index = baseentry->gpe_index - 1;
645 entry = (struct g_part_bsd64_entry *)baseentry;
646 if (index == RAW_PART)
648 le64enc(&dlp->d_partitions[index].p_boffset,
649 baseentry->gpe_start * pp->sectorsize);
650 le64enc(&dlp->d_partitions[index].p_bsize, pp->sectorsize *
651 (baseentry->gpe_end - baseentry->gpe_start + 1));
652 dlp->d_partitions[index].p_fstype = entry->fstype;
653 le_uuid_enc(&dlp->d_partitions[index].p_type_uuid,
655 le_uuid_enc(&dlp->d_partitions[index].p_stor_uuid,
658 /* Calculate checksum. */
659 v = offsetof(struct disklabel64,
660 d_partitions[basetable->gpt_entries]) -
661 offsetof(struct disklabel64, d_magic);
662 le32enc(&dlp->d_crc, crc32(&dlp->d_magic, v));
663 error = g_write_data(cp, 0, dlp, sz);