diff options
-rw-r--r-- | sys/geom/part/g_part_pc98.c | 93 |
1 files changed, 82 insertions, 11 deletions
diff --git a/sys/geom/part/g_part_pc98.c b/sys/geom/part/g_part_pc98.c index 4a763de..2b997bc 100644 --- a/sys/geom/part/g_part_pc98.c +++ b/sys/geom/part/g_part_pc98.c @@ -45,6 +45,14 @@ __FBSDID("$FreeBSD$"); #include "g_part_if.h" +#define PC98_MID_BOOTABLE 0x80 +#define PC98_MID_MASK 0x7f +#define PC98_MID_386BSD 0x14 + +#define PC98_SID_ACTIVE 0x80 +#define PC98_SID_MASK 0x7f +#define PC98_SID_386BSD 0x44 + #define SECSIZE 512 struct g_part_pc98_table { @@ -72,8 +80,10 @@ static char *g_part_pc98_name(struct g_part_table *, struct g_part_entry *, char *, size_t); static int g_part_pc98_probe(struct g_part_table *, struct g_consumer *); static int g_part_pc98_read(struct g_part_table *, struct g_consumer *); -static const char *g_part_pc98_type(struct g_part_table *, struct g_part_entry *, - char *, size_t); +static int g_part_pc98_setunset(struct g_part_table *, struct g_part_entry *, + const char *, unsigned int); +static const char *g_part_pc98_type(struct g_part_table *, + struct g_part_entry *, char *, size_t); static int g_part_pc98_write(struct g_part_table *, struct g_consumer *); static kobj_method_t g_part_pc98_methods[] = { @@ -87,6 +97,7 @@ static kobj_method_t g_part_pc98_methods[] = { KOBJMETHOD(g_part_name, g_part_pc98_name), KOBJMETHOD(g_part_probe, g_part_pc98_probe), KOBJMETHOD(g_part_read, g_part_pc98_read), + KOBJMETHOD(g_part_setunset, g_part_pc98_setunset), KOBJMETHOD(g_part_type, g_part_pc98_type), KOBJMETHOD(g_part_write, g_part_pc98_write), { 0, 0 } @@ -115,14 +126,17 @@ pc98_parse_type(const char *type, u_char *dp_mid, u_char *dp_sid) if (type[1] == '\0' || *endp != '\0' || lt <= 0 || lt >= 65536) return (EINVAL); - *dp_mid = (u_char)lt; - *dp_sid = (u_char)(lt >> 8); + /* Make sure the active and bootable flags aren't set. */ + if (lt & ((PC98_SID_ACTIVE << 8) | PC98_MID_BOOTABLE)) + return (ENOATTR); + *dp_mid = (*dp_mid & PC98_MID_BOOTABLE) | (u_char)lt; + *dp_sid = (*dp_sid & PC98_SID_ACTIVE) | (u_char)(lt >> 8); return (0); } alias = g_part_alias_name(G_PART_ALIAS_FREEBSD); if (!strcasecmp(type, alias)) { - *dp_mid = (u_char)DOSMID_386BSD; - *dp_sid = (u_char)DOSSID_386BSD; + *dp_mid = (*dp_mid & PC98_MID_BOOTABLE) | PC98_MID_386BSD; + *dp_sid = (*dp_sid & PC98_SID_ACTIVE) | PC98_SID_386BSD; return (0); } return (EINVAL); @@ -176,6 +190,8 @@ g_part_pc98_add(struct g_part_table *basetable, struct g_part_entry *baseentry, if (baseentry->gpe_deleted) bzero(&entry->ent, sizeof(entry->ent)); + else + entry->ent.dp_mid = entry->ent.dp_sid = 0; KASSERT(baseentry->gpe_start <= start, (__func__)); KASSERT(baseentry->gpe_end >= start + size - 1, (__func__)); @@ -259,7 +275,13 @@ g_part_pc98_dumpconf(struct g_part_table *table, } else { /* confxml: partition entry information */ sbuf_printf(sb, "%s<label>%s</label>\n", indent, name); - sbuf_printf(sb, "%s<rawtype>%u</rawtype>\n", indent, type); + if (entry->ent.dp_mid & PC98_MID_BOOTABLE) + sbuf_printf(sb, "%s<attrib>bootable</attrib>\n", + indent); + if (entry->ent.dp_sid & PC98_SID_ACTIVE) + sbuf_printf(sb, "%s<attrib>active</attrib>\n", indent); + sbuf_printf(sb, "%s<rawtype>%u</rawtype>\n", indent, + type & 0x7f7f); } return (0); } @@ -271,8 +293,8 @@ g_part_pc98_dumpto(struct g_part_table *table, struct g_part_entry *baseentry) /* Allow dumping to a FreeBSD partition only. */ entry = (struct g_part_pc98_entry *)baseentry; - return ((entry->ent.dp_mid == DOSMID_386BSD && - entry->ent.dp_sid == DOSSID_386BSD) ? 1 : 0); + return (((entry->ent.dp_mid & PC98_MID_MASK) == PC98_MID_386BSD && + (entry->ent.dp_sid & PC98_SID_MASK) == PC98_SID_386BSD) ? 1 : 0); } static int @@ -412,6 +434,54 @@ g_part_pc98_read(struct g_part_table *basetable, struct g_consumer *cp) return (0); } +static int +g_part_pc98_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_pc98_entry *entry; + int changed, mid, sid; + + mid = sid = 0; + if (strcasecmp(attrib, "active") == 0) + sid = 1; + else if (strcasecmp(attrib, "bootable") == 0) + mid = 1; + if (mid == 0 && sid == 0) + 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_pc98_entry *)iter; + if (set) { + if (mid && !(entry->ent.dp_mid & PC98_MID_BOOTABLE)) { + entry->ent.dp_mid |= PC98_MID_BOOTABLE; + changed = 1; + } + if (sid && !(entry->ent.dp_sid & PC98_SID_ACTIVE)) { + entry->ent.dp_sid |= PC98_SID_ACTIVE; + changed = 1; + } + } else { + if (mid && (entry->ent.dp_mid & PC98_MID_BOOTABLE)) { + entry->ent.dp_mid &= ~PC98_MID_BOOTABLE; + changed = 1; + } + if (sid && (entry->ent.dp_sid & PC98_SID_ACTIVE)) { + entry->ent.dp_sid &= ~PC98_SID_ACTIVE; + changed = 1; + } + } + if (changed && !iter->gpe_created) + iter->gpe_modified = 1; + } + return (0); +} + static const char * g_part_pc98_type(struct g_part_table *basetable, struct g_part_entry *baseentry, char *buf, size_t bufsz) @@ -420,8 +490,9 @@ g_part_pc98_type(struct g_part_table *basetable, struct g_part_entry *baseentry, u_int type; entry = (struct g_part_pc98_entry *)baseentry; - type = entry->ent.dp_mid + (entry->ent.dp_sid << 8); - if (type == DOSPTYP_386BSD) + type = (entry->ent.dp_mid & PC98_MID_MASK) | + ((entry->ent.dp_sid & PC98_SID_MASK) << 8); + if (type == (PC98_MID_386BSD | (PC98_SID_386BSD << 8))) return (g_part_alias_name(G_PART_ALIAS_FREEBSD)); snprintf(buf, bufsz, "!%d", type); return (buf); |