summaryrefslogtreecommitdiff
path: root/sbin/fdisk/fdisk.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-09-25 11:24:14 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-09-25 11:24:14 +0000
commit2be73c041e1126e066abd15f19c71a8f0a9271e0 (patch)
treec54236f5000b904b920c1d645a234d3b8bd61d26 /sbin/fdisk/fdisk.c
parent72c4799ecfa6d6072750816f17c82d5c613bb745 (diff)
permit loading of a special MBR bootblock -- do not encode a fake MBR
bootblock inside the program. cleanup printed output. do not assume 'd' partition. Solves a whole bunch of other interaction problems with disklabel. Has been tested a fair bit, but will endure more testing (at the hands of the users! Hahahaha!)
Diffstat (limited to 'sbin/fdisk/fdisk.c')
-rw-r--r--sbin/fdisk/fdisk.c333
1 files changed, 154 insertions, 179 deletions
diff --git a/sbin/fdisk/fdisk.c b/sbin/fdisk/fdisk.c
index 46e7b44bec7..c4c4260a978 100644
--- a/sbin/fdisk/fdisk.c
+++ b/sbin/fdisk/fdisk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD */
+/* $OpenBSD: fdisk.c,v 1.4 1996/09/25 11:24:13 deraadt Exp $ */
/* $NetBSD: fdisk.c,v 1.11 1995/10/04 23:11:19 ghudson Exp $ */
/*
@@ -28,9 +28,10 @@
*/
#ifndef lint
-static char rcsid[] = "$NetBSD: fdisk.c,v 1.11 1995/10/04 23:11:19 ghudson Exp $";
+static char rcsid[] = "$OpenBSD: fdisk.c,v 1.4 1996/09/25 11:24:13 deraadt Exp $";
#endif /* not lint */
+#include <sys/param.h>
#include <sys/types.h>
#include <sys/disklabel.h>
#include <sys/ioctl.h>
@@ -45,8 +46,7 @@ static char rcsid[] = "$NetBSD: fdisk.c,v 1.11 1995/10/04 23:11:19 ghudson Exp $
#include <unistd.h>
#include <util.h>
-#define LBUF 100
-static char lbuf[LBUF];
+#define _PATH_MBR "/usr/mdec/sdboot"
/*
* 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University
@@ -54,113 +54,84 @@ static char lbuf[LBUF];
* Created.
*/
-char *disk = "/dev/rwd0d";
+char *disk;
+char *mbrname = _PATH_MBR;
-struct disklabel disklabel; /* disk parameters */
-
-int cylinders, sectors, heads, cylindersectors, disksectors;
+struct disklabel disklabel; /* disk parameters */
+int cylinders;
+int sectors;
+int heads;
+int cylindersectors;
+int disksectors;
struct mboot {
- unsigned char padding[2]; /* force the longs to be long alligned */
- unsigned char bootinst[DOSPARTOFF];
- struct dos_partition parts[4];
- unsigned short int signature;
-};
-struct mboot mboot;
-
-#define ACTIVE 0x80
-#define BOOT_MAGIC 0xAA55
-
-int dos_cylinders;
-int dos_heads;
-int dos_sectors;
-int dos_cylindersectors;
-
-#define DOSSECT(s,c) (((s) & 0x3f) | (((c) >> 2) & 0xc0))
-#define DOSCYL(c) ((c) & 0xff)
-int partition = -1;
-
-int a_flag; /* set active partition */
-int i_flag; /* replace partition data */
-int u_flag; /* update partition data */
-
-unsigned char bootcode[] = {
-0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
-0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
-0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
-0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
-0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
-0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
-0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
-0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
-0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
-'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
- 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
-'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
- 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
-'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
- 'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
-'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
- 'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
+ u_int8_t padding[2]; /* force the longs to be long alligned */
+ u_int8_t bootinst[DOSPARTOFF];
+ struct dos_partition parts[4];
+ u_int32_t signature;
+} mboot;
+
+#define ACTIVE 0x80
+#define BOOT_MAGIC 0xAA55
+
+int dos_cylinders;
+int dos_heads;
+int dos_sectors;
+int dos_cylindersectors;
+
+#define DOSSECT(s,c) (((s) & 0x3f) | (((c) >> 2) & 0xc0))
+#define DOSCYL(c) ((c) & 0xff)
+int partition = -1;
+
+int a_flag; /* set active partition */
+int i_flag; /* replace partition data */
+int u_flag; /* update partition data */
+int m_flag; /* give me a brand new mbr */
+
struct part_type {
- int type;
- char *name;
+ int type;
+ char *name;
} part_types[] = {
- {0x00, "unused"},
- {0x01, "Primary DOS with 12 bit FAT"},
- {0x02, "XENIX / filesystem"},
- {0x03, "XENIX /usr filesystem"},
- {0x04, "Primary DOS with 16 bit FAT"},
- {0x05, "Extended DOS"},
- {0x06, "Primary 'big' DOS (> 32MB)"},
- {0x07, "OS/2 HPFS, QNX or Advanced UNIX"},
- {0x08, "AIX filesystem"},
- {0x09, "AIX boot partition or Coherent"},
- {0x0A, "OS/2 Boot Manager or OPUS"},
- {0x10, "OPUS"},
- {0x40, "VENIX 286"},
- {0x50, "DM"},
- {0x51, "DM"},
- {0x52, "CP/M or Microport SysV/AT"},
- {0x56, "GB"},
- {0x61, "Speed"},
- {0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"},
- {0x64, "Novell Netware 2.xx"},
- {0x65, "Novell Netware 3.xx"},
- {0x75, "PCIX"},
- {0x80, "Minix 1.1 ... 1.4a"},
- {0x81, "Minix 1.4b ... 1.5.10"},
- {0x82, "Linux swap"},
- {0x83, "Linux filesystem"},
- {0x93, "Amoeba filesystem"},
- {0x94, "Amoeba bad block table"},
- {0xA5, "OpenBSD/NetBSD/FreeBSD/386BSD"},
- {0xB7, "BSDI BSD/386 filesystem"},
- {0xB8, "BSDI BSD/386 swap"},
- {0xDB, "Concurrent CPM or C.DOS or CTOS"},
- {0xE1, "Speed"},
- {0xE3, "Speed"},
- {0xE4, "Speed"},
- {0xF1, "Speed"},
- {0xF2, "DOS 3.3+ Secondary"},
- {0xF4, "Speed"},
- {0xFF, "BBT (Bad Blocks Table)"},
+ { 0x00, "unused"},
+ { 0x01, "Primary DOS with 12 bit FAT"},
+ { 0x02, "XENIX / filesystem"},
+ { 0x03, "XENIX /usr filesystem"},
+ { 0x04, "Primary DOS with 16 bit FAT"},
+ { 0x05, "Extended DOS"},
+ { 0x06, "Primary 'big' DOS (> 32MB)"},
+ { 0x07, "OS/2 HPFS, QNX or Advanced UNIX"},
+ { 0x08, "AIX filesystem"},
+ { 0x09, "AIX boot partition or Coherent"},
+ { 0x0A, "OS/2 Boot Manager or OPUS"},
+ { 0x10, "OPUS"},
+ { 0x40, "VENIX 286"},
+ { 0x50, "DM"},
+ { 0x51, "DM"},
+ { 0x52, "CP/M or Microport SysV/AT"},
+ { 0x56, "GB"},
+ { 0x61, "Speed"},
+ { 0x63, "ISC, System V/386, GNU HURD or Mach"},
+ { 0x64, "Novell Netware 2.xx"},
+ { 0x65, "Novell Netware 3.xx"},
+ { 0x75, "PCIX"},
+ { 0x80, "Minix 1.1 ... 1.4a"},
+ { 0x81, "Minix 1.4b ... 1.5.10"},
+ { 0x82, "Linux swap"},
+ { 0x83, "Linux filesystem"},
+ { 0x93, "Amoeba filesystem"},
+ { 0x94, "Amoeba bad block table"},
+ { 0xA5, "NetBSD/FreeBSD/386BSD"},
+ { 0xA6, "OpenBSD"},
+ { 0xB7, "BSDI BSD/386 filesystem"},
+ { 0xB8, "BSDI BSD/386 swap"},
+ { 0xDB, "Concurrent CPM or C.DOS or CTOS"},
+ { 0xE1, "Speed"},
+ { 0xE3, "Speed"},
+ { 0xE4, "Speed"},
+ { 0xF1, "Speed"},
+ { 0xF2, "DOS 3.3+ Secondary"},
+ { 0xF4, "Speed"},
+ { 0xFF, "BBT (Bad Blocks Table)"},
};
void usage __P((void));
@@ -192,11 +163,9 @@ main(argc, argv)
int argc;
char *argv[];
{
- int ch;
- int part;
+ int ch, part;
- a_flag = i_flag = u_flag = 0;
- while ((ch = getopt(argc, argv, "0123aiu")) != -1)
+ while ((ch = getopt(argc, argv, "0123aiumf:")) != -1)
switch (ch) {
case '0':
partition = 0;
@@ -218,31 +187,35 @@ main(argc, argv)
case 'u':
u_flag = 1;
break;
+ case 'm':
+ m_flag = 1;
+ break;
default:
usage();
}
argc -= optind;
argv += optind;
- if (argc > 0)
- disk = argv[0];
+ if (argc == 0)
+ usage();
+
+ disk = argv[0];
if (open_disk(a_flag || i_flag || u_flag) < 0)
exit(1);
- if (read_s0())
- init_sector0(1);
+ printf("Using device %s:\n", disk);
+ if (m_flag || read_s0())
+ init_sector0(0);
intuit_translated_geometry();
- printf("******* Working on device %s *******\n", disk);
if (u_flag)
get_params_to_use();
else
print_params();
- printf("Warning: BIOS sector numbering starts with sector 1\n");
- printf("Information from DOS bootblock is:\n");
+ printf("WARNING: BIOS sector numbers start at 1 (not 0)\n");
if (partition == -1) {
for (part = 0; part < NDOSPART; part++)
change_part(part);
@@ -266,8 +239,7 @@ main(argc, argv)
void
usage()
{
-
- (void)fprintf(stderr, "usage: fdisk [-aiu] [-0|-1|-2|-3] [device]\n");
+ fprintf(stderr, "usage: fdisk [-aium] [-0123] [-f mbrboot] device\n");
exit(1);
}
@@ -281,7 +253,7 @@ print_s0(which)
printf("Information from DOS bootblock is:\n");
if (which == -1) {
for (part = 0; part < NDOSPART; part++)
- printf("%d: ", part), print_part(part);
+ print_part(part);
} else
print_part(which);
}
@@ -294,19 +266,21 @@ print_part(part)
{
struct dos_partition *partp;
+ printf("MBR Partition %d: ", part);
partp = &mboot.parts[part];
if (!memcmp(partp, &mtpart, sizeof(struct dos_partition))) {
printf("<UNUSED>\n");
return;
}
- printf("sysid %d (%s)\n", partp->dp_typ, get_type(partp->dp_typ));
- printf(" start %d, size %d (%d MB), flag %x\n",
+ printf("sysid %d=0x%02x (%s)\n", partp->dp_typ, partp->dp_typ,
+ get_type(partp->dp_typ));
+ printf(" start %d, size %d (%d MB), flag 0x%02x\n",
partp->dp_start, partp->dp_size,
partp->dp_size * 512 / (1024 * 1024), partp->dp_flag);
- printf("\tbeg: cylinder %4d, head %3d, sector %2d\n",
+ printf(" beg: cylinder %4d, head %3d, sector %2d\n",
DPCYL(partp->dp_scyl, partp->dp_ssect),
partp->dp_shd, DPSECT(partp->dp_ssect));
- printf("\tend: cylinder %4d, head %3d, sector %2d\n",
+ printf(" end: cylinder %4d, head %3d, sector %2d\n",
DPCYL(partp->dp_ecyl, partp->dp_esect),
partp->dp_ehd, DPSECT(partp->dp_esect));
}
@@ -316,12 +290,20 @@ init_sector0(start)
int start;
{
struct dos_partition *partp;
+ FILE *f;
+
+ f = fopen(mbrname, "r");
+ if (!f)
+ errx(1, mbrname);
+
+ if (fread(mboot.bootinst, sizeof mboot.bootinst, 1, f) != 1)
+ errx(1, "fread");
+ fclose(f);
- memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
mboot.signature = BOOT_MAGIC;
partp = &mboot.parts[3];
- partp->dp_typ = DOSPTYP_386BSD;
+ partp->dp_typ = DOSPTYP_OPENBSD;
partp->dp_flag = ACTIVE;
partp->dp_start = start;
partp->dp_size = disksectors - start;
@@ -332,7 +314,8 @@ init_sector0(start)
&partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect);
}
-/* Prerequisite: the disklabel parameters and master boot record must
+/*
+ * Prerequisite: the disklabel parameters and master boot record must
* have been read (i.e. dos_* and mboot are meaningful).
* Specification: modifies dos_cylinders, dos_heads, dos_sectors, and
* dos_cylindersectors to be consistent with what the
@@ -344,7 +327,8 @@ init_sector0(start)
* the translated geometry of.
* This whole routine should be replaced with a kernel interface to get
* the BIOS geometry (which in turn requires modifications to the i386
- * boot loader to pass in the BIOS geometry for each disk). */
+ * boot loader to pass in the BIOS geometry for each disk).
+ */
void
intuit_translated_geometry()
{
@@ -412,11 +396,13 @@ intuit_translated_geometry()
dos_cylindersectors = heads * sectors;
}
-/* For the purposes of intuit_translated_geometry(), treat the partition
+/*
+ * For the purposes of intuit_translated_geometry(), treat the partition
* table as a list of eight mapping between (cylinder, head, sector)
* triplets and absolute sectors. Get the relevant geometry triplet and
* absolute sectors for a given entry, or return -1 if it isn't present.
- * Note: for simplicity, the returned sector is 0-based. */
+ * Note: for simplicity, the returned sector is 0-based.
+ */
int
get_mapping(i, cylinder, head, sector, absolute)
int i, *cylinder, *head, *sector;
@@ -444,39 +430,32 @@ void
change_part(part)
int part;
{
- struct dos_partition *partp;
+ struct dos_partition *partp = &mboot.parts[part];
+ int sysid, start, size;
- partp = &mboot.parts[part];
-
- printf("The data for partition %d is:\n", part);
print_part(part);
-
if (!u_flag || !yesno("Do you want to change it?"))
return;
if (i_flag) {
memset(partp, 0, sizeof(*partp));
if (part == 3) {
- init_sector0(1);
+ init_sector0(0);
printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
print_part(part);
}
}
do {
- {
- int sysid, start, size;
-
- sysid = partp->dp_typ,
- start = partp->dp_start,
- size = partp->dp_size;
- decimal("sysid", &sysid);
- decimal("start", &start);
- decimal("size", &size);
- partp->dp_typ = sysid;
- partp->dp_start = start;
- partp->dp_size = size;
- }
+ sysid = partp->dp_typ,
+ start = partp->dp_start,
+ size = partp->dp_size;
+ decimal("sysid", &sysid);
+ decimal("start", &start);
+ decimal("size", &size);
+ partp->dp_typ = sysid;
+ partp->dp_start = start;
+ partp->dp_size = size;
if (yesno("Explicitly specify beg/end address?")) {
int tsector, tcylinder, thead;
@@ -515,25 +494,26 @@ void
print_params()
{
- printf("parameters extracted from in-core disklabel are:\n");
- printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
- cylinders, heads, sectors, cylindersectors);
+ printf("Parameters extracted from in-core disklabel are:\n");
+ printf(" cylinders=%d heads=%d sectors/track=%d\n",
+ cylinders, heads, sectors);
+ printf(" sectors/cylinder=%d total=%d\n",
+ cylindersectors, disksectors);
if (dos_sectors > 63 || dos_cylinders > 1023 || dos_heads > 255)
printf("Figures below won't work with BIOS for partitions not in cylinder 1\n");
- printf("parameters to be used for BIOS calculations are:\n");
- printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
+ printf("Parameters to be used for BIOS calculations are:\n");
+ printf(" cylinders=%d heads=%d sectors/track=%d\n",
dos_cylinders, dos_heads, dos_sectors, dos_cylindersectors);
+ printf(" sectors/cylinder=%d\n",
+ dos_cylindersectors);
}
void
change_active(which)
int which;
{
- struct dos_partition *partp;
- int part;
- int active = 3;
-
- partp = &mboot.parts[0];
+ struct dos_partition *partp = &mboot.parts[0];
+ int part, active = 3;
if (a_flag && which != -1)
active = which;
@@ -555,7 +535,6 @@ change_active(which)
void
get_params_to_use()
{
-
print_params();
if (yesno("Do you want to change our idea of what BIOS thinks?")) {
do {
@@ -568,9 +547,9 @@ get_params_to_use()
}
}
-/***********************************************\
-* Change real numbers into strange dos numbers *
-\***********************************************/
+/*
+ * Change real numbers into strange dos numbers
+ */
void
dos(sector, cylinderp, headp, sectorp)
int sector;
@@ -624,7 +603,6 @@ read_disk(sector, buf)
int sector;
void *buf;
{
-
if (lseek(fd, (off_t)(sector * 512), 0) == -1)
return (-1);
return (read(fd, buf, 512));
@@ -635,7 +613,6 @@ write_disk(sector, buf)
int sector;
void *buf;
{
-
if (lseek(fd, (off_t)(sector * 512), 0) == -1)
return (-1);
return (write(fd, buf, 512));
@@ -644,7 +621,6 @@ write_disk(sector, buf)
int
get_params()
{
-
if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
warn("DIOCGDINFO");
return (-1);
@@ -655,7 +631,6 @@ get_params()
dos_sectors = sectors = disklabel.d_nsectors;
dos_cylindersectors = cylindersectors = heads * sectors;
disksectors = cylinders * heads * sectors;
-
return (0);
}
@@ -668,7 +643,8 @@ read_s0()
return (-1);
}
if (mboot.signature != BOOT_MAGIC) {
- warn("invalid fdisk partition table found");
+ fprintf(stderr,
+ "warning: invalid fdisk partition table found!\n");
/* So should we initialize things? */
return (-1);
}
@@ -717,32 +693,32 @@ decimal(str, num)
char *str;
int *num;
{
+ char lbuf[100], *cp;
int acc = 0;
- char *cp;
- for (;; printf("%s is not a valid decimal number.\n", lbuf)) {
+ while (1) {
printf("Supply a decimal value for \"%s\" [%d] ", str, *num);
- fgets(lbuf, LBUF, stdin);
+ if (fgets(lbuf, sizeof lbuf, stdin) == NULL)
+ errx(1, "eof");
lbuf[strlen(lbuf)-1] = '\0';
- cp = lbuf;
+ cp = lbuf;
cp += strspn(cp, " \t");
if (*cp == '\0')
return;
-
if (!isdigit(*cp))
- continue;
+ goto bad;
acc = strtol(lbuf, &cp, 10);
cp += strspn(cp, " \t");
if (*cp != '\0')
- continue;
-
+ goto bad;
*num = acc;
return;
+bad:
+ printf("%s is not a valid decimal number.\n", lbuf);
}
-
}
int
@@ -770,6 +746,5 @@ get_type(type)
sizeof(struct part_type), type_match);
if (ptr == 0)
return ("unknown");
- else
- return (ptr->name);
+ return (ptr->name);
}