diff --git a/sbin/gpt/Makefile b/sbin/gpt/Makefile index 94a6b5606e79..8b9705d836ba 100644 --- a/sbin/gpt/Makefile +++ b/sbin/gpt/Makefile @@ -1,9 +1,9 @@ -# $NetBSD: Makefile,v 1.5 2013/11/20 08:08:47 jnemeth Exp $ +# $NetBSD: Makefile,v 1.6 2013/12/09 08:03:17 jnemeth Exp $ # $FreeBSD: src/sbin/gpt/Makefile,v 1.7 2005/09/01 02:49:20 marcel Exp $ PROG= gpt SRCS= add.c biosboot.c create.c destroy.c gpt.c label.c map.c migrate.c \ - recover.c remove.c resize.c show.c + recover.c remove.c resize.c set.c show.c unset.c MAN= gpt.8 LDADD+= -lprop -lutil diff --git a/sbin/gpt/gpt.8 b/sbin/gpt/gpt.8 index 66a7278476f8..d19e8b986dbb 100644 --- a/sbin/gpt/gpt.8 +++ b/sbin/gpt/gpt.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: gpt.8,v 1.24 2013/12/09 01:35:02 jnemeth Exp $ +.\" $NetBSD: gpt.8,v 1.25 2013/12/09 08:03:17 jnemeth Exp $ .\" .\" Copyright (c) 2002 Marcel Moolenaar .\" All rights reserved. @@ -26,7 +26,7 @@ .\" .\" $FreeBSD: src/sbin/gpt/gpt.8,v 1.17 2006/06/22 22:22:32 marcel Exp $ .\" -.Dd December 8, 2013 +.Dd December 9, 2013 .Dt GPT 8 .Os .Sh NAME @@ -344,6 +344,35 @@ If the .Fl a option is specified then the size will be adjusted to be a multiple of alignment if possible. +.\" ==== set ==== +.It Nm Ic set Fl a Ar attribute Fl i Ar index Ar device ... +The +.Ic set +command sets various partition attributes. +The +.Fl a +option specifies which attributes to set and may be specified more then once. +The +.Fl i +option specifies which entry to update. +The possible attributes are +.Do biosboot Dc , +.Do bootme Dc , +.Do bootonce Dc , and +.Do bootfailed Dc . +The biosboot flag is used to indicate which partition should be booted +by legacy BIOS boot code. +See the +.Ic biosboot +command for more information. +The other three attributes are for compatibility with +.Fx +and are not currently used by any +.Nx +code. +They may be used by +.Nx +code in the future. .\" ==== show ==== .It Nm Ic show Oo Fl glu Oc Oo Fl i Ar index Oc Ar device ... The @@ -372,6 +401,35 @@ The order of precedence for the options are: .Fl l , .Fl g , .Fl u . +.\" ==== unset ==== +.It Nm Ic unset Fl a Ar attribute Fl i Ar index Ar device ... +The +.Ic unset +command unsets various partition attributes. +The +.Fl a +option specifies which attributes to unset and may be specified more then once. +The +.Fl i +option specifies which entry to update. +The possible attributes are +.Do biosboot Dc , +.Do bootme Dc , +.Do bootonce Dc , and +.Do bootfailed Dc . +The biosboot flag is used to indicate which partition should be booted +by legacy BIOS boot code. +See the +.Ic biosboot +command for more information. +The other three attributes are for compatibility with +.Fx +and are not currently used by any +.Nx +code. +They may be used by +.Nx +code in the future. .El .Sh EXAMPLES .Bd -literal diff --git a/sbin/gpt/gpt.c b/sbin/gpt/gpt.c index 7a5cc0d5d8d1..acd021b624d3 100644 --- a/sbin/gpt/gpt.c +++ b/sbin/gpt/gpt.c @@ -31,7 +31,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/gpt.c,v 1.16 2006/07/07 02:44:23 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: gpt.c,v 1.25 2013/12/04 20:15:51 jakllsch Exp $"); +__RCSID("$NetBSD: gpt.c,v 1.26 2013/12/09 08:03:17 jnemeth Exp $"); #endif #include @@ -727,7 +727,9 @@ static struct { { cmd_remove, "remove" }, { NULL, "rename" }, { cmd_resize, "resize" }, + { cmd_set, "set" }, { cmd_show, "show" }, + { cmd_unset, "unset" }, { NULL, "verify" }, { NULL, NULL } }; @@ -738,7 +740,8 @@ usage(void) extern const char addmsg1[], addmsg2[], biosbootmsg[], createmsg[]; extern const char destroymsg[], labelmsg1[], labelmsg2[], labelmsg3[]; extern const char migratemsg[], recovermsg[], removemsg1[]; - extern const char removemsg2[], resizemsg[], showmsg[]; + extern const char removemsg2[], resizemsg[], setmsg[], showmsg[]; + extern const char unsetmsg[]; fprintf(stderr, "usage: %s %s\n" @@ -754,6 +757,8 @@ usage(void) " %s %s\n" " %s %s\n" " %s %s\n" + " %s %s\n" + " %s %s\n" " %s %s\n", getprogname(), addmsg1, getprogname(), addmsg2, @@ -768,7 +773,9 @@ usage(void) getprogname(), removemsg1, getprogname(), removemsg2, getprogname(), resizemsg, - getprogname(), showmsg); + getprogname(), setmsg, + getprogname(), showmsg, + getprogname(), unsetmsg); exit(1); } diff --git a/sbin/gpt/gpt.h b/sbin/gpt/gpt.h index 2b081e6a72f8..295d1f170afb 100644 --- a/sbin/gpt/gpt.h +++ b/sbin/gpt/gpt.h @@ -88,6 +88,8 @@ int cmd_migrate(int, char *[]); int cmd_recover(int, char *[]); int cmd_remove(int, char *[]); int cmd_resize(int, char *[]); +int cmd_set(int, char *[]); int cmd_show(int, char *[]); +int cmd_unset(int, char *[]); #endif /* _GPT_H_ */ diff --git a/sbin/gpt/set.c b/sbin/gpt/set.c new file mode 100644 index 000000000000..1403c8a6740e --- /dev/null +++ b/sbin/gpt/set.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 2002 Marcel Moolenaar + * 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 ``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 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 +#ifdef __FBSDID +__FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $"); +#endif +#ifdef __RCSID +__RCSID("$NetBSD: set.c,v 1.1 2013/12/09 08:03:17 jnemeth Exp $"); +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "map.h" +#include "gpt.h" + +static unsigned int entry; +static uint64_t attributes; + +const char setmsg[] = "set -a attribute -i index device ..."; + +__dead static void +usage_set(void) +{ + + fprintf(stderr, + "usage: %s %s\n", getprogname(), setmsg); + exit(1); +} + +static void +set(int fd) +{ + uuid_t uuid; + map_t *gpt, *tpg; + map_t *tbl, *lbt; + struct gpt_hdr *hdr; + struct gpt_ent *ent; + unsigned int i; + + + gpt = map_find(MAP_TYPE_PRI_GPT_HDR); + ent = NULL; + if (gpt == NULL) { + warnx("%s: error: no primary GPT header; run create or recover", + device_name); + return; + } + + tpg = map_find(MAP_TYPE_SEC_GPT_HDR); + if (tpg == NULL) { + warnx("%s: error: no secondary GPT header; run recover", + device_name); + return; + } + + tbl = map_find(MAP_TYPE_PRI_GPT_TBL); + lbt = map_find(MAP_TYPE_SEC_GPT_TBL); + if (tbl == NULL || lbt == NULL) { + warnx("%s: error: run recover -- trust me", device_name); + return; + } + + hdr = gpt->map_data; + if (entry > le32toh(hdr->hdr_entries)) { + warnx("%s: error: index %u out of range (%u max)", device_name, + entry, le32toh(hdr->hdr_entries)); + return; + } + + i = entry - 1; + ent = (void*)((char*)tbl->map_data + i * + le32toh(hdr->hdr_entsz)); + le_uuid_dec(ent->ent_type, &uuid); + if (uuid_is_nil(&uuid, NULL)) { + warnx("%s: error: entry at index %u is unused", + device_name, entry); + return; + } + + ent->ent_attr |= attributes; + + hdr->hdr_crc_table = htole32(crc32(tbl->map_data, + le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz))); + hdr->hdr_crc_self = 0; + hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size))); + + gpt_write(fd, gpt); + gpt_write(fd, tbl); + + hdr = tpg->map_data; + ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz)); + ent->ent_attr |= attributes; + + hdr->hdr_crc_table = htole32(crc32(lbt->map_data, + le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz))); + hdr->hdr_crc_self = 0; + hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size))); + + gpt_write(fd, lbt); + gpt_write(fd, tpg); + + printf("Partition attributes updated\n"); +} + +int +cmd_set(int argc, char *argv[]) +{ + char *p; + int ch, fd; + + while ((ch = getopt(argc, argv, "a:i:")) != -1) { + switch(ch) { + case 'a': + if (strcmp(optarg, "biosboot") == 0) + attributes |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE; + else if (strcmp(optarg, "bootme") == 0) + attributes |= GPT_ENT_ATTR_BOOTME; + else if (strcmp(optarg, "bootonce") == 0) + attributes |= GPT_ENT_ATTR_BOOTONCE; + else if (strcmp(optarg, "bootfailed") == 0) + attributes |= GPT_ENT_ATTR_BOOTFAILED; + else + usage_set(); + break; + case 'i': + if (entry > 0) + usage_set(); + entry = strtoul(optarg, &p, 10); + if (*p != 0 || entry < 1) + usage_set(); + break; + default: + usage_set(); + } + } + + if (argc == optind) + usage_set(); + + if (entry == 0 || attributes == 0) + usage_set(); + + while (optind < argc) { + fd = gpt_open(argv[optind++]); + if (fd == -1) { + warn("unable to open device '%s'", device_name); + continue; + } + + set(fd); + + gpt_close(fd); + } + + return 0; +} diff --git a/sbin/gpt/unset.c b/sbin/gpt/unset.c new file mode 100644 index 000000000000..e44f5b7f0002 --- /dev/null +++ b/sbin/gpt/unset.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 2002 Marcel Moolenaar + * 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 ``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 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 +#ifdef __FBSDID +__FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $"); +#endif +#ifdef __RCSID +__RCSID("$NetBSD: unset.c,v 1.1 2013/12/09 08:03:17 jnemeth Exp $"); +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "map.h" +#include "gpt.h" + +static unsigned int entry; +static uint64_t attributes; + +const char unsetmsg[] = "unset -a attribute -i index device ..."; + +__dead static void +usage_unset(void) +{ + + fprintf(stderr, + "usage: %s %s\n", getprogname(), unsetmsg); + exit(1); +} + +static void +unset(int fd) +{ + uuid_t uuid; + map_t *gpt, *tpg; + map_t *tbl, *lbt; + struct gpt_hdr *hdr; + struct gpt_ent *ent; + unsigned int i; + + + gpt = map_find(MAP_TYPE_PRI_GPT_HDR); + ent = NULL; + if (gpt == NULL) { + warnx("%s: error: no primary GPT header; run create or recover", + device_name); + return; + } + + tpg = map_find(MAP_TYPE_SEC_GPT_HDR); + if (tpg == NULL) { + warnx("%s: error: no secondary GPT header; run recover", + device_name); + return; + } + + tbl = map_find(MAP_TYPE_PRI_GPT_TBL); + lbt = map_find(MAP_TYPE_SEC_GPT_TBL); + if (tbl == NULL || lbt == NULL) { + warnx("%s: error: run recover -- trust me", device_name); + return; + } + + hdr = gpt->map_data; + if (entry > le32toh(hdr->hdr_entries)) { + warnx("%s: error: index %u out of range (%u max)", device_name, + entry, le32toh(hdr->hdr_entries)); + return; + } + + i = entry - 1; + ent = (void*)((char*)tbl->map_data + i * + le32toh(hdr->hdr_entsz)); + le_uuid_dec(ent->ent_type, &uuid); + if (uuid_is_nil(&uuid, NULL)) { + warnx("%s: error: entry at index %u is unused", + device_name, entry); + return; + } + + ent->ent_attr &= ~attributes; + + hdr->hdr_crc_table = htole32(crc32(tbl->map_data, + le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz))); + hdr->hdr_crc_self = 0; + hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size))); + + gpt_write(fd, gpt); + gpt_write(fd, tbl); + + hdr = tpg->map_data; + ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz)); + ent->ent_attr &= ~attributes; + + hdr->hdr_crc_table = htole32(crc32(lbt->map_data, + le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz))); + hdr->hdr_crc_self = 0; + hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size))); + + gpt_write(fd, lbt); + gpt_write(fd, tpg); + + printf("Partition attributes updated\n"); +} + +int +cmd_unset(int argc, char *argv[]) +{ + char *p; + int ch, fd; + + while ((ch = getopt(argc, argv, "a:i:")) != -1) { + switch(ch) { + case 'a': + if (strcmp(optarg, "biosboot") == 0) + attributes |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE; + else if (strcmp(optarg, "bootme") == 0) + attributes |= GPT_ENT_ATTR_BOOTME; + else if (strcmp(optarg, "bootonce") == 0) + attributes |= GPT_ENT_ATTR_BOOTONCE; + else if (strcmp(optarg, "bootfailed") == 0) + attributes |= GPT_ENT_ATTR_BOOTFAILED; + else + usage_unset(); + break; + case 'i': + if (entry > 0) + usage_unset(); + entry = strtoul(optarg, &p, 10); + if (*p != 0 || entry < 1) + usage_unset(); + break; + default: + usage_unset(); + } + } + + if (argc == optind) + usage_unset(); + + if (entry == 0 || attributes == 0) + usage_unset(); + + while (optind < argc) { + fd = gpt_open(argv[optind++]); + if (fd == -1) { + warn("unable to open device '%s'", device_name); + continue; + } + + unset(fd); + + gpt_close(fd); + } + + return 0; +}