summaryrefslogtreecommitdiff
path: root/usr/src/cmd/fdisk/fdisk.c
diff options
context:
space:
mode:
authorAndy Fiddaman <omnios@citrus-it.co.uk>2018-02-11 14:39:52 +0000
committerDan McDonald <danmcd@joyent.com>2018-03-29 21:17:56 -0400
commit7e934d3acc051b7ee3ef0d11571fd1225800a607 (patch)
treed4046ded552b2ec9d639de9816f1811d1f6a073d /usr/src/cmd/fdisk/fdisk.c
parentf6eb544affab78a978fdf94368d923e79e7a045b (diff)
downloadillumos-joyent-7e934d3acc051b7ee3ef0d11571fd1225800a607.tar.gz
9067 Support PMBR customisation with EFI label
9116 fdisk limits heads to 254 (mostly) Reviewed by: Toomas Soome <tsoome@me.com> Reviewed by: Jorge Schrauwen <sjorge@blackdot.be> Reviewed by: Dominik Hassler <hadfl@omniosce.org> Approved by: Robert Mustacchi <rm@joyent.com>
Diffstat (limited to 'usr/src/cmd/fdisk/fdisk.c')
-rw-r--r--usr/src/cmd/fdisk/fdisk.c128
1 files changed, 86 insertions, 42 deletions
diff --git a/usr/src/cmd/fdisk/fdisk.c b/usr/src/cmd/fdisk/fdisk.c
index efd7313e7c..466a608bc2 100644
--- a/usr/src/cmd/fdisk/fdisk.c
+++ b/usr/src/cmd/fdisk/fdisk.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
*/
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
@@ -87,20 +88,6 @@
#define DEFAULT_PATH "/dev/rdsk/"
-/* XXX - should be in fdisk.h, used by sd as well */
-
-/*
- * the MAX values are the maximum usable values for BIOS chs values
- * The MAX_CYL value of 1022 is the maximum usable value
- * the value of 1023 is a fence value,
- * indicating no CHS geometry exists for the corresponding LBA value.
- * HEAD range [ 0 .. MAX_HEAD ], so number of heads is (MAX_HEAD + 1)
- * SECT range [ 1 .. MAX_SECT ], so number of sectors is (MAX_SECT)
- */
-#define MAX_SECT (63)
-#define MAX_CYL (1022)
-#define MAX_HEAD (254)
-
#define DK_MAX_2TB UINT32_MAX /* Max # of sectors in 2TB */
/* for clear_vtoc() */
@@ -159,9 +146,10 @@ static char Usage[] = "Usage: fdisk\n"
"[ -A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n"
"[ -b masterboot ]\n"
"[ -D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n"
+"[ -E [slot:active] ]\n"
"[ -F fdisk_file ] [ -h ] [ -o offset ] [ -P fill_patt ] [ -s size ]\n"
"[ -S geom_file ] [ [ -v ] -W { creat_fdisk_file | - } ]\n"
-"[ -w | r | d | n | I | B | E | g | G | R | t | T ] rdevice";
+"[ -w | r | d | n | I | B | g | G | R | t | T ] rdevice";
static char Usage1[] = " Partition options:\n"
" -A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n"
@@ -180,9 +168,10 @@ static char Usage1[] = " Partition options:\n"
" -b master_boot\n"
" Use master_boot as the master boot file.\n"
" -B Create one Solaris partition that uses the entire disk.\n"
-" -E Create one EFI partition that uses the entire disk.\n"
" -D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n"
" Delete a partition. See attribute definitions for -A.\n"
+" -E [slot:active]\n"
+" Create an EFI partition that uses the entire disk.\n"
" -F fdisk_file\n"
" Use fdisk_file to initialize on-line fdisk table.\n"
" -I Forego device checks. Generate a file image of what would go\n"
@@ -303,6 +292,8 @@ static struct mboot BootCod; /* buffer for master boot record */
static int io_wholedisk = 0; /* use whole disk for Solaris (-B) */
static int io_EFIdisk = 0; /* use whole disk for EFI (-E) */
+static int io_EFIslot = 0; /* slot in which to place EFI entry */
+static int io_EFIactive = 0; /* mark EFI entry as active */
static int io_debug = 0; /* activate verbose mode (-d) */
static int io_image = 0; /* create image using geometry (-I) */
@@ -687,6 +678,7 @@ static void clear_vtoc(int table, int part);
static int lecture_and_query(char *warning, char *devname);
static void sanity_check_provided_device(char *devname, int fd);
static char *get_node(char *devname);
+static int efi_create(void);
#ifdef i386
static void id_to_name(uchar_t sysid, char *buffer);
@@ -714,7 +706,7 @@ static void ext_print_logdrive_layout_debug();
* This function is called only during the non-interactive mode.
* It is touchy and does not tolerate any errors. If there are
* mounted logical drives, changes to the partition table
- * is disallowed.
+ * are disallowed.
*/
static void
update_disk_and_exit(boolean_t table_changed)
@@ -778,7 +770,7 @@ main(int argc, char *argv[])
setbuf(stdout, 0);
/* Process the options. */
- while ((c = getopt(argc, argv, "o:s:P:F:b:A:D:W:S:tTIhwvrndgGRBE"))
+ while ((c = getopt(argc, argv, "o:s:P:F:b:A:D:W:S:tTIhwvrndgGRBE:"))
!= EOF) {
switch (c) {
@@ -816,7 +808,7 @@ main(int argc, char *argv[])
continue;
case 'T':
io_ADJT++;
- /* FALLTHRU */
+ /* FALLTHROUGH */
case 't':
io_adjt++;
continue;
@@ -825,6 +817,11 @@ main(int argc, char *argv[])
io_fdisk++;
continue;
case 'E':
+ if (sscanf(optarg, "%d:%d",
+ &io_EFIslot, &io_EFIactive) != 2) {
+ io_EFIslot = io_EFIactive = 0;
+ optind--;
+ }
io_EFIdisk++;
io_fdisk++;
continue;
@@ -871,7 +868,7 @@ main(int argc, char *argv[])
(void) fprintf(stderr, "%s\n", Usage);
(void) fprintf(stderr, "%s\n", Usage1);
exit(0);
- /* FALLTHRU */
+ /* FALLTHROUGH */
case 'v':
v_flag = 1;
continue;
@@ -905,7 +902,6 @@ main(int argc, char *argv[])
exit(2);
}
-
/* Figure out the correct device node to open */
Dfltdev = get_node(argv[optind]);
@@ -1012,7 +1008,7 @@ main(int argc, char *argv[])
disk_geom.dkg_nhead == 0 ||
disk_geom.dkg_nsect == 0 ||
disk_geom.dkg_ncyl > MAX_CYL ||
- disk_geom.dkg_nhead > MAX_HEAD ||
+ disk_geom.dkg_nhead > MAX_HEAD + 1 ||
disk_geom.dkg_nsect > MAX_SECT) {
/*
@@ -1150,7 +1146,6 @@ main(int argc, char *argv[])
fill_patt(); /* will not return */
}
-
/* This is the fdisk edit, the real reason for the program. */
sanity_check_provided_device(Dfltdev, Dev);
@@ -1268,17 +1263,14 @@ main(int argc, char *argv[])
Set_Table_CHS_Values(0);
update_disk_and_exit(B_TRUE);
} else if (io_EFIdisk) {
- /* create an EFI partition for the whole disk */
- nulltbl();
- i = insert_tbl(EFI_PMBR, 0, 0, 0, 0, 0, 0, 0, 1,
- (dev_capacity > DK_MAX_2TB) ? DK_MAX_2TB :
- (dev_capacity - 1), 0);
- if (i != 0) {
+ if (efi_create() == 0) {
(void) fprintf(stderr,
"Error creating EFI partition\n");
exit(1);
}
- update_disk_and_exit(B_TRUE);
+ (void) close(Dev);
+ exit(0);
+ /* NOTREACHED */
}
}
}
@@ -1463,7 +1455,6 @@ dev_mboot_write(off_t sect, char *buff, int bootsiz)
}
}
-
/* see if the old table had EFI */
for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) {
if (Old_Table[old_pt].systid == EFI_PMBR) {
@@ -1481,8 +1472,14 @@ dev_mboot_write(off_t sect, char *buff, int bootsiz)
(Old_Table[old_pt].relsect ==
Table[new_pt].relsect) &&
(Old_Table[old_pt].numsect ==
- Table[new_pt].numsect))
+ Table[new_pt].numsect)) {
+ /*
+ * New EFI guard partition matches old.
+ * Do not clear EFI labels in this case.
+ */
+ clr_efi = -1;
break;
+ }
}
/*
@@ -2079,7 +2076,7 @@ load(int funct, char *file)
" \"%s\"\n",
file);
exit(1);
- /* FALLTHRU */
+ /* FALLTHROUGH */
case LOADADD:
@@ -2251,7 +2248,7 @@ Set_Table_CHS_Values(int ti)
* so store the maximum CHS field values in the CHS fields.
*/
cy = MAX_CYL + 1;
- hd = MAX_HEAD;
+ hd = MAX_HEAD + 1;
sc = MAX_SECT;
} else {
cy = lba / hba_sectors / hba_heads;
@@ -2269,7 +2266,7 @@ Set_Table_CHS_Values(int ti)
lba = (uint32_t)(Table[ti].relsect + Table[ti].numsect - 1);
if (lba >= hba_heads * hba_sectors * MAX_CYL) {
cy = MAX_CYL + 1;
- hd = MAX_HEAD;
+ hd = MAX_HEAD + 1;
sc = MAX_SECT;
} else {
cy = lba / hba_sectors / hba_heads;
@@ -2315,7 +2312,6 @@ insert_tbl(
return (-1);
}
-
Table[i].systid = (uchar_t)id;
Table[i].bootid = (uchar_t)act;
Table[i].numsect = LE_32(numsect);
@@ -2324,18 +2320,30 @@ insert_tbl(
if (id == UNUSED) {
(void) memset(&Table[i], 0, sizeof (struct ipart));
} else if (0 < bsect && bsect <= MAX_SECT &&
- 0 <= bhead && bhead <= MAX_HEAD &&
+ 0 <= bhead && bhead <= MAX_HEAD + 1 &&
0 < esect && esect <= MAX_SECT &&
- 0 <= ehead && ehead <= MAX_HEAD) {
+ 0 <= ehead && ehead <= MAX_HEAD + 1) {
/*
* If we have been called with a valid geometry, use it
* valid means non-zero values that fit in the BIOS fields
*/
- if (bcyl > MAX_CYL)
+ if (bcyl > MAX_CYL) {
+ /*
+ * bcyl is set to the special fence value indicating
+ * that the geometry is not representable for the
+ * start LBA.
+ * Set all fields to the maximum values.
+ */
bcyl = MAX_CYL + 1;
- if (ecyl > MAX_CYL)
+ bhead = MAX_HEAD + 1;
+ bsect = MAX_SECT;
+ }
+ if (ecyl > MAX_CYL) {
ecyl = MAX_CYL + 1;
+ ehead = MAX_HEAD + 1;
+ esect = MAX_SECT;
+ }
Table[i].begcyl = bcyl & 0xff;
Table[i].endcyl = ecyl & 0xff;
Table[i].beghead = (uchar_t)bhead;
@@ -2764,7 +2772,7 @@ stage0(void)
}
(void) close(Dev);
exit(0);
- /* FALLTHRU */
+ /* FALLTHROUGH */
#endif
#ifdef i386
case '7':
@@ -2780,7 +2788,7 @@ stage0(void)
}
(void) close(Dev);
exit(0);
- /* FALLTHRU */
+ /* FALLTHROUGH */
default:
break;
}
@@ -5625,3 +5633,39 @@ nopartdefined()
return (0);
return (1);
}
+
+/* create an EFI partition for the whole disk */
+static int
+efi_create()
+{
+ if (io_EFIslot < 0 || io_EFIslot > 3) {
+ (void) fprintf(stderr,
+ "EFI partition slot must be between 0 and 3 inclusive.\n");
+ return (0);
+ }
+ if (io_EFIactive != 0 && io_EFIactive != 1) {
+ (void) fprintf(stderr,
+ "EFI partition active flag must be 0 or 1.\n");
+ return (0);
+ }
+
+ nulltbl();
+ /*
+ * In the following call, start and end cylinder values are set to one
+ * above the maximum number of cylinders. This is a special fence
+ * value which indicates that the geometry for the corresponding LBA
+ * is not representable. This results in a protective MBR which
+ * is the same as that created by libefi.
+ */
+ if (insert_tbl(EFI_PMBR,
+ io_EFIactive ? ACTIVE : NOTACTIVE,
+ MAX_HEAD + 1, MAX_SECT, MAX_CYL + 1,
+ MAX_HEAD + 1, MAX_SECT, MAX_CYL + 1,
+ 1,
+ (dev_capacity > DK_MAX_2TB) ? DK_MAX_2TB : (dev_capacity - 1),
+ io_EFIslot) != io_EFIslot)
+ return (0);
+ copy_Table_to_Bootblk();
+ dev_mboot_write(0, Bootsect, sectsiz);
+ return (1);
+}