Add GPT editing. Based on GSOC 2014 work by Markus Muller.
authorkrw <krw@openbsd.org>
Mon, 26 Oct 2015 15:08:26 +0000 (15:08 +0000)
committerkrw <krw@openbsd.org>
Mon, 26 Oct 2015 15:08:26 +0000 (15:08 +0000)
12 files changed:
sbin/fdisk/cmd.c
sbin/fdisk/cmd.h
sbin/fdisk/fdisk.c
sbin/fdisk/gpt.c
sbin/fdisk/gpt.h
sbin/fdisk/mbr.c
sbin/fdisk/mbr.h
sbin/fdisk/misc.c
sbin/fdisk/misc.h
sbin/fdisk/part.c
sbin/fdisk/part.h
sbin/fdisk/user.c

index 19b5e2f..6d44501 100644 (file)
@@ -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 <sys/param.h>
 #include <sys/types.h>
 #include <sys/fcntl.h>
 #include <sys/disklabel.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <unistd.h>
+#include <uuid.h>
 
 #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);
index 9d478b6..af3e767 100644 (file)
@@ -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;
 };
index f1605c2..450d41e 100644 (file)
@@ -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);
index 698f887..7f37628 100644 (file)
@@ -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 <mmu@grummel.net>
  * Copyright (c) 2015 Kenneth R Westerback <krw@openbsd.org>
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/disklabel.h>
 #include <sys/dkio.h>
+#include <sys/fcntl.h>
 #include <sys/ioctl.h>
+#include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #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("<invalid header guid> ");
+       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("<invalid partition guid>             ");
+       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));
 
index 2d4607c..1caca02 100644 (file)
@@ -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 <mmu@grummel.net>
  * Copyright (c) 2015 Kenneth R Westerback <krw@openbsd.org>
  * 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];
index b9eb693..211ed3f 100644 (file)
@@ -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 <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <memory.h>
 
 #include "disk.h"
 
 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);
index 294dea6..0673f87 100644 (file)
@@ -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 */
index e641614..cc95a29 100644 (file)
@@ -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 <string.h>
 #include <err.h>
 #include <errno.h>
+#include <uuid.h>
 
 #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);
+}
index 04d95c5..263fbd2 100644 (file)
@@ -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 */
index 1ad2a85..04ce07a 100644 (file)
@@ -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 <sys/disklabel.h>
 #include <err.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <uuid.h>
 
 #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);
+}
index 645c1c8..c1b2299 100644 (file)
@@ -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);
index 65d995e..40d40a7 100644 (file)
@@ -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
 #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);