From 95e8765c866608e2321b2ad4f5b0c7eba30d19c2 Mon Sep 17 00:00:00 2001 From: krw Date: Mon, 21 Jun 2021 02:05:30 +0000 Subject: [PATCH] Add -A option to "safely" initialize a GPT without removing 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 | 15 ++++++++++- sbin/fdisk/fdisk.8 | 63 +++++++++++++++++++--------------------------- sbin/fdisk/fdisk.c | 41 +++++++++++++++--------------- sbin/fdisk/gpt.c | 15 ++++++++--- sbin/fdisk/part.c | 43 ++++++++++++++++++++++++++++++- sbin/fdisk/part.h | 3 ++- 6 files changed, 117 insertions(+), 63 deletions(-) diff --git a/sbin/fdisk/cmd.c b/sbin/fdisk/cmd.c index fe7c21f871d..777e48bea71 100644 --- a/sbin/fdisk/cmd.c +++ b/sbin/fdisk/cmd.c @@ -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); diff --git a/sbin/fdisk/fdisk.8 b/sbin/fdisk/fdisk.8 index 18f624c25ff..94afcd3e923 100644 --- a/sbin/fdisk/fdisk.8 +++ b/sbin/fdisk/fdisk.8 @@ -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 @@ -23,12 +23,11 @@ .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 diff --git a/sbin/fdisk/fdisk.c b/sbin/fdisk/fdisk.c index 27d9cc1e933..12c042f18a5 100644 --- a/sbin/fdisk/fdisk.c +++ b/sbin/fdisk/fdisk.c @@ -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(); diff --git a/sbin/fdisk/gpt.c b/sbin/fdisk/gpt.c index 79c9df07ae5..a446ef437e6 100644 --- a/sbin/fdisk/gpt.c +++ b/sbin/fdisk/gpt.c @@ -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 * Copyright (c) 2015 Kenneth R Westerback @@ -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) { diff --git a/sbin/fdisk/part.c b/sbin/fdisk/part.c index 87cdff63cab..ac1d2ff8606 100644 --- a/sbin/fdisk/part.c +++ b/sbin/fdisk/part.c @@ -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) { diff --git a/sbin/fdisk/part.h b/sbin/fdisk/part.h index 8660c763448..8526850a484 100644 --- a/sbin/fdisk/part.h +++ b/sbin/fdisk/part.h @@ -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); -- 2.20.1