summaryrefslogtreecommitdiffstats
path: root/sys/geom/label
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 /sys/geom/label
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 >
Diffstat (limited to 'sys/geom/label')
-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
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
+};
OpenPOWER on IntegriCloud