From fba7235c8f065143ebcde5dd90e0f7eb8ce85042 Mon Sep 17 00:00:00 2001 From: krw Date: Mon, 26 Oct 2015 15:08:26 +0000 Subject: [PATCH] Add GPT editing. Based on GSOC 2014 work by Markus Muller. --- sbin/fdisk/cmd.c | 230 ++++++++++++++++++++++++++++++++----- sbin/fdisk/cmd.h | 3 +- sbin/fdisk/fdisk.c | 53 +++++---- sbin/fdisk/gpt.c | 275 ++++++++++++++++++++++++++++++++++++++++++++- sbin/fdisk/gpt.h | 9 +- sbin/fdisk/mbr.c | 32 +++++- sbin/fdisk/mbr.h | 3 +- sbin/fdisk/misc.c | 141 ++++++++++++++--------- sbin/fdisk/misc.h | 7 +- sbin/fdisk/part.c | 121 +++++++++++++++----- sbin/fdisk/part.h | 4 +- sbin/fdisk/user.c | 46 ++++---- 12 files changed, 759 insertions(+), 165 deletions(-) diff --git a/sbin/fdisk/cmd.c b/sbin/fdisk/cmd.c index 19b5e2f9606..6d445017f49 100644 --- a/sbin/fdisk/cmd.c +++ b/sbin/fdisk/cmd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd.c,v 1.82 2015/04/02 18:00:55 krw Exp $ */ +/* $OpenBSD: cmd.c,v 1.83 2015/10/26 15:08:26 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -16,6 +16,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #include @@ -26,30 +27,53 @@ #include #include #include +#include #include "disk.h" #include "misc.h" #include "part.h" #include "mbr.h" +#include "gpt.h" #include "user.h" #include "cmd.h" int reinited; +/* Some helper functions for GPT handling. */ +int Xgedit(char *); +int Xgsetpid(char *); + int Xreinit(char *args, struct mbr *mbr) { struct dos_mbr dos_mbr; + int dogpt; + + if (strncasecmp(args, "gpt", 3) == 0) + dogpt = 1; + else if (strncasecmp(args, "mbr", 3) == 0) + dogpt = 0; + else if (strlen(args) > 0) { + printf("Unrecognized modifier '%s'\n", args); + return (CMD_CONT); + } else if (MBR_protective_mbr(&initial_mbr) == 0) + dogpt = 1; + else + dogpt = 0; MBR_make(&initial_mbr, &dos_mbr); MBR_parse(&dos_mbr, mbr->offset, mbr->reloffset, mbr); - MBR_init(mbr); + if (dogpt) { + MBR_init_GPT(mbr); + GPT_init(); + GPT_print("s"); + } else { + MBR_init(mbr); + MBR_print(mbr, "s"); + } reinited = 1; - /* Tell em we did something */ - printf("In memory copy is initialized to:\n"); - MBR_print(mbr, args); printf("Use 'write' to update disk.\n"); return (CMD_DIRTY); @@ -91,8 +115,9 @@ Xswap(char *args, struct mbr *mbr) { const char *errstr; char *from, *to; - int pf, pt; + int pf, pt, maxpn; struct prt pp; + struct gpt_partition gg; to = args; from = strsep(&to, " \t"); @@ -102,12 +127,17 @@ Xswap(char *args, struct mbr *mbr) return (CMD_CONT); } - pf = strtonum(from, 0, 3, &errstr); + if (letoh64(gh.gh_sig) == GPTSIGNATURE) + maxpn = NGPTPARTITIONS - 1; + else + maxpn = NDOSPART - 1; + + pf = strtonum(from, 0, maxpn, &errstr); if (errstr) { printf("partition number is %s: %s\n", errstr, from); return (CMD_CONT); } - pt = strtonum(to, 0, 3, &errstr); + pt = strtonum(to, 0, maxpn, &errstr); if (errstr) { printf("partition number is %s: %s\n", errstr, to); return (CMD_CONT); @@ -118,13 +148,61 @@ Xswap(char *args, struct mbr *mbr) return (CMD_CONT); } - pp = mbr->part[pt]; - mbr->part[pt] = mbr->part[pf]; - mbr->part[pf] = pp; + if (letoh64(gh.gh_sig) == GPTSIGNATURE) { + gg = gp[pt]; + gp[pt] = gp[pf]; + gp[pf] = gg; + } else { + pp = mbr->part[pt]; + mbr->part[pt] = mbr->part[pf]; + mbr->part[pf] = pp; + } return (CMD_DIRTY); } +int +Xgedit(char *args) +{ + const char *errstr; + struct gpt_partition *gg; + char *name; + u_int64_t bs, ns; + int pn, ret; + + pn = strtonum(args, 0, NGPTPARTITIONS - 1, &errstr); + if (errstr) { + printf("partition number is %s: %s\n", errstr, args); + return (CMD_CONT); + } + gg = &gp[pn]; + + /* Edit partition type */ + ret = Xgsetpid(args); + + /* Unused, so just zero out */ + if (uuid_is_nil(&gg->gp_type, NULL)) { + memset(gg, 0, sizeof(struct gpt_partition)); + printf("Partition %d is disabled.\n", pn); + return (ret); + } + + /* Change table entry */ + bs = getuint64("Partition offset", letoh64(gh.gh_lba_start), + letoh64(gh.gh_lba_end)); + ns = getuint64("Partition size", letoh64(gh.gh_lba_end) - bs + 1, + letoh64(gh.gh_lba_end) - bs + 1); + + gg->gp_lba_start = htole64(bs); + gg->gp_lba_end = htole64(bs + ns - 1); + + /* Ask for partition name. */ + name = ask_string("partition name", utf16le_to_string(gg->gp_name)); + memcpy(gg->gp_name, string_to_utf16le(name), sizeof(gg->gp_name)); + + return (ret); +} + int Xedit(char *args, struct mbr *mbr) { @@ -132,6 +210,9 @@ Xedit(char *args, struct mbr *mbr) int pn, num, ret; struct prt *pp; + if (letoh64(gh.gh_sig) == GPTSIGNATURE) + return (Xgedit(args)); + pn = strtonum(args, 0, 3, &errstr); if (errstr) { printf("partition number is %s: %s\n", errstr, args); @@ -186,6 +267,43 @@ Xedit(char *args, struct mbr *mbr) return (ret); } +int +Xgsetpid(char *args) +{ + const char *errstr; + struct uuid guid; + struct gpt_partition *gg; + int pn, num, status; + + pn = strtonum(args, 0, NGPTPARTITIONS - 1, &errstr); + if (errstr) { + printf("partition number is %s: %s\n", errstr, args); + return (CMD_CONT); + } + gg = &gp[pn]; + + /* Print out current table entry */ + GPT_print_parthdr(); + GPT_print_part(pn, "s"); + + /* Ask for partition type or GUID. */ + num = ask_pid(0, &guid); + if (num <= 0xff) + guid = *(PRT_type_to_uuid(num)); + uuid_enc_le(&gg->gp_type, &guid); + + if (uuid_is_nil(&gg->gp_guid, NULL)) { + uuid_create(&guid, &status); + if (status != uuid_s_ok) { + printf("could not create guid for partition\n"); + return (CMD_CONT); + } + uuid_enc_le(&gg->gp_guid, &guid); + } + + return (CMD_DIRTY); +} + int Xsetpid(char *args, struct mbr *mbr) { @@ -193,6 +311,9 @@ Xsetpid(char *args, struct mbr *mbr) int pn, num; struct prt *pp; + if (letoh64(gh.gh_sig) == GPTSIGNATURE) + return (Xgsetpid(args)); + pn = strtonum(args, 0, 3, &errstr); if (errstr) { printf("partition number is %s: %s\n", errstr, args); @@ -205,7 +326,7 @@ Xsetpid(char *args, struct mbr *mbr) PRT_print(pn, pp, NULL); /* Ask for MBR partition type */ - num = ask_pid(pp->id, 0x01, 0xff); + num = ask_pid(pp->id, NULL); if (num == pp->id) return (CMD_CONT); @@ -258,8 +379,10 @@ int Xprint(char *args, struct mbr *mbr) { - DISK_printgeometry(args); - MBR_print(mbr, args); + if (MBR_protective_mbr(mbr) == 0 && letoh64(gh.gh_sig) == GPTSIGNATURE) + GPT_print(args); + else + MBR_print(mbr, args); return (CMD_CONT); } @@ -291,9 +414,19 @@ Xwrite(char *args, struct mbr *mbr) return (CMD_CONT); } - /* Make sure GPT doesn't get in the way. */ - if (reinited) + if (letoh64(gh.gh_sig) == GPTSIGNATURE) { + printf("Writing GPT.\n"); + if (GPT_write(fd) == -1) { + int saved_errno = errno; + warn("error writing GPT"); + close(fd); + errno = saved_errno; + return (CMD_CONT); + } + } else if (reinited) { + /* Make sure GPT doesn't get in the way. */ MBR_zapgpt(fd, &dos_mbr, DL_GETDSIZE(&dl) - 1); + } /* Refresh in memory copy to reflect what was just written. */ MBR_parse(&dos_mbr, mbr->offset, mbr->reloffset, mbr); @@ -324,10 +457,26 @@ Xexit(char *args, struct mbr *mbr) int Xhelp(char *args, struct mbr *mbr) { + char *mbrstr, *gpthelp; int i; - for (i = 0; cmd_table[i].cmd != NULL; i++) + for (i = 0; cmd_table[i].cmd != NULL; i++) { + if (letoh64(gh.gh_sig) == GPTSIGNATURE) { + if (cmd_table[i].gpt == 0) + continue; + gpthelp = strdup(cmd_table[i].help); + mbrstr = strstr(gpthelp, "MBR"); + if (mbrstr) { + memcpy(mbrstr, "GPT", 3); + printf("\t%s\t\t%s\n", cmd_table[i].cmd, + gpthelp); + free(gpthelp); + continue; + } + } printf("\t%s\t\t%s\n", cmd_table[i].cmd, cmd_table[i].help); + } + return (CMD_CONT); } @@ -345,38 +494,57 @@ int Xflag(char *args, struct mbr *mbr) { const char *errstr; - int i, pn = -1, val = -1; + int i, maxpn, pn = -1; + long long val = -1; char *part, *flag; flag = args; part = strsep(&flag, " \t"); - pn = strtonum(part, 0, 3, &errstr); + if (letoh64(gh.gh_sig) == GPTSIGNATURE) + maxpn = NGPTPARTITIONS - 1; + else + maxpn = NDOSPART - 1; + + pn = strtonum(part, 0, maxpn, &errstr); if (errstr) { printf("partition number is %s: %s.\n", errstr, part); return (CMD_CONT); } if (flag != NULL) { - val = (int)strtonum(flag, 0, 0xff, &errstr); + /* Set flag to value provided. */ + if (letoh64(gh.gh_sig) == GPTSIGNATURE) + val = strtonum(flag, 0, LLONG_MAX, &errstr); + else + val = strtonum(flag, 0, 0xff, &errstr); if (errstr) { printf("flag value is %s: %s.\n", errstr, flag); return (CMD_CONT); } - } - - if (val == -1) { + if (letoh64(gh.gh_sig) == GPTSIGNATURE) + gp[pn].gp_attrs = htole64(val); + else + mbr->part[pn].flag = val; + printf("Partition %d flag value set to 0x%llx.\n", pn, val); + } else { /* Set active flag */ - for (i = 0; i < 4; i++) { - if (i == pn) - mbr->part[i].flag = DOSACTIVE; - else - mbr->part[i].flag = 0x00; + if (letoh64(gh.gh_sig) == GPTSIGNATURE) { + for (i = 0; i < NGPTPARTITIONS; i++) { + if (i == pn) + gp[i].gp_attrs = htole64(GPTDOSACTIVE); + else + gp[i].gp_attrs = htole64(0); + } + } else { + for (i = 0; i < NDOSPART; i++) { + if (i == pn) + mbr->part[i].flag = DOSACTIVE; + else + mbr->part[i].flag = 0x00; + } } printf("Partition %d marked active.\n", pn); - } else { - mbr->part[pn].flag = val; - printf("Partition %d flag value set to 0x%x.\n", pn, val); } return (CMD_DIRTY); diff --git a/sbin/fdisk/cmd.h b/sbin/fdisk/cmd.h index 9d478b64668..af3e7675519 100644 --- a/sbin/fdisk/cmd.h +++ b/sbin/fdisk/cmd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd.h,v 1.17 2015/03/18 14:46:59 krw Exp $ */ +/* $OpenBSD: cmd.h,v 1.18 2015/10/26 15:08:26 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -27,6 +27,7 @@ struct cmd { char *cmd; + int gpt; int (*fcn)(char *, struct mbr *); char *help; }; diff --git a/sbin/fdisk/fdisk.c b/sbin/fdisk/fdisk.c index f1605c2f94c..450d41edd19 100644 --- a/sbin/fdisk/fdisk.c +++ b/sbin/fdisk/fdisk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fdisk.c,v 1.78 2015/10/05 01:39:08 krw Exp $ */ +/* $OpenBSD: fdisk.c,v 1.79 2015/10/26 15:08:26 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -71,8 +71,8 @@ int main(int argc, char *argv[]) { ssize_t len; - int ch, fd; - int i_flag = 0, e_flag = 0, u_flag = 0; + int ch, fd, error; + int i_flag = 0, e_flag = 0, f_flag = 0, u_flag = 0; int c_arg = 0, h_arg = 0, s_arg = 0; u_int32_t l_arg = 0; char *query; @@ -97,6 +97,7 @@ main(int argc, char *argv[]) e_flag = 1; break; case 'f': + f_flag = 1; mbrfile = optarg; break; case 'c': @@ -148,18 +149,24 @@ main(int argc, char *argv[]) else disk.name = argv[0]; - if (g_flag != 0 && i_flag == 0) { - warnx("-g specified without -i"); - usage(); - } + /* Start with the disklabel geometry and get the sector size. */ + DISK_getlabelgeometry(); if (b_arg > 0 && i_flag == 0) { warnx("-b specified without -i"); usage(); } - /* Start with the disklabel geometry and get the sector size. */ - DISK_getlabelgeometry(); + if (g_flag != 0 && i_flag == 0) { + warnx("-g specified without -i"); + usage(); + } + + /* Get the GPT if present. */ + if (GPT_get_gpt()) { + memset(&gh, 0, sizeof(gh)); + memset(&gp, 0, sizeof(gp)); + } if (c_arg | h_arg | s_arg) { /* Use supplied geometry if it is completely specified. */ @@ -188,13 +195,25 @@ main(int argc, char *argv[]) USER_print_disk(); /* Create initial/default MBR. */ + if (i_flag == 0) { + fd = DISK_open(disk.name, O_RDONLY); + error = MBR_read(fd, 0, &dos_mbr); + close(fd); + if (error) + errx(1, "Can't read sector 0!"); + MBR_parse(&dos_mbr, 0, 0, &initial_mbr); + } + if (mbrfile != NULL && (fd = open(mbrfile, O_RDONLY)) == -1) { warn("%s", mbrfile); warnx("using builtin MBR"); + memset(&initial_mbr, 0, sizeof(initial_mbr)); mbrfile = NULL; } if (mbrfile == NULL) { - memcpy(&dos_mbr, builtin_mbr, sizeof(dos_mbr)); + if (MBR_protective_mbr(&initial_mbr) != 0) { + memcpy(&dos_mbr, builtin_mbr, sizeof(dos_mbr)); + } } else { len = read(fd, &dos_mbr, sizeof(dos_mbr)); if (len == -1) @@ -204,7 +223,10 @@ main(int argc, char *argv[]) mbrfile); close(fd); } - MBR_parse(&dos_mbr, 0, 0, &initial_mbr); + if (f_flag || MBR_protective_mbr(&initial_mbr) != 0) { + memset(&gh, 0, sizeof(struct gpt_header)); + MBR_parse(&dos_mbr, 0, 0, &initial_mbr); + } query = NULL; if (i_flag) { @@ -221,15 +243,8 @@ main(int argc, char *argv[]) MBR_pcopy(&initial_mbr); query = "Do you wish to write new MBR?"; } - if (query && ask_yn(query)) { + if (query && ask_yn(query)) Xwrite(NULL, &initial_mbr); - if (g_flag) { - fd = DISK_open(disk.name, O_RDWR); - if (GPT_write(fd) == -1) - warn("error writing GPT"); - close(fd); - } - } if (e_flag) USER_edit(0, 0); diff --git a/sbin/fdisk/gpt.c b/sbin/fdisk/gpt.c index 698f8872980..7f37628c16f 100644 --- a/sbin/fdisk/gpt.c +++ b/sbin/fdisk/gpt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gpt.c,v 1.1 2015/10/05 01:39:08 krw Exp $ */ +/* $OpenBSD: gpt.c,v 1.2 2015/10/26 15:08:26 krw Exp $ */ /* * Copyright (c) 2015 Markus Muller * Copyright (c) 2015 Kenneth R Westerback @@ -16,10 +16,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #include +#include #include +#include +#include #include #include #include @@ -31,9 +35,273 @@ #include "part.h" #include "gpt.h" +#ifdef DEBUG +#define DPRINTF(x...) printf(x) +#else +#define DPRINTF(x...) +#endif + struct gpt_header gh; struct gpt_partition gp[NGPTPARTITIONS]; +int +GPT_get_header(int fd, off_t where) +{ + char *secbuf; + uint64_t partlastlba; + int partspersec; + uint32_t orig_gh_csum, new_gh_csum; + + secbuf = DISK_readsector(fd, where); + if (secbuf == 0) + return (1); + + memcpy(&gh, secbuf, sizeof(struct gpt_header)); + free(secbuf); + + if (letoh64(gh.gh_sig) != GPTSIGNATURE) { + DPRINTF("gpt signature: expected 0x%llx, got 0x%llx\n", + GPTSIGNATURE, letoh64(gh.gh_sig)); + return (1); + } + + if (letoh32(gh.gh_rev) != GPTREVISION) { + DPRINTF("gpt revision: expected 0x%x, got 0x%x\n", + GPTREVISION, letoh32(gh.gh_rev)); + return (1); + } + + if (letoh64(gh.gh_lba_self) != where) { + DPRINTF("gpt self lba: expected %lld, got %llu\n", + (long long)where, letoh64(gh.gh_lba_self)); + return (1); + } + + if (letoh32(gh.gh_size) != GPTMINHDRSIZE) { + DPRINTF("gpt header size: expected %u, got %u\n", + GPTMINHDRSIZE, letoh32(gh.gh_size)); + return (1); + } + + if (letoh32(gh.gh_part_size) != GPTMINPARTSIZE) { + DPRINTF("gpt partition size: expected %u, got %u\n", + GPTMINPARTSIZE, letoh32(gh.gh_part_size)); + return (1); + } + + if (letoh32(gh.gh_part_num) > NGPTPARTITIONS) { + DPRINTF("gpt partition count: expected <= %u, got %u\n", + NGPTPARTITIONS, letoh32(gh.gh_part_num)); + return (1); + } + + orig_gh_csum = gh.gh_csum; + gh.gh_csum = 0; + new_gh_csum = crc32((unsigned char *)&gh, letoh32(gh.gh_size)); + gh.gh_csum = orig_gh_csum; + if (letoh32(orig_gh_csum) != new_gh_csum) { + DPRINTF("gpt header checksum: expected 0x%x, got 0x%x\n", + orig_gh_csum, new_gh_csum); + return (1); + } + + if (letoh64(gh.gh_lba_end) >= DL_GETDSIZE(&dl)) { + DPRINTF("gpt last usable LBA: expected < %lld, got %llu\n", + DL_GETDSIZE(&dl), letoh64(gh.gh_lba_end)); + return (1); + } + + if (letoh64(gh.gh_lba_start) >= letoh64(gh.gh_lba_end)) { + DPRINTF("gpt first usable LBA: expected < %llu, got %llu\n", + letoh64(gh.gh_lba_start), letoh64(gh.gh_lba_start)); + return (1); + } + + if (letoh64(gh.gh_part_lba) <= letoh64(gh.gh_lba_end) && + letoh64(gh.gh_part_lba) >= letoh64(gh.gh_lba_start)) { + DPRINTF("gpt partition table start lba: expected < %llu or " + "> %llu, got %llu\n", letoh64(gh.gh_lba_start), + letoh64(gh.gh_lba_end), letoh64(gh.gh_part_lba)); + return (1); + } + + partspersec = dl.d_secsize / letoh32(gh.gh_part_size); + partlastlba = letoh64(gh.gh_part_lba) + + ((letoh32(gh.gh_part_num) + partspersec - 1) / partspersec) - 1; + if (partlastlba <= letoh64(gh.gh_lba_end) && + partlastlba >= letoh64(gh.gh_lba_start)) { + DPRINTF("gpt partition table last LBA: expected < %llu or " + "> %llu, got %llu\n", letoh64(gh.gh_lba_start), + letoh64(gh.gh_lba_end), partlastlba); + return (1); + } + + /* + * Other possible paranoia checks: + * 1) partition table starts before primary gpt lba. + * 2) partition table extends into lowest partition. + * 3) alt partition table starts before gh_lba_end. + */ + return (0); +} + +int +GPT_get_partition_table(int fd, off_t where) +{ + ssize_t len; + off_t off; + int secs; + uint32_t checksum, partspersec; + + DPRINTF("gpt partition table being read from LBA %llu\n", + letoh64(gh.gh_part_lba)); + + partspersec = dl.d_secsize / letoh32(gh.gh_part_size); + if (partspersec * letoh32(gh.gh_part_size) != dl.d_secsize) { + DPRINTF("gpt partition table entry invalid size. %u\n", + letoh32(gh.gh_part_size)); + return (1); + } + secs = (letoh32(gh.gh_part_num) + partspersec - 1) / partspersec; + + memset(&gp, 0, sizeof(gp)); + + where *= dl.d_secsize; + off = lseek(fd, where, SEEK_SET); + if (off == -1) { + DPRINTF("seek to gpt partition table @ sector %llu failed\n", + (unsigned long long)where / dl.d_secsize); + return (1); + } + len = read(fd, &gp, secs * dl.d_secsize); + if (len == -1 || len != secs * dl.d_secsize) { + DPRINTF("gpt partition table read failed.\n"); + return (1); + } + + checksum = crc32((unsigned char *)&gp, letoh32(gh.gh_part_num) * + letoh32(gh.gh_part_size)); + if (checksum != letoh32(gh.gh_part_csum)) { + DPRINTF("gpt partition table checksum: expected %x, got %x\n", + checksum, letoh32(gh.gh_part_csum)); + return (1); + } + + return (0); +} + +int +GPT_get_gpt(void) +{ + int fd, privalid, altvalid; + + fd = DISK_open(disk.name, O_RDONLY); + + /* + * primary header && primary partition table || + * alt header && alt partition table + */ + privalid = GPT_get_header(fd, GPTSECTOR); + if (privalid == 0) + privalid = GPT_get_partition_table(fd, gh.gh_part_lba); + if (privalid == 0) { + close(fd); + return (0); + } + + altvalid = GPT_get_header(fd, DL_GETDSIZE(&dl) - 1); + if (altvalid == 0) + altvalid = GPT_get_partition_table(fd, gh.gh_part_lba); + if (altvalid == 0) { + close(fd); + return (0); + } + + close(fd); + + return (1); +} + +void +GPT_print(char *units) +{ + const int secsize = unit_types[SECTORS].conversion; + struct uuid guid; + char *guidstr = NULL; + double size; + int i, u, status; + + printf("Disk: %s ", disk.name); + + uuid_dec_le(&gh.gh_guid, &guid); + uuid_to_string(&guid, &guidstr, &status); + if (status == uuid_s_ok) + printf("%s ", guidstr); + else + printf(" "); + free(guidstr); + + u = unit_lookup(units); + size = ((double)disk.size * secsize) / unit_types[u].conversion; + printf("[%.0f ", size); + if (u == SECTORS && secsize != DEV_BSIZE) + printf("%d-byte ", secsize); + printf("%s]\n", unit_types[u].lname); + + GPT_print_parthdr(); + + for (i = 0; i < letoh32(gh.gh_part_num); i++) { + if (uuid_is_nil(&gp[i].gp_type, NULL)) + continue; + GPT_print_part(i, units); + } +} + +void +GPT_print_parthdr() +{ + printf(" First usable LBA: %llu Last usable LBA: %llu\n", + letoh64(gh.gh_lba_start), letoh64(gh.gh_lba_end)); + + printf(" #: uuid " + "lba size \n"); + printf(" type name\n"); + printf("----------------------------------------------------" + "-----------------\n"); +} + +void +GPT_print_part(int n, char *units) +{ + struct uuid guid; + const int secsize = unit_types[SECTORS].conversion; + struct gpt_partition *partn = &gp[n]; + char *guidstr = NULL; + double size; + int u, status; + + printf("%c%3d: ", (letoh64(partn->gp_attrs) & GPTDOSACTIVE)?'*':' ', n); + + uuid_dec_le(&partn->gp_guid, &guid); + uuid_to_string(&guid, &guidstr, &status); + if (status != uuid_s_ok) + printf(" "); + else + printf("%36s ", guidstr); + free(guidstr); + + printf("%12lld ", letoh64(partn->gp_lba_start)); + + u = unit_lookup(units); + size = letoh64(partn->gp_lba_end) - letoh64(partn->gp_lba_start) + 1; + size = (size * secsize) / unit_types[u].conversion; + printf("%12.0f%s\n", size, unit_types[u].abbr); + + uuid_dec_le(&partn->gp_type, &guid); + printf(" %-36s %-36s\n", PRT_uuid_to_type(&guid), + utf16le_to_string(partn->gp_name)); +} + int GPT_init(void) { @@ -83,6 +351,8 @@ GPT_init(void) uuid_enc_le(&gp[1].gp_guid, &guid); gp[1].gp_lba_start = gh.gh_lba_start; gp[1].gp_lba_end = htole64(letoh64(gh.gh_lba_start)+b_arg - 1); + memcpy(gp[1].gp_name, string_to_utf16le("EFI System Area"), + sizeof(gp[1].gp_name)); } #endif uuid_dec_be(gpt_uuid_openbsd, &guid); @@ -103,6 +373,9 @@ GPT_init(void) } #endif gp[3].gp_lba_end = gh.gh_lba_end; + memcpy(gp[3].gp_name, string_to_utf16le("OpenBSD Area"), + sizeof(gp[3].gp_name)); + gh.gh_part_csum = crc32((unsigned char *)&gp, sizeof(gp)); gh.gh_csum = crc32((unsigned char *)&gh, sizeof(gh)); diff --git a/sbin/fdisk/gpt.h b/sbin/fdisk/gpt.h index 2d4607c3667..1caca02305b 100644 --- a/sbin/fdisk/gpt.h +++ b/sbin/fdisk/gpt.h @@ -1,4 +1,4 @@ -/* $OpenBSD: gpt.h,v 1.1 2015/10/05 01:39:08 krw Exp $ */ +/* $OpenBSD: gpt.h,v 1.2 2015/10/26 15:08:26 krw Exp $ */ /* * Copyright (c) 2015 Markus Muller * Copyright (c) 2015 Kenneth R Westerback @@ -16,8 +16,15 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +int GPT_get_hdr(int, off_t); +int GPT_get_partition_table(int, off_t); +int GPT_get_gpt(void); int GPT_init(void); int GPT_write(int); +void GPT_print(char *); +void GPT_print_part(int, char *); +void GPT_print_parthdr(void); + extern struct gpt_header gh; extern struct gpt_partition gp[NGPTPARTITIONS]; diff --git a/sbin/fdisk/mbr.c b/sbin/fdisk/mbr.c index b9eb693a3d1..211ed3f5190 100644 --- a/sbin/fdisk/mbr.c +++ b/sbin/fdisk/mbr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mbr.c,v 1.55 2015/10/05 01:39:08 krw Exp $ */ +/* $OpenBSD: mbr.c,v 1.56 2015/10/26 15:08:26 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "disk.h" @@ -37,6 +38,33 @@ struct mbr initial_mbr; +int +MBR_protective_mbr(struct mbr *mbr) +{ + u_int64_t dsize; + int efi, found, i; + u_int32_t psize; + + found = efi = 0; + for (i = 0; i < NDOSPART; i++) { + if (mbr->part[i].id == DOSPTYP_UNUSED) + continue; + found++; + if (mbr->part[i].id != DOSPTYP_EFI) + continue; + dsize = DL_GETDSIZE(&dl); + psize = mbr->part[i].ns; + if (psize == (dsize - 1) || psize == UINT32_MAX) { + if (mbr->part[i].bs == 1) + efi++; + } + } + if (found == 1 && efi == 1) + return (0); + + return (1); +} + void MBR_init_GPT(struct mbr *mbr) { @@ -167,6 +195,8 @@ MBR_print(struct mbr *mbr, char *units) { int i; + DISK_printgeometry(NULL); + /* Header */ printf("Offset: %lld\t", (long long)mbr->offset); printf("Signature: 0x%X\n", (int)mbr->signature); diff --git a/sbin/fdisk/mbr.h b/sbin/fdisk/mbr.h index 294dea61114..0673f87fb45 100644 --- a/sbin/fdisk/mbr.h +++ b/sbin/fdisk/mbr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mbr.h,v 1.25 2015/10/05 01:39:08 krw Exp $ */ +/* $OpenBSD: mbr.h,v 1.26 2015/10/26 15:08:26 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -39,5 +39,6 @@ int MBR_write(int, off_t, struct dos_mbr *); void MBR_pcopy(struct mbr *); void MBR_zapgpt(int, struct dos_mbr *, uint64_t); void MBR_init_GPT(struct mbr *); +int MBR_protective_mbr(struct mbr *); #endif /* _MBR_H */ diff --git a/sbin/fdisk/misc.c b/sbin/fdisk/misc.c index e6416147c7d..cc95a29875e 100644 --- a/sbin/fdisk/misc.c +++ b/sbin/fdisk/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.53 2015/10/07 00:04:57 krw Exp $ */ +/* $OpenBSD: misc.c,v 1.54 2015/10/26 15:08:26 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -24,6 +24,7 @@ #include #include #include +#include #include "disk.h" #include "misc.h" @@ -59,19 +60,39 @@ unit_lookup(char *units) return (i); } +int +string_from_line(char *buf, size_t buflen) +{ + char *line; + size_t sz; + + line = fgetln(stdin, &sz); + if (line == NULL) + return (1); + + if (line[sz - 1] == '\n') + line[--sz] = '\0'; + + if (sz < buflen) { + memcpy(buf, line, sz); + buf[sz] = '\0'; + } else { + memcpy(buf, line, buflen - 1); + buf[buflen - 1] = '\0'; + } + + return (0); +} + int ask_cmd(char **cmd, char **args) { static char lbuf[100]; char *cp, *buf; - size_t lbuflen; /* Get input */ - if (fgets(lbuf, sizeof lbuf, stdin) == NULL) + if (string_from_line(lbuf, sizeof(lbuf))) errx(1, "eof"); - lbuflen = strlen(lbuf); - if (lbuflen > 0 && lbuf[lbuflen - 1] == '\n') - lbuf[lbuflen - 1] = '\0'; /* Parse input */ buf = lbuf; @@ -89,7 +110,6 @@ ask_num(const char *str, int dflt, int low, int high) { char lbuf[100]; const char *errstr; - size_t lbuflen; int num; if (dflt < low) @@ -100,13 +120,9 @@ ask_num(const char *str, int dflt, int low, int high) do { printf("%s [%d - %d]: [%d] ", str, low, high, dflt); - if (fgets(lbuf, sizeof lbuf, stdin) == NULL) + if (string_from_line(lbuf, sizeof(lbuf))) errx(1, "eof"); - lbuflen = strlen(lbuf); - if (lbuflen > 0 && lbuf[lbuflen - 1] == '\n') - lbuf[lbuflen - 1] = '\0'; - if (lbuf[0] == '\0') { num = dflt; errstr = NULL; @@ -121,36 +137,29 @@ ask_num(const char *str, int dflt, int low, int high) } int -ask_pid(int dflt, int low, int high) +ask_pid(int dflt, struct uuid *guid) { char lbuf[100], *cp; - size_t lbuflen; - int num = -1; - - if (low == 1) - low = 0; /* Show continguous range */ - - if (dflt < low) - dflt = low; - else if (dflt > high) - dflt = high; + int num = -1, status; do { - printf("Partition id ('0' to disable) [%X - %X]: [%X] ", low, - high, dflt); + printf("Partition id ('0' to disable) [01 - FF]: [%X] ", dflt); printf("(? for help) "); - if (fgets(lbuf, sizeof lbuf, stdin) == NULL) + if (string_from_line(lbuf, sizeof(lbuf))) errx(1, "eof"); - lbuflen = strlen(lbuf); - if (lbuflen > 0 && lbuf[lbuflen - 1] == '\n') - lbuf[lbuflen - 1] = '\0'; if (lbuf[0] == '?') { PRT_printall(); continue; } + if (guid) { + uuid_from_string(lbuf, guid, &status); + if (status == uuid_s_ok) + return (0x100); + } + /* Convert */ cp = lbuf; num = strtol(lbuf, &cp, 16); @@ -160,13 +169,13 @@ ask_pid(int dflt, int low, int high) num = dflt; if (*cp != '\0') { printf("'%s' is not a valid number.\n", lbuf); - num = low - 1; + num = -1; } else if (num == 0) { break; - } else if (num < low || num > high) { + } else if (num < 0 || num > 0xff) { printf("'%x' is out of range.\n", num); } - } while (num < low || num > high); + } while (num < 0 || num > 0xff); return (num); } @@ -215,13 +224,9 @@ getuint64(char *prompt, u_int64_t oval, u_int64_t maxval) do { printf("%s: [%llu] ", prompt, oval); - if (fgets(buf, sizeof(buf), stdin) == NULL) + if (string_from_line(buf, sizeof(buf))) errx(1, "eof"); - n = strlen(buf); - if (n > 0 && buf[n-1] == '\n') - buf[--n] = '\0'; - if (buf[0] == '\0') { return (oval); } else if (buf[0] == '*' && buf[1] == '\0') { @@ -229,6 +234,7 @@ getuint64(char *prompt, u_int64_t oval, u_int64_t maxval) } /* deal with units */ + n = strlen(buf); switch (tolower((unsigned char)buf[n-1])) { case 'c': unit = 'c'; @@ -318,28 +324,17 @@ getuint64(char *prompt, u_int64_t oval, u_int64_t maxval) char * ask_string(const char *prompt, const char *oval) { - static char buf[BUFSIZ]; - int n; + static char buf[37]; buf[0] = '\0'; - do { - printf("%s: [%s] ", prompt, oval ? oval : ""); - if (fgets(buf, sizeof(buf), stdin) == NULL) { - buf[0] = '\0'; - if (feof(stdin)) { - clearerr(stdin); - putchar('\n'); - return(NULL); - } - } - n = strlen(buf); - if (n > 0 && buf[n-1] == '\n') - buf[--n] = '\0'; - else if (oval != NULL && buf[0] == '\0') - strlcpy(buf, oval, sizeof(buf)); - } while (buf[0] == '?'); + printf("%s: [%s] ", prompt, oval ? oval : ""); + if (string_from_line(buf, sizeof(buf))) + errx(1, "eof"); - return(&buf[0]); + if (buf[0] == '\0' && oval) + strlcpy(buf, oval, sizeof(buf)); + + return(buf); } /* @@ -372,3 +367,37 @@ crc32(const u_char *buf, const u_int32_t size) return ~crc; } + +char * +utf16le_to_string(u_int16_t *utf) +{ + static char name[36]; + int i; + + for (i = 0; i < sizeof(name); i++) { + name[i] = letoh16(utf[i]) & 0x7F; + if (name[i] == '\0') + break; + } + if (i == sizeof(name)) + name[i - 1] = '\0'; + + return (name); +} + +u_int16_t * +string_to_utf16le(char *ch) +{ + static u_int16_t utf[36]; + int i; + + for (i = 0; i < sizeof(utf); i++) { + utf[i] = htole16((unsigned int)ch[i]); + if (utf[i] == 0) + break; + } + if (i == sizeof(utf)) + utf[i - 1] = 0; + + return (utf); +} diff --git a/sbin/fdisk/misc.h b/sbin/fdisk/misc.h index 04d95c5865d..263fbd2d5c5 100644 --- a/sbin/fdisk/misc.h +++ b/sbin/fdisk/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.30 2015/03/30 17:11:49 krw Exp $ */ +/* $OpenBSD: misc.h,v 1.31 2015/10/26 15:08:26 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -29,12 +29,15 @@ extern struct unit_type unit_types[]; /* Prototypes */ int unit_lookup(char *); +int string_from_line(char *, size_t); int ask_cmd(char **, char **); int ask_num(const char *, int, int, int); -int ask_pid(int, int, int); +int ask_pid(int, struct uuid *); char *ask_string(const char *, const char *); int ask_yn(const char *); u_int64_t getuint64(char *, u_int64_t, u_int64_t); u_int32_t crc32(const u_char *, const u_int32_t); +char *utf16le_to_string(u_int16_t *); +u_int16_t *string_to_utf16le(char *); #endif /* _MISC_H */ diff --git a/sbin/fdisk/part.c b/sbin/fdisk/part.c index 1ad2a85f5b9..04ce07a7d18 100644 --- a/sbin/fdisk/part.c +++ b/sbin/fdisk/part.c @@ -1,4 +1,4 @@ -/* $OpenBSD: part.c,v 1.72 2015/03/27 16:06:00 krw Exp $ */ +/* $OpenBSD: part.c,v 1.73 2015/10/26 15:08:26 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -20,7 +20,9 @@ #include #include #include +#include #include +#include #include "disk.h" #include "misc.h" @@ -31,39 +33,40 @@ int PRT_check_chs(struct prt *partn); static const struct part_type { int type; char sname[14]; + char guid[37]; } part_types[] = { - { 0x00, "unused "}, /* unused */ - { 0x01, "DOS FAT-12 "}, /* Primary DOS with 12 bit FAT */ + { 0x00, "unused ", "00000000-0000-0000-0000-000000000000" }, + { 0x01, "DOS FAT-12 ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, { 0x02, "XENIX / "}, /* XENIX / filesystem */ { 0x03, "XENIX /usr "}, /* XENIX /usr filesystem */ - { 0x04, "DOS FAT-16 "}, /* Primary DOS with 16 bit FAT */ + { 0x04, "DOS FAT-16 ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, { 0x05, "Extended DOS"}, /* Extended DOS */ - { 0x06, "DOS > 32MB "}, /* Primary 'big' DOS (> 32MB) */ - { 0x07, "NTFS "}, /* NTFS */ + { 0x06, "DOS > 32MB ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, + { 0x07, "NTFS ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, { 0x08, "AIX fs "}, /* AIX filesystem */ { 0x09, "AIX/Coherent"}, /* AIX boot partition or Coherent */ { 0x0A, "OS/2 Bootmgr"}, /* OS/2 Boot Manager or OPUS */ - { 0x0B, "Win95 FAT-32"}, /* Primary Win95 w/ 32-bit FAT */ - { 0x0C, "Win95 FAT32L"}, /* Primary Win95 w/ 32-bit FAT LBA-mapped */ - { 0x0E, "DOS FAT-16 "}, /* Primary DOS w/ 16-bit FAT, CHS-mapped */ + { 0x0B, "Win95 FAT-32", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, + { 0x0C, "Win95 FAT32L", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, + { 0x0E, "DOS FAT-16 ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, { 0x0F, "Extended LBA"}, /* Extended DOS LBA-mapped */ { 0x10, "OPUS "}, /* OPUS */ - { 0x11, "OS/2 hidden "}, /* OS/2 BM: hidden DOS 12-bit FAT */ + { 0x11, "OS/2 hidden ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, { 0x12, "Compaq Diag."}, /* Compaq Diagnostics */ - { 0x14, "OS/2 hidden "}, /* OS/2 BM: hidden DOS 16-bit FAT <32M or Novell DOS 7.0 bug */ - { 0x16, "OS/2 hidden "}, /* OS/2 BM: hidden DOS 16-bit FAT >=32M */ - { 0x17, "OS/2 hidden "}, /* OS/2 BM: hidden IFS */ + { 0x14, "OS/2 hidden ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, + { 0x16, "OS/2 hidden ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, + { 0x17, "OS/2 hidden ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, { 0x18, "AST swap "}, /* AST Windows swapfile */ { 0x19, "Willowtech "}, /* Willowtech Photon coS */ - { 0x1C, "ThinkPad Rec"}, /* IBM ThinkPad recovery partition */ - { 0x20, "Willowsoft "}, /* Willowsoft OFS1 */ + { 0x1C, "ThinkPad Rec", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, { 0x24, "NEC DOS "}, /* NEC DOS */ - { 0x27, "Win Recovery"}, /* Windows hidden Recovery Partition */ + { 0x27, "Win Recovery", "de94bba4-06d1-4d40-a16a-bfd50179d6ac" }, + { 0x20, "Willowsoft "}, /* Willowsoft OFS1 */ { 0x38, "Theos "}, /* Theos */ { 0x39, "Plan 9 "}, /* Plan 9 */ { 0x40, "VENIX 286 "}, /* VENIX 286 or LynxOS */ { 0x41, "Lin/Minux DR"}, /* Linux/MINIX (sharing disk with DRDOS) or Personal RISC boot */ - { 0x42, "LinuxSwap DR"}, /* SFS or Linux swap (sharing disk with DRDOS) */ + { 0x42, "LinuxSwap DR", "af9b60a0-1431-4f62-bc68-3311714a69ad" }, { 0x43, "Linux DR "}, /* Linux native (sharing disk with DRDOS) */ { 0x4D, "QNX 4.2 Pri "}, /* QNX 4.2 Primary */ { 0x4E, "QNX 4.2 Sec "}, /* QNX 4.2 Secondary */ @@ -86,30 +89,31 @@ static const struct part_type { { 0x69, "Novell "}, /* Novell */ { 0x70, "DiskSecure "}, /* DiskSecure Multi-Boot */ { 0x75, "PCIX "}, /* PCIX */ + { 0x7f, "ChromeKernel", "fe3a2a5d-4f32-41a7-b725-accc3285a309" }, { 0x80, "Minix (old) "}, /* Minix 1.1 ... 1.4a */ { 0x81, "Minix (new) "}, /* Minix 1.4b ... 1.5.10 */ - { 0x82, "Linux swap "}, /* Linux swap */ - { 0x83, "Linux files*"}, /* Linux filesystem */ + { 0x82, "Linux swap ", "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f" }, + { 0x83, "Linux files*", "0fc63daf-8483-4772-8e79-3d69d8477de4" }, { 0x84, "OS/2 hidden "}, /* OS/2 hidden C: drive */ { 0x85, "Linux ext. "}, /* Linux extended */ { 0x86, "NT FAT VS "}, /* NT FAT volume set */ { 0x87, "NTFS VS "}, /* NTFS volume set or HPFS mirrored */ - { 0x8E, "Linux LVM "}, /* Linux LVM */ + { 0x8E, "Linux LVM ", "e6d6d379-f507-44c2-a23c-238f2a3df928" }, { 0x93, "Amoeba FS "}, /* Amoeba filesystem */ { 0x94, "Amoeba BBT "}, /* Amoeba bad block table */ { 0x99, "Mylex "}, /* Mylex EISA SCSI */ { 0x9F, "BSDI "}, /* BSDI BSD/OS */ { 0xA0, "NotebookSave"}, /* Phoenix NoteBIOS save-to-disk */ - { 0xA5, "FreeBSD "}, /* FreeBSD */ - { 0xA6, "OpenBSD "}, /* OpenBSD */ + { 0xA5, "FreeBSD ", "516e7cb4-6ecf-11d6-8ff8-00022d09712b" }, + { 0xA6, "OpenBSD ", "824cc7a0-36a8-11e3-890a-952519ad3f61" }, { 0xA7, "NEXTSTEP "}, /* NEXTSTEP */ - { 0xA8, "MacOS X "}, /* MacOS X main partition */ - { 0xA9, "NetBSD "}, /* NetBSD */ - { 0xAB, "MacOS X boot"}, /* MacOS X boot partition */ - { 0xAF, "MacOS X HFS+"}, /* MacOS X HFS+ partition */ + { 0xA8, "MacOS X ", "55465300-0000-11aa-aa11-00306543ecac" }, + { 0xA9, "NetBSD ", "516e7cb4-6ecf-11d6-8ff8-00022d09712b" }, + { 0xAB, "MacOS X boot", "426f6f74-0000-11aa-aa11-00306543ecac" }, + { 0xAF, "MacOS X HFS+", "48465300-0000-11aa-aa11-00306543ecac" }, { 0xB7, "BSDI filesy*"}, /* BSDI BSD/386 filesystem */ { 0xB8, "BSDI swap "}, /* BSDI BSD/386 swap */ - { 0xBF, "Solaris "}, /* Solaris */ + { 0xBF, "Solaris ", "6a85cf4d-1dd2-11b2-99a6-080020736631" }, { 0xC0, "CTOS "}, /* CTOS */ { 0xC1, "DRDOSs FAT12"}, /* DRDOS/sec (FAT-12) */ { 0xC4, "DRDOSs < 32M"}, /* DRDOS/sec (FAT-16, < 32M) */ @@ -120,9 +124,9 @@ static const struct part_type { { 0xE1, "SpeedStor "}, /* DOS access or SpeedStor 12-bit FAT extended partition */ { 0xE3, "SpeedStor "}, /* DOS R/O or SpeedStor or Storage Dimensions */ { 0xE4, "SpeedStor "}, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */ - { 0xEB, "BeOS/i386 "}, /* BeOS for Intel */ + { 0xEB, "BeOS/i386 ", "42465331-3ba3-10f1-802a-4861696b7521" }, { 0xEE, "EFI GPT "}, /* EFI Protective Partition */ - { 0xEF, "EFI Sys "}, /* EFI System Partition */ + { 0xEF, "EFI Sys ", "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" }, { 0xF1, "SpeedStor "}, /* SpeedStor or Storage Dimensions */ { 0xF2, "DOS 3.3+ Sec"}, /* DOS 3.3+ Secondary */ { 0xF4, "SpeedStor "}, /* SpeedStor >1024 cyl. or LANstep or IBM PS/2 IML */ @@ -268,6 +272,7 @@ PRT_make(struct prt *partn, off_t offset, off_t reloff, void PRT_print(int num, struct prt *partn, char *units) { + const int secsize = unit_types[SECTORS].conversion; double size; int i; @@ -281,8 +286,7 @@ PRT_print(int num, struct prt *partn, char *units) printf("---------------------------------------" "----------------------------------------\n"); } else { - size = ((double)partn->ns * unit_types[SECTORS].conversion) / - unit_types[i].conversion; + size = ((double)partn->ns * secsize) / unit_types[i].conversion; printf("%c%1d: %.2X %6u %3u %3u - %6u %3u %3u " "[%12llu:%12.0f%s] %s\n", (partn->flag == DOSACTIVE)?'*':' ', @@ -369,3 +373,58 @@ PRT_fix_CHS(struct prt *part) part->ehead = head; part->esect = sect; } + +char * +PRT_uuid_to_type(struct uuid *uuid) +{ + static char partition_type[37]; /* Room for a GUID if needed. */ + char *uuidstr = NULL; + int i, entries, status; + + memset(partition_type, 0, sizeof(partition_type)); + + uuid_to_string(uuid, &uuidstr, &status); + if (status != uuid_s_ok) + goto done; + + entries = sizeof(part_types) / sizeof(struct part_type); + + for (i = 0; i < entries; i++) { + if (memcmp(part_types[i].guid, uuidstr, + sizeof(part_types[i].guid)) == 0) + break; + } + + if (i < entries) + strlcpy(partition_type, part_types[i].sname, + sizeof(partition_type)); + else + strlcpy(partition_type, uuidstr, sizeof(partition_type)); + +done: + free(uuidstr); + + return (partition_type); +} + +struct uuid * +PRT_type_to_uuid(int type) +{ + static struct uuid guid; + int i, entries, status = uuid_s_ok; + + memset(&guid, 0, sizeof(guid)); + + entries = sizeof(part_types) / sizeof(struct part_type); + + for (i = 0; i < entries; i++) { + if (part_types[i].type == type) + break; + } + if (i < entries) + uuid_from_string(part_types[i].guid, &guid, &status); + if (i == entries || status != uuid_s_ok) + uuid_from_string(part_types[0].guid, &guid, &status); + + return (&guid); +} diff --git a/sbin/fdisk/part.h b/sbin/fdisk/part.h index 645c1c8c2df..c1b2299f0ed 100644 --- a/sbin/fdisk/part.h +++ b/sbin/fdisk/part.h @@ -1,4 +1,4 @@ -/* $OpenBSD: part.h,v 1.19 2015/03/26 14:08:12 krw Exp $ */ +/* $OpenBSD: part.h,v 1.20 2015/10/26 15:08:26 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -34,6 +34,8 @@ void PRT_parse(struct dos_partition *, off_t, off_t, struct prt *); void PRT_make(struct prt *, off_t, off_t, struct dos_partition *); void PRT_print(int, struct prt *, char *); +char *PRT_uuid_to_type(struct uuid *); +struct uuid *PRT_type_to_uuid(int); /* This does CHS -> bs/ns */ void PRT_fix_BN(struct prt *, int); diff --git a/sbin/fdisk/user.c b/sbin/fdisk/user.c index 65d995e9b4e..40d40a73253 100644 --- a/sbin/fdisk/user.c +++ b/sbin/fdisk/user.c @@ -1,4 +1,4 @@ -/* $OpenBSD: user.c,v 1.44 2015/04/02 18:00:55 krw Exp $ */ +/* $OpenBSD: user.c,v 1.45 2015/10/26 15:08:26 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -30,25 +30,26 @@ #include "misc.h" #include "cmd.h" #include "user.h" +#include "gpt.h" /* Our command table */ struct cmd cmd_table[] = { - {"help", Xhelp, "Command help list"}, - {"manual", Xmanual, "Show entire OpenBSD man page for fdisk"}, - {"reinit", Xreinit, "Re-initialize loaded MBR (to defaults)"}, - {"setpid", Xsetpid, "Set the identifier of a given table entry"}, - {"disk", Xdisk, "Edit current drive stats"}, - {"edit", Xedit, "Edit given table entry"}, - {"flag", Xflag, "Flag given table entry as bootable"}, - {"update", Xupdate, "Update machine code in loaded MBR"}, - {"select", Xselect, "Select extended partition table entry MBR"}, - {"swap", Xswap, "Swap two partition entries"}, - {"print", Xprint, "Print loaded MBR partition table"}, - {"write", Xwrite, "Write loaded MBR to disk"}, - {"exit", Xexit, "Exit edit of current MBR, without saving changes"}, - {"quit", Xquit, "Quit edit of current MBR, saving current changes"}, - {"abort", Xabort, "Abort program without saving current changes"}, - {NULL, NULL, NULL} + {"help", 1, Xhelp, "Command help list"}, + {"manual", 1, Xmanual, "Show entire OpenBSD man page for fdisk"}, + {"reinit", 1, Xreinit, "Re-initialize loaded MBR (to defaults)"}, + {"setpid", 1, Xsetpid, "Set the identifier of a given table entry"}, + {"disk", 0, Xdisk, "Edit current drive stats"}, + {"edit", 1, Xedit, "Edit given table entry"}, + {"flag", 1, Xflag, "Flag given table entry as bootable"}, + {"update", 0, Xupdate, "Update machine code in loaded MBR"}, + {"select", 0, Xselect, "Select extended partition table entry MBR"}, + {"swap", 1, Xswap, "Swap two partition entries"}, + {"print", 1, Xprint, "Print loaded MBR partition table"}, + {"write", 1, Xwrite, "Write loaded MBR to disk"}, + {"exit", 1, Xexit, "Exit edit of current MBR, without saving changes"}, + {"quit", 1, Xquit, "Quit edit of current MBR, saving current changes"}, + {"abort", 1, Xabort, "Abort program without saving current changes"}, + {NULL, 0, NULL, NULL} }; @@ -96,7 +97,8 @@ again: i = 0; /* Check for valid command */ - if (cmd_table[i].cmd == NULL) { + if ((cmd_table[i].cmd == NULL) || (letoh64(gh.gh_sig) == + GPTSIGNATURE && cmd_table[i].gpt == 0)) { printf("Invalid command '%s'. Try 'help'.\n", cmd); continue; } @@ -141,13 +143,17 @@ USER_print_disk(void) fd = DISK_open(disk.name, O_RDONLY); offset = firstoff = 0; - DISK_printgeometry(NULL); - do { error = MBR_read(fd, offset, &dos_mbr); if (error == -1) break; MBR_parse(&dos_mbr, offset, firstoff, &mbr); + if (offset == 0 && MBR_protective_mbr(&mbr) == 0) { + if (letoh64(gh.gh_sig) == GPTSIGNATURE) { + GPT_print("s"); + break; + } + } MBR_print(&mbr, NULL); -- 2.20.1