version 1.2.6.1, 2015/06/02 19:49:38 |
version 1.2.6.2, 2018/08/13 16:12:12 |
Line 47 __RCSID("$NetBSD$"); |
|
Line 47 __RCSID("$NetBSD$"); |
|
|
|
#include "map.h" |
#include "map.h" |
#include "gpt.h" |
#include "gpt.h" |
|
#include "gpt_private.h" |
|
|
static unsigned int entry; |
static int cmd_set(gpt_t, int, char *[]); |
static uint64_t attributes; |
|
|
|
const char setmsg[] = "set -a attribute -i index device ..."; |
static const char *sethelp[] = { |
|
"-a attribute -i index", |
|
"-l", |
|
}; |
|
|
|
struct gpt_cmd c_set = { |
|
"set", |
|
cmd_set, |
|
sethelp, __arraycount(sethelp), |
|
GPT_OPTDEV, |
|
}; |
|
|
__dead static void |
#define usage() gpt_usage(NULL, &c_set) |
usage_set(void) |
|
{ |
|
|
|
fprintf(stderr, |
|
"usage: %s %s\n", getprogname(), setmsg); |
|
exit(1); |
|
} |
|
|
|
static void |
|
set(int fd) |
|
{ |
|
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)); |
|
if (gpt_uuid_is_nil(ent->ent_type)) { |
|
warnx("%s: error: entry at index %u is unused", |
|
device_name, entry); |
|
return; |
|
} |
|
|
|
ent->ent_attr |= attributes; |
static int |
|
cmd_set(gpt_t gpt, int argc, char *argv[]) |
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 %d attributes updated\n", entry); |
|
} |
|
|
|
int |
|
cmd_set(int argc, char *argv[]) |
|
{ |
{ |
char *p; |
int ch; |
int ch, fd; |
unsigned int entry = 0; |
|
uint64_t attributes = 0; |
|
|
while ((ch = getopt(argc, argv, "a:i:")) != -1) { |
while ((ch = getopt(argc, argv, "a:i:l")) != -1) { |
switch(ch) { |
switch(ch) { |
case 'a': |
case 'a': |
if (strcmp(optarg, "biosboot") == 0) |
if (gpt == NULL || gpt_attr_get(gpt, &attributes) == -1) |
attributes |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE; |
return usage(); |
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; |
break; |
case 'i': |
case 'i': |
if (entry > 0) |
if (gpt == NULL || gpt_uint_get(gpt, &entry) == -1) |
usage_set(); |
return usage(); |
entry = strtoul(optarg, &p, 10); |
|
if (*p != 0 || entry < 1) |
|
usage_set(); |
|
break; |
break; |
|
case 'l': |
|
gpt_attr_help("\t"); |
|
return 0; |
default: |
default: |
usage_set(); |
return usage(); |
} |
} |
} |
} |
|
|
if (argc == optind) |
if (gpt == NULL || argc != optind) |
usage_set(); |
return usage(); |
|
|
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; |
return gpt_attr_update(gpt, entry, attributes, 0); |
} |
} |