fdisk.c revision 37415
18871Srgrimes/*
24Srgrimes * Mach Operating System
34Srgrimes * Copyright (c) 1992 Carnegie Mellon University
44Srgrimes * All Rights Reserved.
58871Srgrimes *
64Srgrimes * Permission to use, copy, modify and distribute this software and its
74Srgrimes * documentation is hereby granted, provided that both the copyright
84Srgrimes * notice and this permission notice appear in all copies of the
94Srgrimes * software, derivative works or modified versions, and any portions
104Srgrimes * thereof, and that both notices appear in supporting documentation.
118871Srgrimes *
124Srgrimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
134Srgrimes * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
144Srgrimes * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
158871Srgrimes *
164Srgrimes * Carnegie Mellon requests users of this software to return to
178871Srgrimes *
184Srgrimes *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
194Srgrimes *  School of Computer Science
204Srgrimes *  Carnegie Mellon University
214Srgrimes *  Pittsburgh PA 15213-3890
228871Srgrimes *
234Srgrimes * any improvements or extensions that they make and grant Carnegie Mellon
244Srgrimes * the rights to redistribute these changes.
254Srgrimes */
264Srgrimes
2737415Scharnier#ifndef lint
2837415Scharnierstatic const char rcsid[] =
2937415Scharnier	"$Id$";
3037415Scharnier#endif /* not lint */
3137415Scharnier
324Srgrimes#include <sys/disklabel.h>
3337415Scharnier#include <sys/stat.h>
3437415Scharnier#include <ctype.h>
3537415Scharnier#include <fcntl.h>
3637415Scharnier#include <err.h>
3737415Scharnier#include <errno.h>
384Srgrimes#include <stdio.h>
3937415Scharnier#include <stdlib.h>
4016561Salex#include <string.h>
4116561Salex#include <unistd.h>
424Srgrimes
434Srgrimesint iotest;
444Srgrimes
454Srgrimes#define LBUF 100
464Srgrimesstatic char lbuf[LBUF];
474Srgrimes
484Srgrimes/*
494Srgrimes *
504Srgrimes * Ported to 386bsd by Julian Elischer  Thu Oct 15 20:26:46 PDT 1992
514Srgrimes *
524Srgrimes * 14-Dec-89  Robert Baron (rvb) at Carnegie-Mellon University
534Srgrimes *	Copyright (c) 1989	Robert. V. Baron
544Srgrimes *	Created.
554Srgrimes */
564Srgrimes
574Srgrimes#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
584Srgrimes#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
594Srgrimes#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
604Srgrimes
614Srgrimes#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
624Srgrimes
6320061Ssos#define MAX_SEC_SIZE 2048	/* maximum section size that is supported */
6420061Ssos#define MIN_SEC_SIZE 512	/* the sector size to start sensing at */
6520061Ssosint secsize = 0;		/* the sensed sector size */
664Srgrimes
6710514Sjoergconst char *disk;
6810514Sjoergconst char *disks[] =
6910514Sjoerg{
7010514Sjoerg  "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0
7110514Sjoerg};
7210514Sjoerg
734Srgrimesstruct disklabel disklabel;		/* disk parameters */
744Srgrimes
754Srgrimesint cyls, sectors, heads, cylsecs, disksecs;
764Srgrimes
774Srgrimesstruct mboot
784Srgrimes{
7937415Scharnier	unsigned char padding[2]; /* force the longs to be long aligned */
804Srgrimes	unsigned char bootinst[DOSPARTOFF];
814Srgrimes	struct	dos_partition parts[4];
824Srgrimes	unsigned short int	signature;
8320061Ssos	/* room to read in MBRs that are bigger then DEV_BSIZE */
8420061Ssos	unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE];
854Srgrimes};
864Srgrimesstruct mboot mboot;
874Srgrimes
884Srgrimes#define ACTIVE 0x80
894Srgrimes#define BOOT_MAGIC 0xAA55
904Srgrimes
914Srgrimesint dos_cyls;
924Srgrimesint dos_heads;
934Srgrimesint dos_sectors;
944Srgrimesint dos_cylsecs;
954Srgrimes
964Srgrimes#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
974Srgrimes#define DOSCYL(c)	(c & 0xff)
984Srgrimesstatic int partition = -1;
994Srgrimes
1004Srgrimes
10119459Sjkh#define MAX_ARGS	10
10219459Sjkh
10319459Sjkhstatic int	current_line_number;
10419459Sjkh
10519459Sjkhstatic int	geom_processed = 0;
10619459Sjkhstatic int	part_processed = 0;
10719459Sjkhstatic int	active_processed = 0;
10819459Sjkh
10919459Sjkh
11019459Sjkhtypedef struct cmd {
11119459Sjkh    char		cmd;
11219459Sjkh    int			n_args;
11319459Sjkh    struct arg {
11419459Sjkh	char	argtype;
11519459Sjkh	int	arg_val;
11619459Sjkh    }			args[MAX_ARGS];
11719459Sjkh} CMD;
11819459Sjkh
11919459Sjkh
1204Srgrimesstatic int a_flag  = 0;		/* set active partition */
1214Srgrimesstatic int i_flag  = 0;		/* replace partition data */
1224Srgrimesstatic int u_flag  = 0;		/* update partition data */
12319459Sjkhstatic int t_flag  = 0;		/* test only, if f_flag is given */
12419459Sjkhstatic char *f_flag = NULL;	/* Read config info from file */
12519459Sjkhstatic int v_flag  = 0;		/* Be verbose */
1264Srgrimes
1274Srgrimesstatic unsigned char bootcode[] = {
1288871Srgrimes0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
1298871Srgrimes0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
1308871Srgrimes0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
1318871Srgrimes0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
1328871Srgrimes0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
1338871Srgrimes0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
1348871Srgrimes0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
1358871Srgrimes0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
1364Srgrimes0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
1374Srgrimes'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
1384Srgrimes	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
1398871Srgrimes'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
1404Srgrimes	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
1414Srgrimes'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
1424Srgrimes	'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
1434Srgrimes'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
1448871Srgrimes	'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
1454Srgrimes
1468871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1478871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1488871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1498871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1508871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1518871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1528871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1538871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1548871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1558871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1568871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1578871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1588871Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
1594Srgrimes};
1604Srgrimes
1614Srgrimesstruct part_type
1624Srgrimes{
1634Srgrimes unsigned char type;
1644Srgrimes char *name;
1654Srgrimes}part_types[] =
1664Srgrimes{
1678871Srgrimes	 {0x00, "unused"}
1688871Srgrimes	,{0x01, "Primary DOS with 12 bit FAT"}
1698871Srgrimes	,{0x02, "XENIX / filesystem"}
1708871Srgrimes	,{0x03, "XENIX /usr filesystem"}
17134582Sache	,{0x04, "Primary DOS with 16 bit FAT (<= 32MB)"}
1728871Srgrimes	,{0x05, "Extended DOS"}
1738871Srgrimes	,{0x06, "Primary 'big' DOS (> 32MB)"}
17434952Sobrien	,{0x07, "OS/2 HPFS, NTFS, QNX or Advanced UNIX"}
1758871Srgrimes	,{0x08, "AIX filesystem"}
1768871Srgrimes	,{0x09, "AIX boot partition or Coherent"}
1778871Srgrimes	,{0x0A, "OS/2 Boot Manager or OPUS"}
17834582Sache	,{0x0B, "DOS or Windows 95 with 32 bit FAT"}
17934582Sache	,{0x0C, "DOS or Windows 95 with 32 bit FAT, LBA"}
18034582Sache	,{0x0E, "Primary 'big' DOS (> 32MB, LBA)"}
18134582Sache	,{0x0F, "Extended DOS, LBA"}
1828871Srgrimes	,{0x10, "OPUS"}
1838871Srgrimes	,{0x40, "VENIX 286"}
1848871Srgrimes	,{0x50, "DM"}
1858871Srgrimes	,{0x51, "DM"}
1868871Srgrimes	,{0x52, "CP/M or Microport SysV/AT"}
1878871Srgrimes	,{0x56, "GB"}
1888871Srgrimes	,{0x61, "Speed"}
1898871Srgrimes	,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
1908871Srgrimes	,{0x64, "Novell Netware 2.xx"}
1918871Srgrimes	,{0x65, "Novell Netware 3.xx"}
1928871Srgrimes	,{0x75, "PCIX"}
1938871Srgrimes	,{0x80, "Minix 1.1 ... 1.4a"}
1948871Srgrimes	,{0x81, "Minix 1.4b ... 1.5.10"}
1958871Srgrimes	,{0x82, "Linux swap"}
1968871Srgrimes	,{0x83, "Linux filesystem"}
1978871Srgrimes	,{0x93, "Amoeba filesystem"}
1988871Srgrimes	,{0x94, "Amoeba bad block table"}
1998871Srgrimes	,{0xA5, "FreeBSD/NetBSD/386BSD"}
20025378Simp	,{0xA6, "OpenBSD"}
2017902Sgpalmer	,{0xA7, "NEXTSTEP"}
2028871Srgrimes	,{0xB7, "BSDI BSD/386 filesystem"}
2038871Srgrimes	,{0xB8, "BSDI BSD/386 swap"}
2048871Srgrimes	,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
2058871Srgrimes	,{0xE1, "Speed"}
2068871Srgrimes	,{0xE3, "Speed"}
2078871Srgrimes	,{0xE4, "Speed"}
2088871Srgrimes	,{0xF1, "Speed"}
2098871Srgrimes	,{0xF2, "DOS 3.3+ Secondary"}
2108871Srgrimes	,{0xF4, "Speed"}
2118871Srgrimes	,{0xFF, "BBT (Bad Blocks Table)"}
2124Srgrimes};
2134Srgrimes
21416561Salexstatic void print_s0(int which);
21516561Salexstatic void print_part(int i);
21616561Salexstatic void init_sector0(unsigned long start);
21719459Sjkhstatic void init_boot(void);
21816561Salexstatic void change_part(int i);
21916561Salexstatic void print_params();
22016561Salexstatic void change_active(int which);
22116561Salexstatic void get_params_to_use();
22218915Sbdestatic void dos(int sec, int size, unsigned char *c, unsigned char *s,
22318915Sbde		unsigned char *h);
22416561Salexstatic int open_disk(int u_flag);
22516561Salexstatic ssize_t read_disk(off_t sector, void *buf);
22616561Salexstatic ssize_t write_disk(off_t sector, void *buf);
22716561Salexstatic int get_params();
22816561Salexstatic int read_s0();
22916561Salexstatic int write_s0();
23016561Salexstatic int ok(char *str);
23116561Salexstatic int decimal(char *str, int *num, int deflt);
23216561Salexstatic char *get_type(int type);
23319459Sjkhstatic int read_config(char *config_file);
23419459Sjkhstatic void reset_boot(void);
23537415Scharnierstatic void usage(void);
23616561Salex#if 0
23716561Salexstatic int hex(char *str, int *num, int deflt);
23816561Salexstatic int string(char *str, char **ans);
23916561Salex#endif
2404Srgrimes
24116561Salex
24216561Salexint
24316561Salexmain(int argc, char *argv[])
2444Srgrimes{
24510514Sjoerg	int	i;
2464Srgrimes
2474Srgrimes	for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
2484Srgrimes		if (*token++ != '-' || !*token)
2494Srgrimes			break;
2504Srgrimes		else { register int flag;
25116561Salex			for ( ; (flag = *token++) ; ) {
2524Srgrimes				switch (flag) {
2534Srgrimes				case '1':
2544Srgrimes					partition = 1;
2554Srgrimes					break;
2564Srgrimes				case '2':
2574Srgrimes					partition = 2;
2584Srgrimes					break;
2594Srgrimes				case '3':
2604Srgrimes					partition = 3;
2614Srgrimes					break;
26226421Sbrian				case '4':
26326421Sbrian					partition = 4;
26426421Sbrian					break;
2654Srgrimes				case 'a':
2664Srgrimes					a_flag = 1;
2674Srgrimes					break;
26819459Sjkh				case 'f':
26919459Sjkh					if (*token)
27019459Sjkh					{
27119459Sjkh					    f_flag = token;
27219459Sjkh					    token = "";
27319459Sjkh					}
27419459Sjkh					else
27519459Sjkh					{
27619459Sjkh					    if (argc == 1)
27737415Scharnier						usage();
27819459Sjkh					    --argc;
27919459Sjkh					    f_flag = *++argv;
28019459Sjkh					}
28119459Sjkh					/*
28219459Sjkh					 * u_flag is needed, because we're
28319459Sjkh					 * writing to the disk.
28419459Sjkh					 */
28519459Sjkh					u_flag = 1;
28619459Sjkh					break;
2874Srgrimes				case 'i':
2884Srgrimes					i_flag = 1;
2894Srgrimes				case 'u':
2904Srgrimes					u_flag = 1;
2914Srgrimes					break;
29219459Sjkh				case 't':
29319459Sjkh					t_flag = 1;
29419459Sjkh				case 'v':
29519459Sjkh					v_flag = 1;
29619459Sjkh					break;
2974Srgrimes				default:
29837415Scharnier					usage();
2994Srgrimes				}
3004Srgrimes			}
3014Srgrimes		}
3024Srgrimes	}
3034Srgrimes
3044Srgrimes	if (argc > 0)
30510514Sjoerg	{
30610514Sjoerg		static char realname[12];
3078871Srgrimes
30810514Sjoerg		if(strncmp(argv[0], "/dev", 4) == 0)
30910514Sjoerg			disk = argv[0];
31010514Sjoerg		else
31110514Sjoerg		{
31210514Sjoerg			snprintf(realname, 12, "/dev/r%s", argv[0]);
31310514Sjoerg			disk = realname;
31410514Sjoerg		}
31510514Sjoerg
31610514Sjoerg		if (open_disk(u_flag) < 0)
31737415Scharnier			err(1, "cannot open disk %s", disk);
31810514Sjoerg	}
31910514Sjoerg	else
32010514Sjoerg	{
32116561Salex		int i, rv = 0;
3224Srgrimes
32310514Sjoerg		for(i = 0; disks[i]; i++)
32410514Sjoerg		{
32510514Sjoerg			disk = disks[i];
32610514Sjoerg			rv = open_disk(u_flag);
32710514Sjoerg			if(rv != -2) break;
32810514Sjoerg		}
32910514Sjoerg		if(rv < 0)
33037415Scharnier			err(1, "cannot open any disk");
33110514Sjoerg	}
33210514Sjoerg
3334Srgrimes	printf("******* Working on device %s *******\n",disk);
33419459Sjkh
33519459Sjkh	if (f_flag)
3364Srgrimes	{
33719459Sjkh	    if (read_s0() || i_flag)
33819459Sjkh	    {
33919459Sjkh		reset_boot();
34019459Sjkh	    }
34119459Sjkh
34219459Sjkh	    if (!read_config(f_flag))
34319459Sjkh	    {
34419459Sjkh		exit(1);
34519459Sjkh	    }
34619459Sjkh	    if (v_flag)
34719459Sjkh	    {
34819459Sjkh		print_s0(-1);
34919459Sjkh	    }
35019459Sjkh	    if (!t_flag)
35119459Sjkh	    {
35219459Sjkh		write_s0();
35319459Sjkh	    }
3544Srgrimes	}
3554Srgrimes	else
3564Srgrimes	{
35719459Sjkh	    if(u_flag)
35819459Sjkh	    {
35919459Sjkh		get_params_to_use();
36019459Sjkh	    }
36119459Sjkh	    else
36219459Sjkh	    {
3634Srgrimes		print_params();
36419459Sjkh	    }
3654Srgrimes
36619459Sjkh	    if (read_s0())
3674Srgrimes		init_sector0(1);
3684Srgrimes
36920061Ssos	    printf("Media sector size is %d\n", secsize);
37019459Sjkh	    printf("Warning: BIOS sector numbering starts with sector 1\n");
37119459Sjkh	    printf("Information from DOS bootblock is:\n");
37219459Sjkh	    if (partition == -1)
37326421Sbrian		for (i = 1; i <= NDOSPART; i++)
37419459Sjkh		    change_part(i);
37519459Sjkh	    else
3764Srgrimes		change_part(partition);
3774Srgrimes
37819459Sjkh	    if (u_flag || a_flag)
3794Srgrimes		change_active(partition);
3804Srgrimes
38119459Sjkh	    if (u_flag || a_flag) {
38219459Sjkh		if (!t_flag)
38319459Sjkh		{
38419459Sjkh		    printf("\nWe haven't changed the partition table yet.  ");
38519459Sjkh		    printf("This is your last chance.\n");
38619459Sjkh		}
3874Srgrimes		print_s0(-1);
38819459Sjkh		if (!t_flag)
38919459Sjkh		{
39019459Sjkh		    if (ok("Should we write new partition table?"))
3914Srgrimes			write_s0();
39219459Sjkh		}
39319459Sjkh		else
39419459Sjkh		{
39519459Sjkh		    printf("\n-t flag specified -- partition table not written.\n");
39619459Sjkh		}
39719459Sjkh	    }
3984Srgrimes	}
3994Srgrimes
4004Srgrimes	exit(0);
40137415Scharnier}
4024Srgrimes
40337415Scharnierstatic void
40437415Scharnierusage()
40537415Scharnier{
40637415Scharnier	fprintf(stderr,
40737415Scharnier "usage: fdisk {-a|-i|-u} [-f <config file> [-t] [-v]] [-{1,2,3,4}] [disk]\n");
40837415Scharnier        exit(1);
4094Srgrimes}
4104Srgrimes
41116561Salexstatic void
41216561Salexprint_s0(int which)
4134Srgrimes{
4144Srgrimesint	i;
4154Srgrimes
4164Srgrimes	print_params();
4174Srgrimes	printf("Information from DOS bootblock is:\n");
4184Srgrimes	if (which == -1)
41926421Sbrian		for (i = 1; i <= NDOSPART; i++)
4204Srgrimes			printf("%d: ", i), print_part(i);
4214Srgrimes	else
4224Srgrimes		print_part(which);
4234Srgrimes}
4244Srgrimes
4254Srgrimesstatic struct dos_partition mtpart = { 0 };
4264Srgrimes
42716561Salexstatic void
42816561Salexprint_part(int i)
4294Srgrimes{
43026389Sgibbs	struct	  dos_partition *partp;
43126389Sgibbs	u_int64_t part_mb;
4324Srgrimes
43326421Sbrian	partp = ((struct dos_partition *) &mboot.parts) + i - 1;
4344Srgrimes
4354Srgrimes	if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
4364Srgrimes		printf("<UNUSED>\n");
4374Srgrimes		return;
4384Srgrimes	}
43926389Sgibbs	/*
44026389Sgibbs	 * Be careful not to overflow.
44126389Sgibbs	 */
44226389Sgibbs	part_mb = partp->dp_size;
44326389Sgibbs	part_mb *= secsize;
44426389Sgibbs	part_mb /= (1024 * 1024);
4454Srgrimes	printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
44637244Sbde	printf("    start %lu, size %lu (%qd Meg), flag %x%s\n",
44737244Sbde		(u_long)partp->dp_start,
44837244Sbde		(u_long)partp->dp_size,
44926389Sgibbs		part_mb,
45034952Sobrien		partp->dp_flag,
45134952Sobrien		partp->dp_flag == ACTIVE ? " (active)" : "");
4524Srgrimes	printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
4534Srgrimes		,DPCYL(partp->dp_scyl, partp->dp_ssect)
4544Srgrimes		,DPSECT(partp->dp_ssect)
4554Srgrimes		,partp->dp_shd
4564Srgrimes		,DPCYL(partp->dp_ecyl, partp->dp_esect)
4574Srgrimes		,DPSECT(partp->dp_esect)
4584Srgrimes		,partp->dp_ehd);
4594Srgrimes}
4604Srgrimes
46119459Sjkh
46216561Salexstatic void
46319459Sjkhinit_boot(void)
46419459Sjkh{
46519459Sjkh	memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
46619459Sjkh	mboot.signature = BOOT_MAGIC;
46719459Sjkh}
46819459Sjkh
46919459Sjkh
47019459Sjkhstatic void
47116561Salexinit_sector0(unsigned long start)
4724Srgrimes{
4734Srgrimesstruct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
47416561Salexunsigned long size = disksecs - start;
4754Srgrimes
47619459Sjkh	init_boot();
4774Srgrimes
4784Srgrimes	partp->dp_typ = DOSPTYP_386BSD;
4794Srgrimes	partp->dp_flag = ACTIVE;
4804Srgrimes	partp->dp_start = start;
4814Srgrimes	partp->dp_size = size;
4824Srgrimes
48318915Sbde	dos(partp->dp_start, partp->dp_size,
48418915Sbde	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
48518915Sbde	dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
48618915Sbde	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
4874Srgrimes}
4884Srgrimes
48916561Salexstatic void
49016561Salexchange_part(int i)
4914Srgrimes{
49226421Sbrianstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i - 1;
4934Srgrimes
4944Srgrimes    printf("The data for partition %d is:\n", i);
4954Srgrimes    print_part(i);
4964Srgrimes
4974Srgrimes    if (u_flag && ok("Do you want to change it?")) {
4984Srgrimes	int tmp;
4994Srgrimes
5004Srgrimes	if (i_flag) {
5014Srgrimes		bzero((char *)partp, sizeof (struct dos_partition));
50226421Sbrian		if (i == 4) {
5034Srgrimes			init_sector0(1);
50426421Sbrian			printf("\nThe static data for the DOS partition 4 has been reinitialized to:\n");
5054Srgrimes			print_part(i);
5064Srgrimes		}
5074Srgrimes	}
5084Srgrimes
5094Srgrimes	do {
51034952Sobrien		Decimal("sysid (165=FreeBSD)", partp->dp_typ, tmp);
5114Srgrimes		Decimal("start", partp->dp_start, tmp);
5124Srgrimes		Decimal("size", partp->dp_size, tmp);
5134Srgrimes
51436262Sjraynard		if (ok("Explicitly specify beg/end address ?"))
5154Srgrimes		{
5164Srgrimes			int	tsec,tcyl,thd;
5174Srgrimes			tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
5184Srgrimes			thd = partp->dp_shd;
5194Srgrimes			tsec = DPSECT(partp->dp_ssect);
5204Srgrimes			Decimal("beginning cylinder", tcyl, tmp);
5214Srgrimes			Decimal("beginning head", thd, tmp);
5224Srgrimes			Decimal("beginning sector", tsec, tmp);
5234Srgrimes			partp->dp_scyl = DOSCYL(tcyl);
5244Srgrimes			partp->dp_ssect = DOSSECT(tsec,tcyl);
5254Srgrimes			partp->dp_shd = thd;
5264Srgrimes
5274Srgrimes			tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
5284Srgrimes			thd = partp->dp_ehd;
5294Srgrimes			tsec = DPSECT(partp->dp_esect);
5304Srgrimes			Decimal("ending cylinder", tcyl, tmp);
5314Srgrimes			Decimal("ending head", thd, tmp);
5324Srgrimes			Decimal("ending sector", tsec, tmp);
5334Srgrimes			partp->dp_ecyl = DOSCYL(tcyl);
5344Srgrimes			partp->dp_esect = DOSSECT(tsec,tcyl);
5354Srgrimes			partp->dp_ehd = thd;
5364Srgrimes		} else {
53718915Sbde			dos(partp->dp_start, partp->dp_size,
53818915Sbde			    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
53918915Sbde			dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
54018915Sbde			    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
5414Srgrimes		}
5428871Srgrimes
5434Srgrimes		print_part(i);
5444Srgrimes	} while (!ok("Are we happy with this entry?"));
5454Srgrimes    }
5464Srgrimes}
5474Srgrimes
54816561Salexstatic void
5494Srgrimesprint_params()
5504Srgrimes{
5514Srgrimes	printf("parameters extracted from in-core disklabel are:\n");
5524Srgrimes	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
5534Srgrimes			,cyls,heads,sectors,cylsecs);
5544Srgrimes	if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
55520061Ssos		printf("Figures below won't work with BIOS for partitions not in cyl 1\n");
5564Srgrimes	printf("parameters to be used for BIOS calculations are:\n");
5574Srgrimes	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
5584Srgrimes		,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
5594Srgrimes}
5604Srgrimes
56116561Salexstatic void
56216561Salexchange_active(int which)
5634Srgrimes{
5644Srgrimesint i;
56526421Sbrianint active = 4, tmp;
5664Srgrimesstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
5674Srgrimes
5684Srgrimes	if (a_flag && which != -1)
5694Srgrimes		active = which;
5703723Sbde	if (!ok("Do you want to change the active partition?"))
5713723Sbde		return;
57234952Sobriensetactive:
57334952Sobrien	active = 4;
57434952Sobrien	do {
5753723Sbde		Decimal("active partition", active, tmp);
57634952Sobrien		if (active < 1 || 4 < active) {
57734952Sobrien			printf("Active partition number must be in range 1-4."
57834952Sobrien					"  Try again.\n");
57934952Sobrien			goto setactive;
58034952Sobrien		}
58134952Sobrien	} while (!ok("Are you happy with this choice"));
5824Srgrimes	for (i = 0; i < NDOSPART; i++)
5834Srgrimes		partp[i].dp_flag = 0;
58426421Sbrian	if (active > 0 && active <= NDOSPART)
58526421Sbrian		partp[active-1].dp_flag = ACTIVE;
5864Srgrimes}
5874Srgrimes
58816561Salexvoid
5894Srgrimesget_params_to_use()
5904Srgrimes{
5914Srgrimes	int	tmp;
5924Srgrimes	print_params();
5934Srgrimes	if (ok("Do you want to change our idea of what BIOS thinks ?"))
5944Srgrimes	{
5954Srgrimes		do
5964Srgrimes		{
5974Srgrimes			Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
5984Srgrimes			Decimal("BIOS's idea of #heads", dos_heads, tmp);
5994Srgrimes			Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
6004Srgrimes			dos_cylsecs = dos_heads * dos_sectors;
6014Srgrimes			print_params();
6024Srgrimes		}
6034Srgrimes		while(!ok("Are you happy with this choice"));
6044Srgrimes	}
6054Srgrimes}
6064Srgrimes
60719459Sjkh
6084Srgrimes/***********************************************\
6094Srgrimes* Change real numbers into strange dos numbers	*
6104Srgrimes\***********************************************/
61116561Salexstatic void
61218915Sbdedos(sec, size, c, s, h)
61318915Sbdeint sec, size;
6144Srgrimesunsigned char *c, *s, *h;
6154Srgrimes{
6164Srgrimesint cy;
6174Srgrimesint hd;
6184Srgrimes
61918915Sbde	if (sec == 0 && size == 0) {
6203723Sbde		*s = *c = *h = 0;
6213723Sbde		return;
6223723Sbde	}
6233723Sbde
6244Srgrimes	cy = sec / ( dos_cylsecs );
6254Srgrimes	sec = sec - cy * ( dos_cylsecs );
6264Srgrimes
6274Srgrimes	hd = sec / dos_sectors;
6284Srgrimes	sec = (sec - hd * dos_sectors) + 1;
6294Srgrimes
6304Srgrimes	*h = hd;
6314Srgrimes	*c = cy & 0xff;
6324Srgrimes	*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
6334Srgrimes}
6344Srgrimes
6354Srgrimesint fd;
6364Srgrimes
6374Srgrimes	/* Getting device status */
6384Srgrimes
63916561Salexstatic int
64016561Salexopen_disk(int u_flag)
6414Srgrimes{
6424Srgrimesstruct stat 	st;
6434Srgrimes
6448871Srgrimes	if (stat(disk, &st) == -1) {
64537415Scharnier		warnx("can't get file status of %s", disk);
6464Srgrimes		return -1;
6472810Sbde	}
6482810Sbde	if ( !(st.st_mode & S_IFCHR) )
64937415Scharnier		warnx("device %s is not character special", disk);
6503723Sbde	if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) {
65110514Sjoerg		if(errno == ENXIO)
65210514Sjoerg			return -2;
65337415Scharnier		warnx("can't open device %s", disk);
6544Srgrimes		return -1;
6554Srgrimes	}
6564Srgrimes	if (get_params(0) == -1) {
65737415Scharnier		warnx("can't get disk parameters on %s", disk);
6584Srgrimes		return -1;
6594Srgrimes	}
6604Srgrimes	return fd;
6614Srgrimes}
6624Srgrimes
66316561Salexstatic ssize_t
66416561Salexread_disk(off_t sector, void *buf)
6654Srgrimes{
6664Srgrimes	lseek(fd,(sector * 512), 0);
66720061Ssos	if( secsize == 0 )
66820061Ssos		for( secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; secsize *= 2 )
66920061Ssos			{
67020061Ssos			/* try the read */
67120061Ssos			int size = read(fd, buf, secsize);
67220061Ssos			if( size == secsize )
67320061Ssos				/* it worked so return */
67420061Ssos				return secsize;
67520061Ssos			}
67620061Ssos	else
67720061Ssos		return read( fd, buf, secsize );
67820061Ssos
67920061Ssos	/* we failed to read at any of the sizes */
68020061Ssos	return -1;
6814Srgrimes}
6824Srgrimes
68316561Salexstatic ssize_t
68416561Salexwrite_disk(off_t sector, void *buf)
6854Srgrimes{
6864Srgrimes	lseek(fd,(sector * 512), 0);
68720061Ssos	/* write out in the size that the read_disk found worked */
68820061Ssos	return write(fd, buf, secsize);
6894Srgrimes}
6904Srgrimes
69116561Salexstatic int
69216561Salexget_params()
6934Srgrimes{
6944Srgrimes
6954Srgrimes    if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
69637415Scharnier	warnx("can't get disk parameters on %s; supplying dummy ones", disk);
6972810Sbde	dos_cyls = cyls = 1;
6982810Sbde	dos_heads = heads = 1;
6992810Sbde	dos_sectors = sectors = 1;
7002810Sbde	dos_cylsecs = cylsecs = heads * sectors;
7012810Sbde	disksecs = cyls * heads * sectors;
7022810Sbde	return disksecs;
7034Srgrimes    }
7044Srgrimes
7054Srgrimes    dos_cyls = cyls = disklabel.d_ncylinders;
7064Srgrimes    dos_heads = heads = disklabel.d_ntracks;
7074Srgrimes    dos_sectors = sectors = disklabel.d_nsectors;
7084Srgrimes    dos_cylsecs = cylsecs = heads * sectors;
7094Srgrimes    disksecs = cyls * heads * sectors;
7104Srgrimes
7114Srgrimes    return (disksecs);
7124Srgrimes}
7134Srgrimes
7144Srgrimes
71516561Salexstatic int
7164Srgrimesread_s0()
7174Srgrimes{
7188871Srgrimes	if (read_disk(0, (char *) mboot.bootinst) == -1) {
71937415Scharnier		warnx("can't read fdisk partition table");
7204Srgrimes		return -1;
7214Srgrimes	}
7224Srgrimes	if (mboot.signature != BOOT_MAGIC) {
72337415Scharnier		warnx("invalid fdisk partition table found");
7244Srgrimes		/* So should we initialize things */
7254Srgrimes		return -1;
7264Srgrimes	}
7274Srgrimes	return 0;
7284Srgrimes}
7294Srgrimes
73016561Salexstatic int
7314Srgrimeswrite_s0()
7324Srgrimes{
7334Srgrimes	int	flag;
7344Srgrimes	if (iotest) {
7354Srgrimes		print_s0(-1);
7364Srgrimes		return 0;
7374Srgrimes	}
7384Srgrimes	/*
7394Srgrimes	 * write enable label sector before write (if necessary),
7404Srgrimes	 * disable after writing.
7414Srgrimes	 * needed if the disklabel protected area also protects
7424Srgrimes	 * sector 0. (e.g. empty disk)
7434Srgrimes	 */
7444Srgrimes	flag = 1;
74511143Sjulian#ifdef NOT_NOW
7464Srgrimes	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
74737415Scharnier		warn("ioctl DIOCWLABEL");
74811143Sjulian#endif
7498871Srgrimes	if (write_disk(0, (char *) mboot.bootinst) == -1) {
75037415Scharnier		warnx("can't write fdisk partition table");
7514Srgrimes		return -1;
7524Srgrimes	flag = 0;
75311143Sjulian#ifdef NOT_NOW
7544Srgrimes	(void) ioctl(fd, DIOCWLABEL, &flag);
75511143Sjulian#endif
7564Srgrimes	}
75716561Salex	return(0);
7584Srgrimes}
7594Srgrimes
7604Srgrimes
76116561Salexstatic int
7624Srgrimesok(str)
7634Srgrimeschar *str;
7644Srgrimes{
7654Srgrimes	printf("%s [n] ", str);
7664Srgrimes	fgets(lbuf, LBUF, stdin);
7674Srgrimes	lbuf[strlen(lbuf)-1] = 0;
7684Srgrimes
7694Srgrimes	if (*lbuf &&
7704Srgrimes		(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
7714Srgrimes		 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
7724Srgrimes		return 1;
7734Srgrimes	else
7744Srgrimes		return 0;
7754Srgrimes}
7764Srgrimes
77716561Salexstatic int
77816561Salexdecimal(char *str, int *num, int deflt)
7794Srgrimes{
7804Srgrimesint acc = 0, c;
7814Srgrimeschar *cp;
7824Srgrimes
7834Srgrimes	while (1) {
7844Srgrimes		printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
7854Srgrimes		fgets(lbuf, LBUF, stdin);
7864Srgrimes		lbuf[strlen(lbuf)-1] = 0;
7874Srgrimes
7884Srgrimes		if (!*lbuf)
7894Srgrimes			return 0;
7904Srgrimes
7914Srgrimes		cp = lbuf;
7924Srgrimes		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
7934Srgrimes		if (!c)
7944Srgrimes			return 0;
79516561Salex		while ((c = *cp++)) {
7964Srgrimes			if (c <= '9' && c >= '0')
7974Srgrimes				acc = acc * 10 + c - '0';
7984Srgrimes			else
7994Srgrimes				break;
8004Srgrimes		}
8014Srgrimes		if (c == ' ' || c == '\t')
8024Srgrimes			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8034Srgrimes		if (!c) {
8044Srgrimes			*num = acc;
8054Srgrimes			return 1;
8064Srgrimes		} else
80734952Sobrien			printf("%s is an invalid decimal number.  Try again.\n",
8084Srgrimes				lbuf);
8094Srgrimes	}
8104Srgrimes
8114Srgrimes}
8124Srgrimes
81316561Salex#if 0
81416561Salexstatic int
81516561Salexhex(char *str, int *num, int deflt)
8164Srgrimes{
8174Srgrimesint acc = 0, c;
8184Srgrimeschar *cp;
8194Srgrimes
8204Srgrimes	while (1) {
8214Srgrimes		printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
8224Srgrimes		fgets(lbuf, LBUF, stdin);
8234Srgrimes		lbuf[strlen(lbuf)-1] = 0;
8244Srgrimes
8254Srgrimes		if (!*lbuf)
8264Srgrimes			return 0;
8274Srgrimes
8284Srgrimes		cp = lbuf;
8294Srgrimes		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8304Srgrimes		if (!c)
8314Srgrimes			return 0;
83216561Salex		while ((c = *cp++)) {
8334Srgrimes			if (c <= '9' && c >= '0')
8344Srgrimes				acc = (acc << 4) + c - '0';
8354Srgrimes			else if (c <= 'f' && c >= 'a')
8364Srgrimes				acc = (acc << 4) + c - 'a' + 10;
8374Srgrimes			else if (c <= 'F' && c >= 'A')
8384Srgrimes				acc = (acc << 4) + c - 'A' + 10;
8394Srgrimes			else
8404Srgrimes				break;
8414Srgrimes		}
8424Srgrimes		if (c == ' ' || c == '\t')
8434Srgrimes			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8444Srgrimes		if (!c) {
8454Srgrimes			*num = acc;
8464Srgrimes			return 1;
8474Srgrimes		} else
84834952Sobrien			printf("%s is an invalid hex number.  Try again.\n",
8494Srgrimes				lbuf);
8504Srgrimes	}
8514Srgrimes
8524Srgrimes}
8534Srgrimes
85416561Salexstatic int
85516561Salexstring(char *str, char **ans)
8564Srgrimes{
8574Srgrimesint c;
8584Srgrimeschar *cp = lbuf;
8594Srgrimes
8604Srgrimes	while (1) {
8614Srgrimes		printf("Supply a string value for \"%s\" [%s] ", str, *ans);
8624Srgrimes		fgets(lbuf, LBUF, stdin);
8634Srgrimes		lbuf[strlen(lbuf)-1] = 0;
8644Srgrimes
8654Srgrimes		if (!*lbuf)
8664Srgrimes			return 0;
8674Srgrimes
8684Srgrimes		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8694Srgrimes		if (c == '"') {
8704Srgrimes			c = *++cp;
8714Srgrimes			*ans = cp;
8724Srgrimes			while ((c = *cp) && c != '"') cp++;
8734Srgrimes		} else {
8744Srgrimes			*ans = cp;
8754Srgrimes			while ((c = *cp) && c != ' ' && c != '\t') cp++;
8764Srgrimes		}
8774Srgrimes
8784Srgrimes		if (c)
8794Srgrimes			*cp = 0;
8804Srgrimes		return 1;
8814Srgrimes	}
8824Srgrimes}
88316561Salex#endif
8844Srgrimes
88516561Salexstatic char *
88616561Salexget_type(int type)
8874Srgrimes{
8884Srgrimes	int	numentries = (sizeof(part_types)/sizeof(struct part_type));
8894Srgrimes	int	counter = 0;
8904Srgrimes	struct	part_type *ptr = part_types;
8914Srgrimes
8928871Srgrimes
8934Srgrimes	while(counter < numentries)
8944Srgrimes	{
8954Srgrimes		if(ptr->type == type)
8964Srgrimes		{
8974Srgrimes			return(ptr->name);
8984Srgrimes		}
8994Srgrimes		ptr++;
9004Srgrimes		counter++;
9014Srgrimes	}
9024Srgrimes	return("unknown");
9034Srgrimes}
90419459Sjkh
90519459Sjkh
90619459Sjkhstatic void
90719459Sjkhparse_config_line(line, command)
90819459Sjkh    char	*line;
90919459Sjkh    CMD		*command;
91019459Sjkh{
91119459Sjkh    char	*cp, *end;
91219459Sjkh
91319459Sjkh    cp = line;
91419459Sjkh    while (1)	/* dirty trick used to insure one exit point for this
91519459Sjkh		   function */
91619459Sjkh    {
91719459Sjkh	memset(command, 0, sizeof(*command));
91819459Sjkh
91919459Sjkh	while (isspace(*cp)) ++cp;
92019459Sjkh	if (*cp == '\0' || *cp == '#')
92119459Sjkh	{
92219459Sjkh	    break;
92319459Sjkh	}
92419459Sjkh	command->cmd = *cp++;
92519459Sjkh
92619459Sjkh	/*
92719459Sjkh	 * Parse args
92819459Sjkh	 */
92919459Sjkh	while (1)
93019459Sjkh	{
93119459Sjkh	    while (isspace(*cp)) ++cp;
93219459Sjkh	    if (*cp == '#')
93319459Sjkh	    {
93419459Sjkh		break;		/* found comment */
93519459Sjkh	    }
93619459Sjkh	    if (isalpha(*cp))
93719459Sjkh	    {
93819459Sjkh		command->args[command->n_args].argtype = *cp++;
93919459Sjkh	    }
94019459Sjkh	    if (!isdigit(*cp))
94119459Sjkh	    {
94219459Sjkh		break;		/* assume end of line */
94319459Sjkh	    }
94419459Sjkh	    end = NULL;
94519459Sjkh	    command->args[command->n_args].arg_val = strtol(cp, &end, 0);
94619459Sjkh	    if (cp == end)
94719459Sjkh	    {
94819459Sjkh		break;		/* couldn't parse number */
94919459Sjkh	    }
95019459Sjkh	    cp = end;
95119459Sjkh	    command->n_args++;
95219459Sjkh	}
95319459Sjkh	break;
95419459Sjkh    }
95519459Sjkh}
95619459Sjkh
95719459Sjkh
95819459Sjkhstatic int
95919459Sjkhprocess_geometry(command)
96019459Sjkh    CMD		*command;
96119459Sjkh{
96219459Sjkh    int		status = 1, i;
96319459Sjkh
96419459Sjkh    while (1)
96519459Sjkh    {
96619459Sjkh	geom_processed = 1;
96719459Sjkh	if (part_processed)
96819459Sjkh	{
96937415Scharnier	    warnx(
97037415Scharnier	"ERROR line %d: the geometry specification line must occur before\n\
97137415Scharnier    all partition specifications",
97237415Scharnier		    current_line_number);
97319459Sjkh	    status = 0;
97419459Sjkh	    break;
97519459Sjkh	}
97619459Sjkh	if (command->n_args != 3)
97719459Sjkh	{
97837415Scharnier	    warnx("ERROR line %d: incorrect number of geometry args",
97937415Scharnier		    current_line_number);
98019459Sjkh	    status = 0;
98119459Sjkh	    break;
98219459Sjkh	}
98319459Sjkh	dos_cyls = -1;
98419459Sjkh	dos_heads = -1;
98519459Sjkh	dos_sectors = -1;
98619459Sjkh	for (i = 0; i < 3; ++i)
98719459Sjkh	{
98819459Sjkh	    switch (command->args[i].argtype)
98919459Sjkh	    {
99019459Sjkh	    case 'c':
99119459Sjkh		dos_cyls = command->args[i].arg_val;
99219459Sjkh		break;
99319459Sjkh	    case 'h':
99419459Sjkh		dos_heads = command->args[i].arg_val;
99519459Sjkh		break;
99619459Sjkh	    case 's':
99719459Sjkh		dos_sectors = command->args[i].arg_val;
99819459Sjkh		break;
99919459Sjkh	    default:
100037415Scharnier		warnx(
100137415Scharnier		"ERROR line %d: unknown geometry arg type: '%c' (0x%02x)",
100237415Scharnier			current_line_number, command->args[i].argtype,
100319459Sjkh			command->args[i].argtype);
100419459Sjkh		status = 0;
100519459Sjkh		break;
100619459Sjkh	    }
100719459Sjkh	}
100819459Sjkh	if (status == 0)
100919459Sjkh	{
101019459Sjkh	    break;
101119459Sjkh	}
101219459Sjkh
101319459Sjkh	dos_cylsecs = dos_heads * dos_sectors;
101419459Sjkh
101519459Sjkh	/*
101619459Sjkh	 * Do sanity checks on parameter values
101719459Sjkh	 */
101819459Sjkh	if (dos_cyls < 0)
101919459Sjkh	{
102037415Scharnier	    warnx("ERROR line %d: number of cylinders not specified",
102137415Scharnier		    current_line_number);
102219459Sjkh	    status = 0;
102319459Sjkh	}
102419459Sjkh	if (dos_cyls == 0 || dos_cyls > 1024)
102519459Sjkh	{
102637415Scharnier	    warnx(
102737415Scharnier	"WARNING line %d: number of cylinders (%d) may be out-of-range\n\
102819459Sjkh    (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\
102937415Scharnier    is dedicated to FreeBSD)",
103037415Scharnier		    current_line_number, dos_cyls);
103119459Sjkh	}
103219459Sjkh
103319459Sjkh	if (dos_heads < 0)
103419459Sjkh	{
103537415Scharnier	    warnx("ERROR line %d: number of heads not specified",
103637415Scharnier		    current_line_number);
103719459Sjkh	    status = 0;
103819459Sjkh	}
103919459Sjkh	else if (dos_heads < 1 || dos_heads > 256)
104019459Sjkh	{
104137415Scharnier	    warnx("ERROR line %d: number of heads must be within (1-256)",
104237415Scharnier		    current_line_number);
104319459Sjkh	    status = 0;
104419459Sjkh	}
104519459Sjkh
104619459Sjkh	if (dos_sectors < 0)
104719459Sjkh	{
104837415Scharnier	    warnx("ERROR line %d: number of sectors not specified",
104937415Scharnier		    current_line_number);
105019459Sjkh	    status = 0;
105119459Sjkh	}
105219459Sjkh	else if (dos_sectors < 1 || dos_sectors > 63)
105319459Sjkh	{
105437415Scharnier	    warnx("ERROR line %d: number of sectors must be within (1-63)",
105537415Scharnier		    current_line_number);
105619459Sjkh	    status = 0;
105719459Sjkh	}
105819459Sjkh
105919459Sjkh	break;
106019459Sjkh    }
106119459Sjkh    return (status);
106219459Sjkh}
106319459Sjkh
106419459Sjkh
106519459Sjkhstatic int
106619459Sjkhprocess_partition(command)
106719459Sjkh    CMD		*command;
106819459Sjkh{
106919459Sjkh    int				status = 0, partition;
107019459Sjkh    unsigned long		chunks, adj_size, max_end;
107119459Sjkh    struct dos_partition	*partp;
107219459Sjkh
107319459Sjkh    while (1)
107419459Sjkh    {
107519459Sjkh	part_processed = 1;
107619459Sjkh	if (command->n_args != 4)
107719459Sjkh	{
107837415Scharnier	    warnx("ERROR line %d: incorrect number of partition args",
107937415Scharnier		    current_line_number);
108019459Sjkh	    break;
108119459Sjkh	}
108219459Sjkh	partition = command->args[0].arg_val;
108326421Sbrian	if (partition < 1 || partition > 4)
108419459Sjkh	{
108537415Scharnier	    warnx("ERROR line %d: invalid partition number %d",
108637415Scharnier		    current_line_number, partition);
108719459Sjkh	    break;
108819459Sjkh	}
108926421Sbrian	partp = ((struct dos_partition *) &mboot.parts) + partition - 1;
109019459Sjkh	bzero((char *)partp, sizeof (struct dos_partition));
109119459Sjkh	partp->dp_typ = command->args[1].arg_val;
109219459Sjkh	partp->dp_start = command->args[2].arg_val;
109319459Sjkh	partp->dp_size = command->args[3].arg_val;
109419459Sjkh	max_end = partp->dp_start + partp->dp_size;
109519459Sjkh
109619459Sjkh	if (partp->dp_typ == 0)
109719459Sjkh	{
109819459Sjkh	    /*
109919459Sjkh	     * Get out, the partition is marked as unused.
110019459Sjkh	     */
110119459Sjkh	    /*
110219459Sjkh	     * Insure that it's unused.
110319459Sjkh	     */
110419459Sjkh	    bzero((char *)partp, sizeof (struct dos_partition));
110519459Sjkh	    status = 1;
110619459Sjkh	    break;
110719459Sjkh	}
110819459Sjkh
110919459Sjkh	/*
111019459Sjkh	 * Adjust start upwards, if necessary, to fall on an head boundary.
111119459Sjkh	 */
111219459Sjkh	if (partp->dp_start % dos_sectors != 0)
111319459Sjkh	{
111419459Sjkh	    adj_size =
111519459Sjkh		(partp->dp_start / dos_sectors + 1) * dos_sectors;
111619459Sjkh	    if (adj_size > max_end)
111719459Sjkh	    {
111819459Sjkh		/*
111919459Sjkh		 * Can't go past end of partition
112019459Sjkh		 */
112137415Scharnier		warnx(
112237415Scharnier	"ERROR line %d: unable to adjust start of partition %d to fall on\n\
112337415Scharnier    a cylinder boundary",
112437415Scharnier			current_line_number, partition);
112519459Sjkh		break;
112619459Sjkh	    }
112737415Scharnier	    warnx(
112837415Scharnier	"WARNING: adjusting start offset of partition '%d' from %lu\n\
112937415Scharnier    to %lu, to round to an head boundary",
113037415Scharnier		    partition, (u_long)partp->dp_start, adj_size);
113119459Sjkh	    partp->dp_start = adj_size;
113219459Sjkh	}
113319459Sjkh
113419459Sjkh	/*
113519459Sjkh	 * Adjust size downwards, if necessary, to fall on a cylinder
113619459Sjkh	 * boundary.
113719459Sjkh	 */
113819459Sjkh	chunks =
113919459Sjkh	    ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs;
114019459Sjkh	adj_size = chunks - partp->dp_start;
114119459Sjkh	if (adj_size != partp->dp_size)
114219459Sjkh	{
114337415Scharnier	    warnx(
114437415Scharnier	"WARNING: adjusting size of partition '%d' from %lu to %lu,\n\
114537415Scharnier    to round to a cylinder boundary",
114637415Scharnier		    partition, (u_long)partp->dp_size, adj_size);
114719459Sjkh	    if (chunks > 0)
114819459Sjkh	    {
114919459Sjkh		partp->dp_size = adj_size;
115019459Sjkh	    }
115119459Sjkh	    else
115219459Sjkh	    {
115319459Sjkh		partp->dp_size = 0;
115419459Sjkh	    }
115519459Sjkh	}
115619459Sjkh	if (partp->dp_size < 1)
115719459Sjkh	{
115837415Scharnier	    warnx("ERROR line %d: size for partition '%d' is zero",
115937415Scharnier		    current_line_number, partition);
116019459Sjkh	    break;
116119459Sjkh	}
116219459Sjkh
116319459Sjkh	dos(partp->dp_start, partp->dp_size,
116419459Sjkh	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
116519459Sjkh	dos(partp->dp_start+partp->dp_size - 1, partp->dp_size,
116619459Sjkh	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
116719459Sjkh	status = 1;
116819459Sjkh	break;
116919459Sjkh    }
117019459Sjkh    return (status);
117119459Sjkh}
117219459Sjkh
117319459Sjkh
117419459Sjkhstatic int
117519459Sjkhprocess_active(command)
117619459Sjkh    CMD		*command;
117719459Sjkh{
117819459Sjkh    int				status = 0, partition, i;
117919459Sjkh    struct dos_partition	*partp;
118019459Sjkh
118119459Sjkh    while (1)
118219459Sjkh    {
118319459Sjkh	active_processed = 1;
118419459Sjkh	if (command->n_args != 1)
118519459Sjkh	{
118637415Scharnier	    warnx("ERROR line %d: incorrect number of active args",
118737415Scharnier		    current_line_number);
118819459Sjkh	    status = 0;
118919459Sjkh	    break;
119019459Sjkh	}
119119459Sjkh	partition = command->args[0].arg_val;
119226421Sbrian	if (partition < 1 || partition > 4)
119319459Sjkh	{
119437415Scharnier	    warnx("ERROR line %d: invalid partition number %d",
119537415Scharnier		    current_line_number, partition);
119619459Sjkh	    break;
119719459Sjkh	}
119819459Sjkh	/*
119919459Sjkh	 * Reset active partition
120019459Sjkh	 */
120119459Sjkh	partp = ((struct dos_partition *) &mboot.parts);
120219459Sjkh	for (i = 0; i < NDOSPART; i++)
120319459Sjkh	    partp[i].dp_flag = 0;
120426421Sbrian	partp[partition-1].dp_flag = ACTIVE;
120519459Sjkh
120619459Sjkh	status = 1;
120719459Sjkh	break;
120819459Sjkh    }
120919459Sjkh    return (status);
121019459Sjkh}
121119459Sjkh
121219459Sjkh
121319459Sjkhstatic int
121419459Sjkhprocess_line(line)
121519459Sjkh    char	*line;
121619459Sjkh{
121719459Sjkh    CMD		command;
121819459Sjkh    int		status = 1;
121919459Sjkh
122019459Sjkh    while (1)
122119459Sjkh    {
122219459Sjkh	parse_config_line(line, &command);
122319459Sjkh	switch (command.cmd)
122419459Sjkh	{
122519459Sjkh	case 0:
122619459Sjkh	    /*
122719459Sjkh	     * Comment or blank line
122819459Sjkh	     */
122919459Sjkh	    break;
123019459Sjkh	case 'g':
123119459Sjkh	    /*
123219459Sjkh	     * Set geometry
123319459Sjkh	     */
123419459Sjkh	    status = process_geometry(&command);
123519459Sjkh	    break;
123619459Sjkh	case 'p':
123719459Sjkh	    status = process_partition(&command);
123819459Sjkh	    break;
123919459Sjkh	case 'a':
124019459Sjkh	    status = process_active(&command);
124119459Sjkh	    break;
124219459Sjkh	default:
124319459Sjkh	    status = 0;
124419459Sjkh	    break;
124519459Sjkh	}
124619459Sjkh	break;
124719459Sjkh    }
124819459Sjkh    return (status);
124919459Sjkh}
125019459Sjkh
125119459Sjkh
125219459Sjkhstatic int
125319459Sjkhread_config(config_file)
125419459Sjkh    char *config_file;
125519459Sjkh{
125619459Sjkh    FILE	*fp = NULL;
125719459Sjkh    int		status = 1;
125819459Sjkh    char	buf[1010];
125919459Sjkh
126019459Sjkh    while (1)	/* dirty trick used to insure one exit point for this
126119459Sjkh		   function */
126219459Sjkh    {
126319459Sjkh	if (strcmp(config_file, "-") != 0)
126419459Sjkh	{
126519459Sjkh	    /*
126619459Sjkh	     * We're not reading from stdin
126719459Sjkh	     */
126819459Sjkh	    if ((fp = fopen(config_file, "r")) == NULL)
126919459Sjkh	    {
127019459Sjkh		status = 0;
127119459Sjkh		break;
127219459Sjkh	    }
127319459Sjkh	}
127419459Sjkh	else
127519459Sjkh	{
127619459Sjkh	    fp = stdin;
127719459Sjkh	}
127819459Sjkh	current_line_number = 0;
127919459Sjkh	while (!feof(fp))
128019459Sjkh	{
128119459Sjkh	    if (fgets(buf, sizeof(buf), fp) == NULL)
128219459Sjkh	    {
128319459Sjkh		break;
128419459Sjkh	    }
128519459Sjkh	    ++current_line_number;
128619459Sjkh	    status = process_line(buf);
128719459Sjkh	    if (status == 0)
128819459Sjkh	    {
128919459Sjkh		break;
129019459Sjkh	    }
129119459Sjkh	}
129219459Sjkh	break;
129319459Sjkh    }
129419459Sjkh    if (fp)
129519459Sjkh    {
129619459Sjkh	/*
129719459Sjkh	 * It doesn't matter if we're reading from stdin, as we've reached EOF
129819459Sjkh	 */
129919459Sjkh	fclose(fp);
130019459Sjkh    }
130119459Sjkh    return (status);
130219459Sjkh}
130319459Sjkh
130419459Sjkh
130519459Sjkhstatic void
130619459Sjkhreset_boot(void)
130719459Sjkh{
130819459Sjkh    int				i;
130919459Sjkh    struct dos_partition	*partp;
131019459Sjkh
131119459Sjkh    init_boot();
131219459Sjkh    for (i = 0; i < 4; ++i)
131319459Sjkh    {
131419459Sjkh	partp = ((struct dos_partition *) &mboot.parts) + i;
131519459Sjkh	bzero((char *)partp, sizeof (struct dos_partition));
131619459Sjkh    }
131719459Sjkh}
1318