Add -A option to "safely" initialize a GPT without removing
authorkrw <krw@openbsd.org>
Mon, 21 Jun 2021 02:05:30 +0000 (02:05 +0000)
committerkrw <krw@openbsd.org>
Mon, 21 Jun 2021 02:05:30 +0000 (02:05 +0000)
special boot partitions needed by some hardware. Make it
difficult to add, delete or modify those partitions with 'fdisk
-e'.

Trim back and correct syntax in usage(). Whack at man page
verbiage.

Suggestions and ok deraadt@

sbin/fdisk/cmd.c
sbin/fdisk/fdisk.8
sbin/fdisk/fdisk.c
sbin/fdisk/gpt.c
sbin/fdisk/part.c
sbin/fdisk/part.h

index fe7c21f..777e48b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cmd.c,v 1.116 2021/06/16 15:40:47 krw Exp $   */
+/*     $OpenBSD: cmd.c,v 1.117 2021/06/21 02:05:30 krw Exp $   */
 
 /*
  * Copyright (c) 1997 Tobias Weingartner
@@ -307,12 +307,25 @@ gsetpid(int pn)
        GPT_print_parthdr(TERSE);
        GPT_print_part(pn, "s", TERSE);
 
+       if (PRT_protected_guid(&gg->gp_type)) {
+               uuid_dec_le(&gg->gp_type, &guid);
+               printf("can't edit partition type %s\n",
+                   PRT_uuid_to_typename(&guid));
+               goto done;
+       }
+
        /* Ask for partition type or GUID. */
        uuid_dec_le(&gg->gp_type, &guid);
        num = ask_pid(PRT_uuid_to_type(&guid), &guid);
        if (num <= 0xff)
                guid = *(PRT_type_to_uuid(num));
        uuid_enc_le(&gg->gp_type, &guid);
+       if (PRT_protected_guid(&gg->gp_type)) {
+               uuid_dec_le(&gg->gp_type, &guid);
+               printf("can't change partition type to %s\n",
+                   PRT_uuid_to_typename(&guid));
+               goto done;
+       }
 
        if (uuid_is_nil(&gg->gp_guid, NULL)) {
                uuid_create(&guid, &status);
index 18f624c..94afcd3 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: fdisk.8,v 1.100 2021/06/20 19:40:06 jmc Exp $
+.\"    $OpenBSD: fdisk.8,v 1.101 2021/06/21 02:05:30 krw Exp $
 .\"
 .\"
 .\" Copyright (c) 1997 Tobias Weingartner
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: June 20 2021 $
+.Dd $Mdocdate: June 21 2021 $
 .Dt FDISK 8
 .Os
 .Sh NAME
 .Nd partition table maintenance program
 .Sh SYNOPSIS
 .Nm fdisk
-.Op Fl egvy
-.Op Fl i | u
+.Op Fl ey
+.Op Fl i Oo Fl g Oc | Fl u | Fl A | Fl v
 .Op Fl b Ar blocks Ns Op @ Ns Ar offset Ns Op : Ns Ar type
-.Op Fl c Ar cylinders Fl h Ar heads Fl s Ar sectors
+.Op Fl l Ar blocks | Fl c Ar cylinders Fl h Ar heads Fl s Ar sectors
 .Op Fl f Ar mbrfile
-.Op Fl l Ar blocks
 .Ar disk
 .Sh DESCRIPTION
 .Nm fdisk
@@ -54,17 +53,33 @@ at install time.
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
+.It Fl A
+Allocates the largest chunks of free space in an existing GPT to the
+.Ox
+partition
+and the optional
+.Fl b
+partition.
+The free space is maximized by deleting
+all existing partitions except the boot partitions
+.Sq APFS ISC ,
+.Sq APFS ,
+.Sq APFS Recovry ,
+.Sq HiFive FSBL
+and
+.Sq HiFive BBL .
 .It Fl b Ar blocks Ns Op @ Ns Ar offset Ns Op : Ns Ar type
 A special boot partition of the specified size, offset and type will be written to disk.
 The
 .Ox
 partition will follow the boot partition and use the remaining space on the disk.
 .Pp
-Only valid with
-.Fl i .
-If
-.Fl g
-is specified only the
+Can only be used when initializing a disk with
+.Fl i Op Fl g
+or
+.Fl A .
+If a GPT is being initialized
+only the
 .Ar blocks
 value will be used, with the boot partition being placed at the first available LBA and
 given the type EFI SYS.
@@ -85,11 +100,6 @@ or values that
 .Em /boot
 has passed to the kernel.
 .Pp
-Only one of
-.Fl chs
-or
-.Fl l
-can be specified.
 .It Fl e
 Use the
 .Nm
@@ -108,8 +118,6 @@ The default GPT will have a single
 partition containing all available space not allocated by a
 .Fl b
 specification.
-Only valid with
-.Fl i .
 .It Fl i
 Requests that the partition table data be re-initialized.
 In this mode,
@@ -129,21 +137,9 @@ In the default template, MBR partition number 3 will be configured as an
 MBR partition containing all available space not allocated by a
 .Fl b
 specification.
-.Pp
-Only one of
-.Fl i
-or
-.Fl u
-can be specified.
 .It Fl l Ar blocks
 Specify the number of blocks in the disk, and force the MBR to be in LBA
 mode only.
-.Pp
-Only one of
-.Fl chs
-or
-.Fl l
-can be specified.
 .It Fl u
 Update MBR bootcode, preserving existing MBR partition table.
 The MBR bootcode extends from offset 0x000 to the start of the MBR partition
@@ -155,16 +151,9 @@ This is useful for writing new MBR bootcode onto an existing drive, and is
 equivalent to the DOS command
 .Dq FDISK /MBR .
 Note that this option will overwrite the NT disk signature, if present.
-.Pp
-Only one of
-.Fl i
-or
-.Fl u
-can be specified.
 .It Fl v
 Print the contents of the MBR, the Primary GPT and the Secondary GPT.
 Also print more detailed GPT header and partition entry information.
-Cannot be used with
 .Fl i ,
 .Fl u ,
 or
index 27d9cc1..12c042f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: fdisk.c,v 1.109 2021/06/20 18:44:19 krw Exp $ */
+/*     $OpenBSD: fdisk.c,v 1.110 2021/06/21 02:05:30 krw Exp $ */
 
 /*
  * Copyright (c) 1997 Tobias Weingartner
@@ -43,7 +43,7 @@ static unsigned char builtin_mbr[] = {
 
 uint32_t b_sectors, b_offset;
 uint8_t b_type;
-int y_flag;
+int    A_flag, y_flag;
 
 static void
 usage(void)
@@ -51,19 +51,8 @@ usage(void)
        extern char * __progname;
 
        fprintf(stderr, "usage: %s "
-           "[-egvy] [-i|-u] [-b #] [-c # -h # -s #] "
-           "[-f mbrfile] [-l # ] disk\n"
-           "\t-b: specify special boot partition block count; requires -i\n"
-           "\t-chs: specify disk geometry; all three must be specified\n"
-           "\t-e: interactively edit MBR or GPT\n"
-           "\t-f: specify non-standard MBR template\n"
-           "\t-g: initialize disk with GPT; requires -i\n"
-           "\t-i: initialize disk with MBR unless -g is also specified\n"
-           "\t-l: specify LBA block count; cannot be used with -chs\n"
-           "\t-u: update MBR code; preserve partition table\n"
-           "\t-v: print the MBR, the Primary GPT and the Secondary GPT\n"
-           "\t-y: do not ask questions\n"
-           "`disk' may be of the forms: sd0 or /dev/rsd0c.\n",
+           "[-evy] [-i [-g] | -u | -A ] [-b blocks[@offset[:type]]]\n"
+           "\t[-l blocks | -c cylinders -h heads -s sectors] [-f mbrfile] disk\n",
            __progname);
        exit(1);
 }
@@ -86,10 +75,13 @@ main(int argc, char *argv[])
        struct dos_mbr dos_mbr;
        struct mbr mbr;
 
-       while ((ch = getopt(argc, argv, "iegpuvf:c:h:s:l:b:y")) != -1) {
+       while ((ch = getopt(argc, argv, "Aiegpuvf:c:h:s:l:b:y")) != -1) {
                const char *errstr;
 
                switch(ch) {
+               case 'A':
+                       A_flag = 1;
+                       break;
                case 'i':
                        i_flag = 1;
                        break;
@@ -155,13 +147,14 @@ main(int argc, char *argv[])
 
        /* Argument checking */
        if (argc != 1 || (i_flag && u_flag) ||
-           (i_flag == 0 && (b_sectors || g_flag)) ||
+           (i_flag == 0 && g_flag) ||
+           (b_sectors && !(i_flag || A_flag)) ||
            ((c_arg | h_arg | s_arg) && !(c_arg && h_arg && s_arg)) ||
            ((c_arg | h_arg | s_arg) && l_arg))
                usage();
 
        disk.name = argv[0];
-       DISK_open(i_flag || u_flag || e_flag);
+       DISK_open(A_flag || i_flag || u_flag || e_flag);
 
        /* "proc exec" for man page display */
        if (pledge("stdio rpath wpath disklabel proc exec", NULL) == -1)
@@ -177,7 +170,7 @@ main(int argc, char *argv[])
        if (efi != -1)
                GPT_read(ANYGPT);
 
-       if (!(i_flag || u_flag || e_flag)) {
+       if (!(A_flag || i_flag || u_flag || e_flag)) {
                if (pledge("stdio", NULL) == -1)
                        err(1, "pledge");
                USER_print_disk(verbosity);
@@ -206,7 +199,15 @@ main(int argc, char *argv[])
        MBR_parse(&dos_mbr, 0, 0, &initial_mbr);
 
        query = NULL;
-       if (i_flag) {
+       if (A_flag) {
+               if (letoh64(gh.gh_sig) != GPTSIGNATURE)
+                       errx(1, "-A requires a valid GPT");
+               else {
+                       MBR_init_GPT(&initial_mbr);
+                       GPT_init();
+                       query = "Do you wish to write new GPT?";
+               }
+       } else if (i_flag) {
                if (g_flag) {
                        MBR_init_GPT(&initial_mbr);
                        GPT_init();
index 79c9df0..a446ef4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: gpt.c,v 1.31 2021/06/20 18:44:19 krw Exp $    */
+/*     $OpenBSD: gpt.c,v 1.32 2021/06/21 02:05:30 krw Exp $    */
 /*
  * Copyright (c) 2015 Markus Muller <mmu@grummel.net>
  * Copyright (c) 2015 Kenneth R Westerback <krw@openbsd.org>
@@ -417,13 +417,22 @@ int
 init_gp(void)
 {
        extern uint32_t b_sectors;
+       extern int A_flag;
        const uint8_t gpt_uuid_efi_system[] = GPT_UUID_EFI_SYSTEM;
        const uint8_t gpt_uuid_openbsd[] = GPT_UUID_OPENBSD;
        struct gpt_partition oldgp[NGPTPARTITIONS];
-       int rslt;
+       int pn, rslt;
 
        memcpy(&oldgp, &gp, sizeof(oldgp));
-       memset(&gp, 0, sizeof(gp));
+       if (A_flag == 0)
+               memset(&gp, 0, sizeof(gp));
+       else {
+               for (pn = 0; pn < NGPTPARTITIONS; pn++) {
+                       if (PRT_protected_guid(&gp[pn].gp_type))
+                               continue;
+                       memset(&gp[pn], 0, sizeof(gp[pn]));
+               }
+       }
 
        rslt = 0;
        if (b_sectors > 0) {
index 87cdff6..ac1d2ff 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: part.c,v 1.85 2021/06/13 23:53:51 krw Exp $   */
+/*     $OpenBSD: part.c,v 1.86 2021/06/21 02:05:30 krw Exp $   */
 
 /*
  * Copyright (c) 1997 Tobias Weingartner
@@ -142,6 +142,47 @@ static const struct part_type {
        { 0xFF, "Xenix BBT   "},   /* Xenix Bad Block Table */
 };
 
+static const struct protected_guid {
+       char    guid[UUID_STR_LEN + 1];
+} protected_guid[] = {
+       { "7c3457ef-0000-11aa-aa11-00306543ecac" },     /* APFS         */
+       { "69646961-6700-11aa-aa11-00306543ecac" },     /* APFS ISC     */
+       { "52637672-7900-11aa-aa11-00306543ecac" },     /* APFS Recovry */
+       { "5b193300-fc78-40cd-8002-e86c45580b47" },     /* HiFive FSBL  */
+       { "2e54b353-1271-4842-806f-e436d6af6985" },     /* HiFive BBL   */
+};
+
+#define        nitems(_a)      ((sizeof(_a)) / sizeof((_a)[0]))
+
+int
+PRT_protected_guid(struct uuid *leuuid)
+{
+       struct uuid      uuid;
+       char            *str = NULL;
+       int              rslt;
+       unsigned int     i;
+       uint32_t         status;
+
+       uuid_dec_le(leuuid, &uuid);
+       uuid_to_string(&uuid, &str, &status);
+       if (status != uuid_s_ok) {
+               rslt = 1;
+               goto done;
+       }
+
+       rslt = 0;
+       for(i = 0; i < nitems(protected_guid); i++) {
+               if (strncmp(str, protected_guid[i].guid, UUID_STR_LEN) == 0) {
+                       rslt = 1;
+                       break;
+               }
+       }
+
+ done:
+       free(str);
+       return rslt;
+}
+
 void
 PRT_printall(void)
 {
index 8660c76..8526850 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: part.h,v 1.23 2021/06/10 16:09:17 krw Exp $   */
+/*     $OpenBSD: part.h,v 1.24 2021/06/21 02:05:30 krw Exp $   */
 
 /*
  * Copyright (c) 1997 Tobias Weingartner
@@ -36,6 +36,7 @@ void PRT_print(int, struct prt *, char *);
 char *PRT_uuid_to_typename(struct uuid *);
 int PRT_uuid_to_type(struct uuid *);
 struct uuid *PRT_type_to_uuid(int);
+int PRT_protected_guid(struct uuid *);
 
 /* This does CHS -> bs/ns */
 void PRT_fix_BN(struct prt *, int);