diff options
author | ivoras <ivoras@FreeBSD.org> | 2009-06-13 00:27:03 +0000 |
---|---|---|
committer | ivoras <ivoras@FreeBSD.org> | 2009-06-13 00:27:03 +0000 |
commit | 79583448b47e888f628b66355bcedd14ac22ef39 (patch) | |
tree | c825b3f07dbd769fc6ebee9c09faa796ccc3c8fc /sys/geom/label | |
parent | b0bb75a321693ed722df0349f7fe300eb51db5e8 (diff) | |
download | FreeBSD-src-79583448b47e888f628b66355bcedd14ac22ef39.zip FreeBSD-src-79583448b47e888f628b66355bcedd14ac22ef39.tar.gz |
Add support for labels derived from GPT metadata.
Approved by: gnn (mentor)
Reviewed by: pjd
PR: 128398
Submitted by: Marius Nuennerich < marius at nuenneri.ch >
Diffstat (limited to 'sys/geom/label')
-rw-r--r-- | sys/geom/label/g_label.c | 2 | ||||
-rw-r--r-- | sys/geom/label/g_label.h | 2 | ||||
-rw-r--r-- | sys/geom/label/g_label_gpt.c | 164 |
3 files changed, 168 insertions, 0 deletions
diff --git a/sys/geom/label/g_label.c b/sys/geom/label/g_label.c index fe2798a..0a22dcf 100644 --- a/sys/geom/label/g_label.c +++ b/sys/geom/label/g_label.c @@ -84,6 +84,8 @@ const struct g_label_desc *g_labels[] = { &g_label_ext2fs, &g_label_reiserfs, &g_label_ntfs, + &g_label_gpt, + &g_label_gpt_uuid, NULL }; diff --git a/sys/geom/label/g_label.h b/sys/geom/label/g_label.h index e3541a9..6e5d8f0 100644 --- a/sys/geom/label/g_label.h +++ b/sys/geom/label/g_label.h @@ -71,6 +71,8 @@ extern const struct g_label_desc g_label_msdosfs; extern const struct g_label_desc g_label_ext2fs; extern const struct g_label_desc g_label_reiserfs; extern const struct g_label_desc g_label_ntfs; +extern const struct g_label_desc g_label_gpt; +extern const struct g_label_desc g_label_gpt_uuid; #endif /* _KERNEL */ struct g_label_metadata { diff --git a/sys/geom/label/g_label_gpt.c b/sys/geom/label/g_label_gpt.c new file mode 100644 index 0000000..298a0ad --- /dev/null +++ b/sys/geom/label/g_label_gpt.c @@ -0,0 +1,164 @@ +/*- + * Copyright (c) 2008 Marius Nuennerich + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/systm.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/kobj.h> +#include <sys/gpt.h> + +#include <geom/geom.h> +#include <geom/label/g_label.h> +#include <geom/part/g_part.h> + +#define PART_CLASS_NAME "PART" +#define SCHEME_NAME "GPT" + +#define G_LABEL_GPT_VOLUME_DIR "gpt" +#define G_LABEL_GPT_ID_DIR "gptid" + +/* also defined in geom/part/g_part_gpt.c */ +struct g_part_gpt_entry { + struct g_part_entry base; + struct gpt_ent ent; +}; + +/* shamelessly stolen from g_part_gpt.c */ +static void +sbuf_nprintf_utf16(struct sbuf *sb, uint16_t *str, size_t len) +{ + u_int bo; + uint32_t ch; + uint16_t c; + + bo = LITTLE_ENDIAN; /* GPT is little-endian */ + while (len > 0 && *str != 0) { + ch = (bo == BIG_ENDIAN) ? be16toh(*str) : le16toh(*str); + str++, len--; + if ((ch & 0xf800) == 0xd800) { + if (len > 0) { + c = (bo == BIG_ENDIAN) ? be16toh(*str) + : le16toh(*str); + str++, len--; + } else + c = 0xfffd; + if ((ch & 0x400) == 0 && (c & 0xfc00) == 0xdc00) { + ch = ((ch & 0x3ff) << 10) + (c & 0x3ff); + ch += 0x10000; + } else + ch = 0xfffd; + } else if (ch == 0xfffe) { /* BOM (U+FEFF) swapped. */ + bo = (bo == BIG_ENDIAN) ? LITTLE_ENDIAN : BIG_ENDIAN; + continue; + } else if (ch == 0xfeff) /* BOM (U+FEFF) unswapped. */ + continue; + + /* Write the Unicode character in UTF-8 */ + if (ch < 0x80) + sbuf_printf(sb, "%c", ch); + else if (ch < 0x800) + sbuf_printf(sb, "%c%c", 0xc0 | (ch >> 6), + 0x80 | (ch & 0x3f)); + else if (ch < 0x10000) + sbuf_printf(sb, "%c%c%c", 0xe0 | (ch >> 12), + 0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f)); + else if (ch < 0x200000) + sbuf_printf(sb, "%c%c%c%c", 0xf0 | (ch >> 18), + 0x80 | ((ch >> 12) & 0x3f), + 0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f)); + } +} + +static void +g_label_gpt_taste(struct g_consumer *cp, char *label, size_t size) +{ + struct g_provider *pp; + struct g_part_table *tp; + struct g_part_gpt_entry *part_gpt_entry; + struct sbuf *lbl; + + g_topology_assert_not(); + pp = cp->provider; + tp = (struct g_part_table *)pp->geom->softc; + label[0] = '\0'; + + /* We taste only partitions from GPART */ + if (strncmp(pp->geom->class->name, PART_CLASS_NAME, sizeof(PART_CLASS_NAME))) + return; + /* and only GPT */ + if (strncmp(tp->gpt_scheme->name, SCHEME_NAME, sizeof(SCHEME_NAME))) + return; + + part_gpt_entry = (struct g_part_gpt_entry *)pp->private; + + /* + * create sbuf with biggest possible size + * we need max. 4 bytes for every 2-byte utf16 char + */ + lbl = sbuf_new(NULL, NULL, sizeof(part_gpt_entry->ent.ent_name) << 1, SBUF_FIXEDLEN); + /* size ist the number of characters, not bytes */ + sbuf_nprintf_utf16(lbl, part_gpt_entry->ent.ent_name, sizeof(part_gpt_entry->ent.ent_name) >> 1); + sbuf_finish(lbl); + strlcpy(label, sbuf_data(lbl), size); + sbuf_delete(lbl); +} + +static void +g_label_gpt_uuid_taste(struct g_consumer *cp, char *label, size_t size) +{ + struct g_provider *pp; + struct g_part_table *tp; + struct g_part_gpt_entry *part_gpt_entry; + + g_topology_assert_not(); + pp = cp->provider; + tp = (struct g_part_table *)pp->geom->softc; + label[0] = '\0'; + + /* we taste only partitions from GPART */ + if (strncmp(pp->geom->class->name, PART_CLASS_NAME, sizeof(PART_CLASS_NAME))) + return; + /* and only GPT */ + if (strncmp(tp->gpt_scheme->name, SCHEME_NAME, sizeof(SCHEME_NAME))) + return; + + part_gpt_entry = (struct g_part_gpt_entry *)pp->private; + snprintf_uuid(label, size, &part_gpt_entry->ent.ent_uuid); +} + +const struct g_label_desc g_label_gpt = { + .ld_taste = g_label_gpt_taste, + .ld_dir = G_LABEL_GPT_VOLUME_DIR +}; + +const struct g_label_desc g_label_gpt_uuid = { + .ld_taste = g_label_gpt_uuid_taste, + .ld_dir = G_LABEL_GPT_ID_DIR +}; |