summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2010-09-24 19:33:47 +0000
committerpjd <pjd@FreeBSD.org>2010-09-24 19:33:47 +0000
commit39f36627d95bb74f59e469420305bfd0d61c8626 (patch)
treefc0da05c74ac2dcfd9a139397d12b60f577795f2 /sys/geom
parent4f5572a9beffcf6acbefa1dc77fa8e4fc64a4c52 (diff)
downloadFreeBSD-src-39f36627d95bb74f59e469420305bfd0d61c8626.zip
FreeBSD-src-39f36627d95bb74f59e469420305bfd0d61c8626.tar.gz
Allow to configure GPT attributes. It shouldn't be allowed to set bootfailed
attribute (it should be allowed only to unset it), but for test purposes it might be useful, so the current code allows it. Reviewed by: arch@ (Message-ID: <20100917234542.GE1902@garage.freebsd.pl>) MFC after: 2 weeks
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/part/g_part_gpt.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c
index 46a92ab..ee319cf 100644
--- a/sys/geom/part/g_part_gpt.c
+++ b/sys/geom/part/g_part_gpt.c
@@ -100,6 +100,8 @@ static const char *g_part_gpt_name(struct g_part_table *, struct g_part_entry *,
char *, size_t);
static int g_part_gpt_probe(struct g_part_table *, struct g_consumer *);
static int g_part_gpt_read(struct g_part_table *, struct g_consumer *);
+static int g_part_gpt_setunset(struct g_part_table *table,
+ struct g_part_entry *baseentry, const char *attrib, unsigned int set);
static const char *g_part_gpt_type(struct g_part_table *, struct g_part_entry *,
char *, size_t);
static int g_part_gpt_write(struct g_part_table *, struct g_consumer *);
@@ -118,6 +120,7 @@ static kobj_method_t g_part_gpt_methods[] = {
KOBJMETHOD(g_part_name, g_part_gpt_name),
KOBJMETHOD(g_part_probe, g_part_gpt_probe),
KOBJMETHOD(g_part_read, g_part_gpt_read),
+ KOBJMETHOD(g_part_setunset, g_part_gpt_setunset),
KOBJMETHOD(g_part_type, g_part_gpt_type),
KOBJMETHOD(g_part_write, g_part_gpt_write),
{ 0, 0 }
@@ -519,6 +522,16 @@ g_part_gpt_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry,
g_gpt_printf_utf16(sb, entry->ent.ent_name,
sizeof(entry->ent.ent_name) >> 1);
sbuf_printf(sb, "</label>\n");
+ if (entry->ent.ent_attr & GPT_ENT_ATTR_BOOTME)
+ sbuf_printf(sb, "%s<attrib>bootme</attrib>\n", indent);
+ if (entry->ent.ent_attr & GPT_ENT_ATTR_BOOTONCE) {
+ sbuf_printf(sb, "%s<attrib>bootonce</attrib>\n",
+ indent);
+ }
+ if (entry->ent.ent_attr & GPT_ENT_ATTR_BOOTFAILED) {
+ sbuf_printf(sb, "%s<attrib>bootfailed</attrib>\n",
+ indent);
+ }
sbuf_printf(sb, "%s<rawtype>", indent);
sbuf_printf_uuid(sb, &entry->ent.ent_type);
sbuf_printf(sb, "</rawtype>\n");
@@ -755,6 +768,78 @@ g_part_gpt_read(struct g_part_table *basetable, struct g_consumer *cp)
return (0);
}
+static int
+g_part_gpt_setunset(struct g_part_table *table, struct g_part_entry *baseentry,
+ const char *attrib, unsigned int set)
+{
+ struct g_part_entry *iter;
+ struct g_part_gpt_entry *entry;
+ int changed, bootme, bootonce, bootfailed;
+
+ bootme = bootonce = bootfailed = 0;
+ if (strcasecmp(attrib, "bootme") == 0) {
+ bootme = 1;
+ } else if (strcasecmp(attrib, "bootonce") == 0) {
+ /* BOOTME is set automatically with BOOTONCE, but not unset. */
+ bootonce = 1;
+ if (set)
+ bootme = 1;
+ } else if (strcasecmp(attrib, "bootfailed") == 0) {
+ /*
+ * It should only be possible to unset BOOTFAILED, but it might
+ * be useful for test purposes to also be able to set it.
+ */
+ bootfailed = 1;
+ }
+ if (!bootme && !bootonce && !bootfailed)
+ return (EINVAL);
+
+ LIST_FOREACH(iter, &table->gpt_entry, gpe_entry) {
+ if (iter->gpe_deleted)
+ continue;
+ if (iter != baseentry)
+ continue;
+ changed = 0;
+ entry = (struct g_part_gpt_entry *)iter;
+ if (set) {
+ if (bootme &&
+ !(entry->ent.ent_attr & GPT_ENT_ATTR_BOOTME)) {
+ entry->ent.ent_attr |= GPT_ENT_ATTR_BOOTME;
+ changed = 1;
+ }
+ if (bootonce &&
+ !(entry->ent.ent_attr & GPT_ENT_ATTR_BOOTONCE)) {
+ entry->ent.ent_attr |= GPT_ENT_ATTR_BOOTONCE;
+ changed = 1;
+ }
+ if (bootfailed &&
+ !(entry->ent.ent_attr & GPT_ENT_ATTR_BOOTFAILED)) {
+ entry->ent.ent_attr |= GPT_ENT_ATTR_BOOTFAILED;
+ changed = 1;
+ }
+ } else {
+ if (bootme &&
+ (entry->ent.ent_attr & GPT_ENT_ATTR_BOOTME)) {
+ entry->ent.ent_attr &= ~GPT_ENT_ATTR_BOOTME;
+ changed = 1;
+ }
+ if (bootonce &&
+ (entry->ent.ent_attr & GPT_ENT_ATTR_BOOTONCE)) {
+ entry->ent.ent_attr &= ~GPT_ENT_ATTR_BOOTONCE;
+ changed = 1;
+ }
+ if (bootfailed &&
+ (entry->ent.ent_attr & GPT_ENT_ATTR_BOOTFAILED)) {
+ entry->ent.ent_attr &= ~GPT_ENT_ATTR_BOOTFAILED;
+ changed = 1;
+ }
+ }
+ if (changed && !iter->gpe_created)
+ iter->gpe_modified = 1;
+ }
+ return (0);
+}
+
static const char *
g_part_gpt_type(struct g_part_table *basetable, struct g_part_entry *baseentry,
char *buf, size_t bufsz)
OpenPOWER on IntegriCloud