diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /sbin/fdisk |
initial import of NetBSD tree
Diffstat (limited to 'sbin/fdisk')
-rw-r--r-- | sbin/fdisk/Makefile | 7 | ||||
-rw-r--r-- | sbin/fdisk/fdisk.8 | 173 | ||||
-rw-r--r-- | sbin/fdisk/fdisk.c | 772 |
3 files changed, 952 insertions, 0 deletions
diff --git a/sbin/fdisk/Makefile b/sbin/fdisk/Makefile new file mode 100644 index 00000000000..4f9961cc10a --- /dev/null +++ b/sbin/fdisk/Makefile @@ -0,0 +1,7 @@ +# $NetBSD: Makefile,v 1.4 1995/03/18 14:55:33 cgd Exp $ + +PROG= fdisk +SRCS= fdisk.c +MAN= fdisk.8 + +.include <bsd.prog.mk> diff --git a/sbin/fdisk/fdisk.8 b/sbin/fdisk/fdisk.8 new file mode 100644 index 00000000000..6d3a37b4c9b --- /dev/null +++ b/sbin/fdisk/fdisk.8 @@ -0,0 +1,173 @@ +.\" $NetBSD: fdisk.8,v 1.8 1995/03/18 14:55:34 cgd Exp $ +.\" +.Dd April 4, 1993 +.Dt FDISK 8 +.\" .Os BSD 4 +.Sh NAME +.Nm fdisk +.Nd DOS partition maintenance program +.Sh SYNOPSIS +.Nm +.Op Fl aiu +.Op Ar device +.Sh PROLOGUE +In order for the BIOS to boot the kernel, certain conventions must be +adhered to. +Sector 0 of the disk must contain boot code, a partition table, and a +magic number. +BIOS partitions can be used to break the disk up into several pieces. +The BIOS brings in sector 0, verifies the magic number, and begins +executing the code at the first byte. +This code is turn searches the DOS partition table for an `active' +partition. +If one is found, the boot block from that partition is loaded and replaces +the original boot block. +Under DOS, you could have one or more partitions with one active. +The DOS +.Nm +program can be used to divide space on the disk into partitions and set +one active. +.Pp +The NetBSD program +.Nm +serves a similar purpose to the DOS program. +When called with no arguments, it prints the sector 0 partition table. +An example follows: +.Bd -literal + ******* Working on device /dev/rwd0d ******* + parameters extracted from in-core disklabel are: + cylinders=769 heads=15 sectors/track=33 (495 sectors/cylinder) + + parameters to be used for BIOS calculations are: + cylinders=769 heads=15 sectors/track=33 (495 sectors/cylinder) + + Warning: BIOS sector numbering starts with sector 1 + Information from DOS bootblock is: + The data for partition 0 is: + sysid 165 (NetBSD) + start 495, size 380160 (185 MB), flag 0 + beg: cylinder 1, head 0, sector 1 + end: cylinder 768, head 14, sector 33 + The data for partition 1 is: + sysid 164 (unknown) + start 378180, size 2475 (1 MB), flag 0 + beg: cylinder 764, head 0, sector 1 + end: cylinder 768, head 14, sector 33 + The data for partition 2 is: + <UNUSED> + The data for partition 3 is: + sysid 99 (ISC UNIX, other System V/386, GNU HURD or Mach) + start 380656, size 224234 (109 MB), flag 80 + beg: cylinder 769, head 0, sector 2 + end: cylinder 197, head 14, sector 33 +.Ed +.Pp +The disk is divided into three partitions that happen to fill the disk. +The second partition overlaps the end of the first. +(Used for debugging purposes) +.Bl -tag -width "cyl, sector and head" +.It Em "sysid" +is used to label the partition. NetBSD reserves the +magic number 165 decimal (A5 in hex). +.It Em "start and size" +fields provide the start address +and size of a partition in sectors. +.It Em "flag 80" +specifies that this is the active partition. +.It Em "cyl, sector and head" +fields are used to specify the beginning address +and end address for the partition. +.It Em "Note:" +these numbers are calculated using BIOS's understanding of the disk geometry +and saved in the bootblock. +.El +.Pp +The flags +.Fl i +or +.Fl u +are used to indicate that the partition data is to be updated. +The +.Nm +program will enter a conversational mode. +This mode is designed not to change any data unless you explicitly tell it to; +.Nm +selects defaults for its questions to guarantee that behavior. +.Pp +It displays each partition and asks if you want to edit it. +If you reply affirmatively, +it will step through each field showing the old value +and asking for a new one. +When you are done with a partition, +.Nm +will display the information again and ask if it is correct. +.Nm +will then procede to the next entry. +.Pp +Getting the +.Em cyl, sector, +and +.Em head +fields correct is tricky. +So by default, +they will be calculated for you; +you can specify them if you choose. +.Pp +After all the partitions are processed, +you are given the option to change the +.Em active +partition. +To change only the +.Em active +partition, you can use the +.Fl a +flag instead. +.Pp +Finally, +when the all the data for the first sector has been accumulated, +.Nm +will ask if you really want to rewrite sector 0. +Only if you reply affirmatively to this question will +.Nm +write anything to the disk. +.Pp +The difference between the +.Fl u +flag and +.Fl i +flag is that +the +.Fl u +flag just edits the fields as they appear on the disk, while the +.Fl i +flag is used to `initialize' sector 0. +The +.Fl i +flag instructs +.Nm +to start by making the first 3 partitions empty, setting the last partition +to use the whole disk for NetBSD, and marking the last partition active. +.Sh NOTES +The automatic calculation of starting cylinder etc. uses +a set of figures that represent what the BIOS thinks is the +geometry of the drive. +These figures are by default taken from the incore disklabel, but +.Nm +gives you an opportunity to change them. +This allows the user to create a bootblock that can work with drives +that use geometry translation under the BIOS. +.Pp +If you hand craft your disk layout, +please make sure that the NetBSD partition starts on a cylinder boundary. +(This restriction may be changed in the future.) +.Pp +Editing an existing partition is risky, and may cause you to +lose all the data in that partition. +.Pp +You should run this program interactively once or twice to see how it works. +This is completely safe as long as you answer the last question in the negative. +.Sh SEE ALSO +.Xr disklabel 8 +.Sh BUGS +There are subtleties that the program detects that are not explained in +this manual page. diff --git a/sbin/fdisk/fdisk.c b/sbin/fdisk/fdisk.c new file mode 100644 index 00000000000..60cfe1bc2ab --- /dev/null +++ b/sbin/fdisk/fdisk.c @@ -0,0 +1,772 @@ +/* $NetBSD: fdisk.c,v 1.11 1995/10/04 23:11:19 ghudson Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef lint +static char rcsid[] = "$NetBSD: fdisk.c,v 1.11 1995/10/04 23:11:19 ghudson Exp $"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/disklabel.h> +#include <sys/ioctl.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define LBUF 100 +static char lbuf[LBUF]; + +/* + * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University + * Copyright (c) 1989 Robert. V. Baron + * Created. + */ + +char *disk = "/dev/rwd0d"; + +struct disklabel disklabel; /* disk parameters */ + +int cylinders, sectors, heads, cylindersectors, 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 +}; + +struct part_type { + 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, "NetBSD or 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)"}, +}; + +void usage __P((void)); +void print_s0 __P((int)); +void print_part __P((int)); +void init_sector0 __P((int)); +void intuit_translated_geometry __P((void)); +int try_heads __P((quad_t, quad_t, quad_t, quad_t, quad_t, quad_t, quad_t, + quad_t)); +int try_sectors __P((quad_t, quad_t, quad_t, quad_t, quad_t)); +void change_part __P((int)); +void print_params __P((void)); +void change_active __P((int)); +void get_params_to_use __P((void)); +void dos __P((int, unsigned char *, unsigned char *, unsigned char *)); +int open_disk __P((int)); +int read_disk __P((int, void *)); +int write_disk __P((int, void *)); +int get_params __P((void)); +int read_s0 __P((void)); +int write_s0 __P((void)); +int yesno __P((char *)); +void decimal __P((char *, int *)); +int type_match __P((const void *, const void *)); +char *get_type __P((int)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int ch; + int part; + + a_flag = i_flag = u_flag = 0; + while ((ch = getopt(argc, argv, "0123aiu")) != -1) + switch (ch) { + case '0': + partition = 0; + break; + case '1': + partition = 1; + break; + case '2': + partition = 2; + break; + case '3': + partition = 3; + break; + case 'a': + a_flag = 1; + break; + case 'i': + i_flag = 1; + case 'u': + u_flag = 1; + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc > 0) + disk = argv[0]; + + if (open_disk(a_flag || i_flag || u_flag) < 0) + exit(1); + + if (read_s0()) + init_sector0(1); + + 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"); + if (partition == -1) { + for (part = 0; part < NDOSPART; part++) + change_part(part); + } else + change_part(partition); + + if (u_flag || a_flag) + change_active(partition); + + if (u_flag || a_flag) { + printf("\nWe haven't changed the partition table yet. "); + printf("This is your last chance.\n"); + print_s0(-1); + if (yesno("Should we write new partition table?")) + write_s0(); + } + + exit(0); +} + +void +usage() +{ + + (void)fprintf(stderr, "usage: fdisk [-aiu] [-0|-1|-2|-3] [device]\n"); + exit(1); +} + +void +print_s0(which) + int which; +{ + int part; + + print_params(); + printf("Information from DOS bootblock is:\n"); + if (which == -1) { + for (part = 0; part < NDOSPART; part++) + printf("%d: ", part), print_part(part); + } else + print_part(which); +} + +static struct dos_partition mtpart = { 0 }; + +void +print_part(part) + int part; +{ + struct dos_partition *partp; + + 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", + partp->dp_start, partp->dp_size, + partp->dp_size * 512 / (1024 * 1024), partp->dp_flag); + printf("\tbeg: 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", + DPCYL(partp->dp_ecyl, partp->dp_esect), + partp->dp_ehd, DPSECT(partp->dp_esect)); +} + +void +init_sector0(start) + int start; +{ + struct dos_partition *partp; + + memcpy(mboot.bootinst, bootcode, sizeof(bootcode)); + mboot.signature = BOOT_MAGIC; + + partp = &mboot.parts[3]; + partp->dp_typ = DOSPTYP_386BSD; + partp->dp_flag = ACTIVE; + partp->dp_start = start; + partp->dp_size = disksectors - start; + + dos(partp->dp_start, + &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect); + dos(partp->dp_start + partp->dp_size - 1, + &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect); +} + +/* 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 + * partition table is using, if we can find a geometry + * which is consistent with all partition table entries. + * We may get the number of cylinders slightly wrong (in + * the conservative direction). The idea is to be able + * to create a NetBSD partition on a disk we don't know + * 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). */ +void +intuit_translated_geometry() +{ + int cylinders = -1, heads = -1, sectors = -1, i, j; + int c1, h1, s1, c2, h2, s2; + long a1, a2; + quad_t num, denom; + + /* Try to deduce the number of heads from two different mappings. */ + for (i = 0; i < NDOSPART * 2; i++) { + if (get_mapping(i, &c1, &h1, &s1, &a1) < 0) + continue; + for (j = 0; j < 8; j++) { + if (get_mapping(j, &c2, &h2, &s2, &a2) < 0) + continue; + num = (quad_t)h1*(a2-s2) - h2*(a1-s1); + denom = (quad_t)c2*(a1-s1) - c1*(a2-s2); + if (denom != 0 && num % denom == 0) { + heads = num / denom; + break; + } + } + if (heads != -1) + break; + } + + if (heads == -1) + return; + + /* Now figure out the number of sectors from a single mapping. */ + for (i = 0; i < NDOSPART * 2; i++) { + if (get_mapping(i, &c1, &h1, &s1, &a1) < 0) + continue; + num = a1 - s1; + denom = c1 * heads + h1; + if (denom != 0 && num % denom == 0) { + sectors = num / denom; + break; + } + } + + if (sectors == -1) + return; + + /* Estimate the number of cylinders. */ + cylinders = dos_cylinders * dos_cylindersectors / heads / sectors; + + /* Now verify consistency with each of the partition table entries. + * Be willing to shove cylinders up a little bit to make things work, + * but translation mismatches are fatal. */ + for (i = 0; i < NDOSPART * 2; i++) { + if (get_mapping(i, &c1, &h1, &s1, &a1) < 0) + continue; + if (sectors * (c1 * heads + h1) + s1 != a1) + return; + if (c1 >= cylinders) + cylinders = c1 + 1; + } + + /* Everything checks out. Reset the geometry to use for further + * calculations. */ + dos_cylinders = cylinders; + dos_heads = heads; + dos_sectors = sectors; + dos_cylindersectors = heads * sectors; +} + +/* 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. */ +int +get_mapping(i, cylinder, head, sector, absolute) + int i, *cylinder, *head, *sector; + long *absolute; +{ + struct dos_partition *part = &mboot.parts[i / 2]; + + if (part->dp_typ == 0) + return -1; + if (i % 2 == 0) { + *cylinder = DPCYL(part->dp_scyl, part->dp_ssect); + *head = part->dp_shd; + *sector = DPSECT(part->dp_ssect) - 1; + *absolute = part->dp_start; + } else { + *cylinder = DPCYL(part->dp_ecyl, part->dp_esect); + *head = part->dp_ehd; + *sector = DPSECT(part->dp_esect) - 1; + *absolute = part->dp_start + part->dp_size - 1; + } + return 0; +} + +void +change_part(part) + int part; +{ + struct dos_partition *partp; + + 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); + 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; + } + + if (yesno("Explicitly specify beg/end address?")) { + int tsector, tcylinder, thead; + + tcylinder = DPCYL(partp->dp_scyl, partp->dp_ssect); + thead = partp->dp_shd; + tsector = DPSECT(partp->dp_ssect); + decimal("beginning cylinder", &tcylinder); + decimal("beginning head", &thead); + decimal("beginning sector", &tsector); + partp->dp_scyl = DOSCYL(tcylinder); + partp->dp_shd = thead; + partp->dp_ssect = DOSSECT(tsector, tcylinder); + + tcylinder = DPCYL(partp->dp_ecyl, partp->dp_esect); + thead = partp->dp_ehd; + tsector = DPSECT(partp->dp_esect); + decimal("ending cylinder", &tcylinder); + decimal("ending head", &thead); + decimal("ending sector", &tsector); + partp->dp_ecyl = DOSCYL(tcylinder); + partp->dp_ehd = thead; + partp->dp_esect = DOSSECT(tsector, tcylinder); + } else { + dos(partp->dp_start, + &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect); + dos(partp->dp_start + partp->dp_size - 1, + &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect); + } + + print_part(part); + } while (!yesno("Is this entry okay?")); +} + +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); + 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", + dos_cylinders, dos_heads, dos_sectors, dos_cylindersectors); +} + +void +change_active(which) + int which; +{ + struct dos_partition *partp; + int part; + int active = 3; + + partp = &mboot.parts[0]; + + if (a_flag && which != -1) + active = which; + else { + for (part = 0; part < NDOSPART; part++) + if (partp[part].dp_flag & ACTIVE) + active = part; + } + if (yesno("Do you want to change the active partition?")) { + do { + decimal("active partition", &active); + } while (!yesno("Are you happy with this choice?")); + } + for (part = 0; part < NDOSPART; part++) + partp[part].dp_flag &= ~ACTIVE; + partp[active].dp_flag |= ACTIVE; +} + +void +get_params_to_use() +{ + + print_params(); + if (yesno("Do you want to change our idea of what BIOS thinks?")) { + do { + decimal("BIOS's idea of #cylinders", &dos_cylinders); + decimal("BIOS's idea of #heads", &dos_heads); + decimal("BIOS's idea of #sectors", &dos_sectors); + dos_cylindersectors = dos_heads * dos_sectors; + print_params(); + } while (!yesno("Are you happy with this choice?")); + } +} + +/***********************************************\ +* Change real numbers into strange dos numbers * +\***********************************************/ +void +dos(sector, cylinderp, headp, sectorp) + int sector; + unsigned char *cylinderp, *headp, *sectorp; +{ + int cylinder, head; + + cylinder = sector / dos_cylindersectors; + sector -= cylinder * dos_cylindersectors; + + head = sector / dos_sectors; + sector -= head * dos_sectors; + + *cylinderp = DOSCYL(cylinder); + *headp = head; + *sectorp = DOSSECT(sector + 1, cylinder); +} + +int fd; + +int +open_disk(u_flag) + int u_flag; +{ + struct stat st; + + if ((fd = open(disk, u_flag ? O_RDWR : O_RDONLY)) == -1) { + warn("%s", disk); + return (-1); + } + if (fstat(fd, &st) == -1) { + close(fd); + warn("%s", disk); + return (-1); + } + if (!S_ISCHR(st.st_mode) && !S_ISREG(st.st_mode)) { + close(fd); + warnx("%s is not a character device or regular file", disk); + return (-1); + } + if (get_params() == -1) { + close(fd); + return (-1); + } + return (0); +} + +int +read_disk(sector, buf) + int sector; + void *buf; +{ + + if (lseek(fd, (off_t)(sector * 512), 0) == -1) + return (-1); + return (read(fd, buf, 512)); +} + +int +write_disk(sector, buf) + int sector; + void *buf; +{ + + if (lseek(fd, (off_t)(sector * 512), 0) == -1) + return (-1); + return (write(fd, buf, 512)); +} + +int +get_params() +{ + + if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { + warn("DIOCGDINFO"); + return (-1); + } + + dos_cylinders = cylinders = disklabel.d_ncylinders; + dos_heads = heads = disklabel.d_ntracks; + dos_sectors = sectors = disklabel.d_nsectors; + dos_cylindersectors = cylindersectors = heads * sectors; + disksectors = cylinders * heads * sectors; + + return (0); +} + +int +read_s0() +{ + + if (read_disk(0, mboot.bootinst) == -1) { + warn("can't read fdisk partition table"); + return (-1); + } + if (mboot.signature != BOOT_MAGIC) { + warn("invalid fdisk partition table found"); + /* So should we initialize things? */ + return (-1); + } + return (0); +} + +int +write_s0() +{ + int flag; + + /* + * write enable label sector before write (if necessary), + * disable after writing. + * needed if the disklabel protected area also protects + * sector 0. (e.g. empty disk) + */ + flag = 1; + if (ioctl(fd, DIOCWLABEL, &flag) < 0) + warn("DIOCWLABEL"); + if (write_disk(0, mboot.bootinst) == -1) { + warn("can't write fdisk partition table"); + return -1; + } + flag = 0; + if (ioctl(fd, DIOCWLABEL, &flag) < 0) + warn("DIOCWLABEL"); +} + +int +yesno(str) + char *str; +{ + int ch, first; + + printf("%s [n] ", str); + + first = ch = getchar(); + while (ch != '\n' && ch != EOF) + ch = getchar(); + return (first == 'y' || first == 'Y'); +} + +void +decimal(str, num) + char *str; + int *num; +{ + int acc = 0; + char *cp; + + for (;; printf("%s is not a valid decimal number.\n", lbuf)) { + printf("Supply a decimal value for \"%s\" [%d] ", str, *num); + + fgets(lbuf, LBUF, stdin); + lbuf[strlen(lbuf)-1] = '\0'; + cp = lbuf; + + cp += strspn(cp, " \t"); + if (*cp == '\0') + return; + + if (!isdigit(*cp)) + continue; + acc = strtol(lbuf, &cp, 10); + + cp += strspn(cp, " \t"); + if (*cp != '\0') + continue; + + *num = acc; + return; + } + +} + +int +type_match(key, item) + const void *key, *item; +{ + const int *typep = key; + const struct part_type *ptr = item; + + if (*typep < ptr->type) + return (-1); + if (*typep > ptr->type) + return (1); + return (0); +} + +char * +get_type(type) + int type; +{ + struct part_type *ptr; + + ptr = bsearch(&type, part_types, + sizeof(part_types) / sizeof(struct part_type), + sizeof(struct part_type), type_match); + if (ptr == 0) + return ("unknown"); + else + return (ptr->name); +} |