summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorivoras <ivoras@FreeBSD.org>2009-06-13 00:27:03 +0000
committerivoras <ivoras@FreeBSD.org>2009-06-13 00:27:03 +0000
commit79583448b47e888f628b66355bcedd14ac22ef39 (patch)
treec825b3f07dbd769fc6ebee9c09faa796ccc3c8fc
parentb0bb75a321693ed722df0349f7fe300eb51db5e8 (diff)
downloadFreeBSD-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 >
-rw-r--r--sbin/geom/class/label/glabel.816
-rw-r--r--sys/conf/files1
-rw-r--r--sys/geom/label/g_label.c2
-rw-r--r--sys/geom/label/g_label.h2
-rw-r--r--sys/geom/label/g_label_gpt.c164
5 files changed, 183 insertions, 2 deletions
diff --git a/sbin/geom/class/label/glabel.8 b/sbin/geom/class/label/glabel.8
index bc1994e..454cba0 100644
--- a/sbin/geom/class/label/glabel.8
+++ b/sbin/geom/class/label/glabel.8
@@ -1,4 +1,5 @@
.\" Copyright (c) 2004-2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+.\" Copyright (c) 2008-2009 Ivan Voras <ivoras@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -24,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 2, 2004
+.Dd June 13, 2009
.Dt GLABEL 8
.Os
.Sh NAME
@@ -119,7 +120,18 @@ NTFS (directory
.Pa /dev/ntfs/ ) .
.El
.Pp
-Non file-system labels are created in the directory
+Support for partition metadata is implemented for:
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+GPT labels (directory
+.Pa /dev/gpt/ ) .
+.It
+GPT UUIDs (directory
+.Pa /dev/gptid/ ) .
+.El
+.Pp
+Generic labels are created in the directory
.Pa /dev/label/ .
.Pp
The first argument to
diff --git a/sys/conf/files b/sys/conf/files
index 247eb07..fc7b52d 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1852,6 +1852,7 @@ geom/label/g_label_msdosfs.c optional geom_label
geom/label/g_label_ntfs.c optional geom_label
geom/label/g_label_reiserfs.c optional geom_label
geom/label/g_label_ufs.c optional geom_label
+geom/label/g_label_gpt.c optional geom_label
geom/linux_lvm/g_linux_lvm.c optional geom_linux_lvm
geom/mirror/g_mirror.c optional geom_mirror
geom/mirror/g_mirror_ctl.c optional geom_mirror
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
+};
OpenPOWER on IntegriCloud