diff options
-rw-r--r-- | sbin/geom/class/part/geom_part.c | 8 | ||||
-rw-r--r-- | sys/geom/part/g_part.c | 39 | ||||
-rw-r--r-- | sys/geom/part/g_part_ebr.c | 2 | ||||
-rw-r--r-- | sys/geom/part/g_part_gpt.c | 63 | ||||
-rw-r--r-- | sys/geom/part/g_part_mbr.c | 2 | ||||
-rw-r--r-- | sys/geom/part/g_part_pc98.c | 3 |
6 files changed, 78 insertions, 39 deletions
diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c index 8a57ca4..9b3e0e5 100644 --- a/sbin/geom/class/part/geom_part.c +++ b/sbin/geom/class/part/geom_part.c @@ -147,10 +147,10 @@ struct g_command PUBSYM(class_commands)[] = { }, { "set", 0, gpart_issue, { { 'a', "attrib", NULL, G_TYPE_STRING }, - { 'i', GPART_PARAM_INDEX, NULL, G_TYPE_NUMBER }, + { 'i', GPART_PARAM_INDEX, G_VAL_OPTIONAL, G_TYPE_NUMBER }, { 'f', "flags", GPART_FLAGS, G_TYPE_STRING }, G_OPT_SENTINEL }, - "-a attrib -i index [-f flags] geom" + "-a attrib [-i index] [-f flags] geom" }, { "show", 0, gpart_show, { { 'l', "show_label", NULL, G_TYPE_BOOL }, @@ -164,10 +164,10 @@ struct g_command PUBSYM(class_commands)[] = { }, { "unset", 0, gpart_issue, { { 'a', "attrib", NULL, G_TYPE_STRING }, - { 'i', GPART_PARAM_INDEX, NULL, G_TYPE_NUMBER }, + { 'i', GPART_PARAM_INDEX, G_VAL_OPTIONAL, G_TYPE_NUMBER }, { 'f', "flags", GPART_FLAGS, G_TYPE_STRING }, G_OPT_SENTINEL }, - "-a attrib -i index [-f flags] geom" + "-a attrib [-i index] [-f flags] geom" }, { "resize", 0, gpart_issue, { { 'a', "alignment", GPART_AUTOFILL, G_TYPE_STRING }, diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c index 1583122..31b535a 100644 --- a/sys/geom/part/g_part.c +++ b/sys/geom/part/g_part.c @@ -1352,16 +1352,20 @@ g_part_ctl_setunset(struct gctl_req *req, struct g_part_parms *gpp, table = gp->softc; - LIST_FOREACH(entry, &table->gpt_entry, gpe_entry) { - if (entry->gpe_deleted || entry->gpe_internal) - continue; - if (entry->gpe_index == gpp->gpp_index) - break; - } - if (entry == NULL) { - gctl_error(req, "%d index '%d'", ENOENT, gpp->gpp_index); - return (ENOENT); - } + if (gpp->gpp_parms & G_PART_PARM_INDEX) { + LIST_FOREACH(entry, &table->gpt_entry, gpe_entry) { + if (entry->gpe_deleted || entry->gpe_internal) + continue; + if (entry->gpe_index == gpp->gpp_index) + break; + } + if (entry == NULL) { + gctl_error(req, "%d index '%d'", ENOENT, + gpp->gpp_index); + return (ENOENT); + } + } else + entry = NULL; error = G_PART_SETUNSET(table, entry, gpp->gpp_attrib, set); if (error) { @@ -1374,8 +1378,11 @@ g_part_ctl_setunset(struct gctl_req *req, struct g_part_parms *gpp, sb = sbuf_new_auto(); sbuf_printf(sb, "%s %sset on ", gpp->gpp_attrib, (set) ? "" : "un"); - G_PART_FULLNAME(table, entry, sb, gp->name); - sbuf_printf(sb, "\n"); + if (entry) + G_PART_FULLNAME(table, entry, sb, gp->name); + else + sbuf_cat(sb, gp->name); + sbuf_cat(sb, "\n"); sbuf_finish(sb); gctl_set_param(req, "output", sbuf_data(sb), sbuf_len(sb) + 1); sbuf_delete(sb); @@ -1581,8 +1588,8 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb) case 's': if (!strcmp(verb, "set")) { ctlreq = G_PART_CTL_SET; - mparms |= G_PART_PARM_ATTRIB | G_PART_PARM_GEOM | - G_PART_PARM_INDEX; + mparms |= G_PART_PARM_ATTRIB | G_PART_PARM_GEOM; + oparms |= G_PART_PARM_INDEX; } break; case 'u': @@ -1592,8 +1599,8 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb) modifies = 0; } else if (!strcmp(verb, "unset")) { ctlreq = G_PART_CTL_UNSET; - mparms |= G_PART_PARM_ATTRIB | G_PART_PARM_GEOM | - G_PART_PARM_INDEX; + mparms |= G_PART_PARM_ATTRIB | G_PART_PARM_GEOM; + oparms |= G_PART_PARM_INDEX; } break; } diff --git a/sys/geom/part/g_part_ebr.c b/sys/geom/part/g_part_ebr.c index 889f263..03b9aac 100644 --- a/sys/geom/part/g_part_ebr.c +++ b/sys/geom/part/g_part_ebr.c @@ -540,6 +540,8 @@ g_part_ebr_setunset(struct g_part_table *table, struct g_part_entry *baseentry, struct g_part_ebr_entry *entry; int changed; + if (baseentry == NULL) + return (ENODEV); if (strcasecmp(attrib, "active") != 0) return (EINVAL); diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c index 405b492..12b0f89 100644 --- a/sys/geom/part/g_part_gpt.c +++ b/sys/geom/part/g_part_gpt.c @@ -260,6 +260,16 @@ gpt_map_type(struct uuid *t) return (0); } +static void +gpt_create_pmbr(struct g_part_gpt_table *table, struct g_provider *pp) +{ + + bzero(table->mbr + DOSPARTOFF, DOSPARTSIZE * NDOSPART); + gpt_write_mbr_entry(table->mbr, 0, 0xee, 1, + MIN(pp->mediasize / pp->sectorsize - 1, UINT32_MAX)); + le16enc(table->mbr + DOSMAGICOFFSET, DOSMAGIC); +} + /* * Under Boot Camp the PMBR partition (type 0xEE) doesn't cover the * whole disk anymore. Rather, it covers the GPT table and the EFI @@ -284,7 +294,7 @@ gpt_is_bootcamp(struct g_part_gpt_table *table, const char *provname) } static void -gpt_update_bootcamp(struct g_part_table *basetable) +gpt_update_bootcamp(struct g_part_table *basetable, struct g_provider *pp) { struct g_part_entry *baseentry; struct g_part_gpt_entry *entry; @@ -341,6 +351,7 @@ gpt_update_bootcamp(struct g_part_table *basetable) disable: table->bootcamp = 0; + gpt_create_pmbr(table, pp); } static struct gpt_hdr * @@ -609,6 +620,8 @@ g_part_gpt_create(struct g_part_table *basetable, struct g_part_parms *gpp) pp->sectorsize) return (ENOSPC); + gpt_create_pmbr(table, pp); + /* Allocate space for the header */ table->hdr = g_malloc(sizeof(struct gpt_hdr), M_WAITOK | M_ZERO); @@ -936,9 +949,13 @@ g_part_gpt_read(struct g_part_table *basetable, struct g_consumer *cp) static int g_part_gpt_recover(struct g_part_table *basetable) { + struct g_part_gpt_table *table; + struct g_provider *pp; - g_gpt_set_defaults(basetable, - LIST_FIRST(&basetable->gpt_gp->consumer)->provider); + table = (struct g_part_gpt_table *)basetable; + pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider; + gpt_create_pmbr(table, pp); + g_gpt_set_defaults(basetable, pp); basetable->gpt_corrupt = 0; return (0); } @@ -949,6 +966,7 @@ g_part_gpt_setunset(struct g_part_table *basetable, { struct g_part_gpt_entry *entry; struct g_part_gpt_table *table; + uint8_t *p; uint64_t attr; int i; @@ -956,15 +974,32 @@ g_part_gpt_setunset(struct g_part_table *basetable, entry = (struct g_part_gpt_entry *)baseentry; if (strcasecmp(attrib, "active") == 0) { - if (!table->bootcamp || baseentry->gpe_index > NDOSPART) - return (EINVAL); - for (i = 0; i < NDOSPART; i++) { - table->mbr[DOSPARTOFF + i * DOSPARTSIZE] = - (i == baseentry->gpe_index - 1) ? 0x80 : 0; + if (table->bootcamp) { + /* The active flag must be set on a valid entry. */ + if (entry == NULL) + return (ENXIO); + if (baseentry->gpe_index > NDOSPART) + return (EINVAL); + for (i = 0; i < NDOSPART; i++) { + p = &table->mbr[DOSPARTOFF + i * DOSPARTSIZE]; + p[0] = (i == baseentry->gpe_index - 1) + ? ((set) ? 0x80 : 0) : 0; + } + } else { + /* The PMBR is marked as active without an entry. */ + if (entry != NULL) + return (ENXIO); + for (i = 0; i < NDOSPART; i++) { + p = &table->mbr[DOSPARTOFF + i * DOSPARTSIZE]; + p[0] = (p[4] == 0xee) ? ((set) ? 0x80 : 0) : 0; + } } return (0); } + if (entry == NULL) + return (ENODEV); + attr = 0; if (strcasecmp(attrib, "bootme") == 0) { attr |= GPT_ENT_ATTR_BOOTME; @@ -1032,17 +1067,7 @@ g_part_gpt_write(struct g_part_table *basetable, struct g_consumer *cp) /* Reconstruct the MBR from the GPT if under Boot Camp. */ if (table->bootcamp) - gpt_update_bootcamp(basetable); - - /* Update partition entries in the PMBR if Boot Camp disabled. */ - if (!table->bootcamp) { - bzero(table->mbr + DOSPARTOFF, DOSPARTSIZE * NDOSPART); - gpt_write_mbr_entry(table->mbr, 0, 0xee, 1, - MIN(pp->mediasize / pp->sectorsize - 1, UINT32_MAX)); - /* Mark the PMBR active since some BIOS require it. */ - table->mbr[DOSPARTOFF] = 0x80; - } - le16enc(table->mbr + DOSMAGICOFFSET, DOSMAGIC); + gpt_update_bootcamp(basetable, pp); /* Write the PMBR */ buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO); diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c index d522d02..459aee6 100644 --- a/sys/geom/part/g_part_mbr.c +++ b/sys/geom/part/g_part_mbr.c @@ -497,6 +497,8 @@ g_part_mbr_setunset(struct g_part_table *table, struct g_part_entry *baseentry, struct g_part_mbr_entry *entry; int changed; + if (baseentry == NULL) + return (ENODEV); if (strcasecmp(attrib, "active") != 0) return (EINVAL); diff --git a/sys/geom/part/g_part_pc98.c b/sys/geom/part/g_part_pc98.c index 0d81a0e..4d2b60c 100644 --- a/sys/geom/part/g_part_pc98.c +++ b/sys/geom/part/g_part_pc98.c @@ -498,6 +498,9 @@ g_part_pc98_setunset(struct g_part_table *table, struct g_part_entry *baseentry, struct g_part_pc98_entry *entry; int changed, mid, sid; + if (baseentry == NULL) + return (ENODEV); + mid = sid = 0; if (strcasecmp(attrib, "active") == 0) sid = 1; |