summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/geom/part/g_part_pc98.c93
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);
OpenPOWER on IntegriCloud