fdisk.c revision 20061
1145479Smp/*
259243Sobrien * Mach Operating System
359243Sobrien * Copyright (c) 1992 Carnegie Mellon University
459243Sobrien * All Rights Reserved.
559243Sobrien *
659243Sobrien * Permission to use, copy, modify and distribute this software and its
759243Sobrien * documentation is hereby granted, provided that both the copyright
859243Sobrien * notice and this permission notice appear in all copies of the
959243Sobrien * software, derivative works or modified versions, and any portions
1059243Sobrien * thereof, and that both notices appear in supporting documentation.
1159243Sobrien *
1259243Sobrien * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
1359243Sobrien * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
1459243Sobrien * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1559243Sobrien *
1659243Sobrien * Carnegie Mellon requests users of this software to return to
17100616Smp *
1859243Sobrien *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
1959243Sobrien *  School of Computer Science
2059243Sobrien *  Carnegie Mellon University
2159243Sobrien *  Pittsburgh PA 15213-3890
2259243Sobrien *
2359243Sobrien * any improvements or extensions that they make and grant Carnegie Mellon
2459243Sobrien * the rights to redistribute these changes.
2559243Sobrien */
2659243Sobrien
2759243Sobrien#include <sys/types.h>
2859243Sobrien#include <sys/disklabel.h>
2959243Sobrien#include <stdio.h>
3059243Sobrien#include <string.h>
3159243Sobrien#include <errno.h>
3259243Sobrien#include <sys/stat.h>
3359243Sobrien#include <sys/ioctl.h>
3459243Sobrien#include <fcntl.h>
35145479Smp#include <unistd.h>
3659243Sobrien
3759243Sobrienint iotest;
3859243Sobrien
3959243Sobrien#define LBUF 100
40145479Smpstatic char lbuf[LBUF];
41145479Smp
42145479Smp/*
43145479Smp *
44145479Smp * Ported to 386bsd by Julian Elischer  Thu Oct 15 20:26:46 PDT 1992
45131962Smp *
4659243Sobrien * 14-Dec-89  Robert Baron (rvb) at Carnegie-Mellon University
4759243Sobrien *	Copyright (c) 1989	Robert. V. Baron
4859243Sobrien *	Created.
4959243Sobrien */
5059243Sobrien
5159243Sobrien#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
5259243Sobrien#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
5359243Sobrien#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
5459243Sobrien
5559243Sobrien#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
5659243Sobrien
5759243Sobrien#define MAX_SEC_SIZE 2048	/* maximum section size that is supported */
5859243Sobrien#define MIN_SEC_SIZE 512	/* the sector size to start sensing at */
5959243Sobrienint secsize = 0;		/* the sensed sector size */
6059243Sobrien
6159243Sobrienconst char *disk;
6259243Sobrienconst char *disks[] =
6359243Sobrien{
6459243Sobrien  "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0
6559243Sobrien};
6659243Sobrien
6759243Sobrienchar *name;
6859243Sobrien
6959243Sobrienstruct disklabel disklabel;		/* disk parameters */
7059243Sobrien
7159243Sobrienint cyls, sectors, heads, cylsecs, disksecs;
72145479Smp
7359243Sobrienstruct mboot
7459243Sobrien{
7559243Sobrien	unsigned char padding[2]; /* force the longs to be long alligned */
7659243Sobrien	unsigned char bootinst[DOSPARTOFF];
7759243Sobrien	struct	dos_partition parts[4];
78145479Smp	unsigned short int	signature;
7959243Sobrien	/* room to read in MBRs that are bigger then DEV_BSIZE */
8059243Sobrien	unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE];
8159243Sobrien};
8259243Sobrienstruct mboot mboot;
8359243Sobrien
8459243Sobrien#define ACTIVE 0x80
8559243Sobrien#define BOOT_MAGIC 0xAA55
8659243Sobrien
8759243Sobrienint dos_cyls;
8859243Sobrienint dos_heads;
8959243Sobrienint dos_sectors;
9059243Sobrienint dos_cylsecs;
9159243Sobrien
9259243Sobrien#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
9359243Sobrien#define DOSCYL(c)	(c & 0xff)
9459243Sobrienstatic int partition = -1;
9559243Sobrien
9659243Sobrien
9759243Sobrien#define MAX_ARGS	10
9859243Sobrien
9959243Sobrienstatic int	current_line_number;
100145479Smp
10159243Sobrienstatic int	geom_processed = 0;
10259243Sobrienstatic int	part_processed = 0;
10359243Sobrienstatic int	active_processed = 0;
10459243Sobrien
10559243Sobrien
10659243Sobrientypedef struct cmd {
10759243Sobrien    char		cmd;
10859243Sobrien    int			n_args;
10959243Sobrien    struct arg {
11059243Sobrien	char	argtype;
11159243Sobrien	int	arg_val;
11259243Sobrien    }			args[MAX_ARGS];
11359243Sobrien} CMD;
11459243Sobrien
11559243Sobrien
11659243Sobrienstatic int a_flag  = 0;		/* set active partition */
11759243Sobrienstatic int i_flag  = 0;		/* replace partition data */
11859243Sobrienstatic int u_flag  = 0;		/* update partition data */
11959243Sobrienstatic int t_flag  = 0;		/* test only, if f_flag is given */
12059243Sobrienstatic char *f_flag = NULL;	/* Read config info from file */
12159243Sobrienstatic int v_flag  = 0;		/* Be verbose */
12259243Sobrien
12359243Sobrienstatic unsigned char bootcode[] = {
12459243Sobrien0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
12559243Sobrien0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
12659243Sobrien0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
12759243Sobrien0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
12859243Sobrien0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
129131962Smp0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
13059243Sobrien0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
13159243Sobrien0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
13259243Sobrien0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
13359243Sobrien'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
13459243Sobrien	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
13559243Sobrien'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
13659243Sobrien	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
13759243Sobrien'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
13859243Sobrien	'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
13959243Sobrien'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
14059243Sobrien	'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
14159243Sobrien
14259243Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
14359243Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
14459243Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
14559243Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
14659243Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
14759243Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
14859243Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
14959243Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
15059243Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
15159243Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
15259243Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
15359243Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
154131962Smp  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
155131962Smp};
156131962Smp
157131962Smpstruct part_type
158131962Smp{
159131962Smp unsigned char type;
160131962Smp char *name;
161131962Smp}part_types[] =
162131962Smp{
163131962Smp	 {0x00, "unused"}
164131962Smp	,{0x01, "Primary DOS with 12 bit FAT"}
165131962Smp	,{0x02, "XENIX / filesystem"}
16659243Sobrien	,{0x03, "XENIX /usr filesystem"}
16759243Sobrien	,{0x04, "Primary DOS with 16 bit FAT"}
16859243Sobrien	,{0x05, "Extended DOS"}
16959243Sobrien	,{0x06, "Primary 'big' DOS (> 32MB)"}
17059243Sobrien	,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"}
17159243Sobrien	,{0x08, "AIX filesystem"}
17259243Sobrien	,{0x09, "AIX boot partition or Coherent"}
17359243Sobrien	,{0x0A, "OS/2 Boot Manager or OPUS"}
17459243Sobrien	,{0x10, "OPUS"}
17583098Smp	,{0x40, "VENIX 286"}
17683098Smp	,{0x50, "DM"}
17783098Smp	,{0x51, "DM"}
17859243Sobrien	,{0x52, "CP/M or Microport SysV/AT"}
17959243Sobrien	,{0x56, "GB"}
18059243Sobrien	,{0x61, "Speed"}
18159243Sobrien	,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
18259243Sobrien	,{0x64, "Novell Netware 2.xx"}
18359243Sobrien	,{0x65, "Novell Netware 3.xx"}
18459243Sobrien	,{0x75, "PCIX"}
18559243Sobrien	,{0x80, "Minix 1.1 ... 1.4a"}
18659243Sobrien	,{0x81, "Minix 1.4b ... 1.5.10"}
18759243Sobrien	,{0x82, "Linux swap"}
18859243Sobrien	,{0x83, "Linux filesystem"}
18959243Sobrien	,{0x93, "Amoeba filesystem"}
19059243Sobrien	,{0x94, "Amoeba bad block table"}
19159243Sobrien	,{0xA5, "FreeBSD/NetBSD/386BSD"}
19259243Sobrien	,{0xA7, "NEXTSTEP"}
19359243Sobrien	,{0xB7, "BSDI BSD/386 filesystem"}
19459243Sobrien	,{0xB8, "BSDI BSD/386 swap"}
19559243Sobrien	,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
19669408Sache	,{0xE1, "Speed"}
19769408Sache	,{0xE3, "Speed"}
198145479Smp	,{0xE4, "Speed"}
19969408Sache	,{0xF1, "Speed"}
20069408Sache	,{0xF2, "DOS 3.3+ Secondary"}
201100616Smp	,{0xF4, "Speed"}
202100616Smp	,{0xFF, "BBT (Bad Blocks Table)"}
203100616Smp};
204100616Smp
20569408Sachestatic void print_s0(int which);
20659243Sobrienstatic void print_part(int i);
20759243Sobrienstatic void init_sector0(unsigned long start);
20859243Sobrienstatic void init_boot(void);
20959243Sobrienstatic void change_part(int i);
21059243Sobrienstatic void print_params();
21159243Sobrienstatic void change_active(int which);
212145479Smpstatic void get_params_to_use();
21359243Sobrienstatic void dos(int sec, int size, unsigned char *c, unsigned char *s,
21459243Sobrien		unsigned char *h);
215145479Smpstatic int open_disk(int u_flag);
21659243Sobrienstatic ssize_t read_disk(off_t sector, void *buf);
21759243Sobrienstatic ssize_t write_disk(off_t sector, void *buf);
218145479Smpstatic int get_params();
21959243Sobrienstatic int read_s0();
22059243Sobrienstatic int write_s0();
221145479Smpstatic int ok(char *str);
222145479Smpstatic int decimal(char *str, int *num, int deflt);
223145479Smpstatic char *get_type(int type);
22459243Sobrienstatic int read_config(char *config_file);
22559243Sobrienstatic void reset_boot(void);
22659243Sobrien#if 0
22759243Sobrienstatic int hex(char *str, int *num, int deflt);
22859243Sobrienstatic int string(char *str, char **ans);
22959243Sobrien#endif
23059243Sobrien
23159243Sobrien
23259243Sobrienint
23359243Sobrienmain(int argc, char *argv[])
23459243Sobrien{
23559243Sobrien	int	i;
23659243Sobrien
23759243Sobrien	name = *argv;
23859243Sobrien	{register char *cp = name;
23959243Sobrien		while (*cp) if (*cp++ == '/') name = cp;
24059243Sobrien	}
24159243Sobrien
24259243Sobrien	for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
24359243Sobrien		if (*token++ != '-' || !*token)
24459243Sobrien			break;
24559243Sobrien		else { register int flag;
24659243Sobrien			for ( ; (flag = *token++) ; ) {
24759243Sobrien				switch (flag) {
24859243Sobrien				case '0':
24959243Sobrien					partition = 0;
25059243Sobrien					break;
25159243Sobrien				case '1':
25259243Sobrien					partition = 1;
25359243Sobrien					break;
25459243Sobrien				case '2':
25559243Sobrien					partition = 2;
25659243Sobrien					break;
25759243Sobrien				case '3':
25859243Sobrien					partition = 3;
25959243Sobrien					break;
26059243Sobrien				case 'a':
26159243Sobrien					a_flag = 1;
26259243Sobrien					break;
26359243Sobrien				case 'f':
26459243Sobrien					if (*token)
26559243Sobrien					{
26659243Sobrien					    f_flag = token;
26759243Sobrien					    token = "";
26859243Sobrien					}
26959243Sobrien					else
27059243Sobrien					{
27159243Sobrien					    if (argc == 1)
27259243Sobrien					    {
27359243Sobrien						goto usage;
27459243Sobrien					    }
27559243Sobrien					    --argc;
27659243Sobrien					    f_flag = *++argv;
27759243Sobrien					}
27859243Sobrien					/*
27959243Sobrien					 * u_flag is needed, because we're
28059243Sobrien					 * writing to the disk.
28159243Sobrien					 */
282145479Smp					u_flag = 1;
28359243Sobrien					break;
28459243Sobrien				case 'i':
28559243Sobrien					i_flag = 1;
28659243Sobrien				case 'u':
28759243Sobrien					u_flag = 1;
28859243Sobrien					break;
28959243Sobrien				case 't':
29059243Sobrien					t_flag = 1;
29159243Sobrien				case 'v':
29259243Sobrien					v_flag = 1;
29359243Sobrien					break;
29459243Sobrien				default:
29559243Sobrien					goto usage;
29659243Sobrien				}
29759243Sobrien			}
29859243Sobrien		}
29959243Sobrien	}
30059243Sobrien
30159243Sobrien	if (argc > 0)
30259243Sobrien	{
30359243Sobrien		static char realname[12];
30459243Sobrien
30559243Sobrien		if(strncmp(argv[0], "/dev", 4) == 0)
30659243Sobrien			disk = argv[0];
30759243Sobrien		else
30859243Sobrien		{
30959243Sobrien			snprintf(realname, 12, "/dev/r%s", argv[0]);
31059243Sobrien			disk = realname;
31159243Sobrien		}
31259243Sobrien
31359243Sobrien		if (open_disk(u_flag) < 0)
31459243Sobrien		{
315145479Smp			fprintf(stderr, "Cannot open disk %s (%s)\n",
316145479Smp				disk, sys_errlist[errno]);
31759243Sobrien			exit(1);
31859243Sobrien		}
31959243Sobrien	}
32059243Sobrien	else
32159243Sobrien	{
32259243Sobrien		int i, rv = 0;
32359243Sobrien
32459243Sobrien		for(i = 0; disks[i]; i++)
32559243Sobrien		{
32659243Sobrien			disk = disks[i];
32759243Sobrien			rv = open_disk(u_flag);
32859243Sobrien			if(rv != -2) break;
32959243Sobrien		}
33059243Sobrien		if(rv < 0)
33159243Sobrien		{
33259243Sobrien			fprintf(stderr, "Cannot open any disk (%s)\n",
333145479Smp				sys_errlist[errno]);
33459243Sobrien			exit(1);
33559243Sobrien		}
33659243Sobrien	}
33759243Sobrien
33859243Sobrien	printf("******* Working on device %s *******\n",disk);
33959243Sobrien
34059243Sobrien	if (f_flag)
34159243Sobrien	{
34259243Sobrien	    if (read_s0() || i_flag)
34359243Sobrien	    {
34459243Sobrien		reset_boot();
34559243Sobrien	    }
346145479Smp
34759243Sobrien	    if (!read_config(f_flag))
34859243Sobrien	    {
34959243Sobrien		exit(1);
35059243Sobrien	    }
35159243Sobrien	    if (v_flag)
35259243Sobrien	    {
35359243Sobrien		print_s0(-1);
35459243Sobrien	    }
35559243Sobrien	    if (!t_flag)
35659243Sobrien	    {
35759243Sobrien		write_s0();
35859243Sobrien	    }
35959243Sobrien	}
36059243Sobrien	else
361145479Smp	{
36259243Sobrien	    if(u_flag)
363145479Smp	    {
36459243Sobrien		get_params_to_use();
36559243Sobrien	    }
36659243Sobrien	    else
36759243Sobrien	    {
36859243Sobrien		print_params();
36959243Sobrien	    }
37059243Sobrien
37159243Sobrien	    if (read_s0())
37259243Sobrien		init_sector0(1);
37359243Sobrien
37459243Sobrien	    printf("Media sector size is %d\n", secsize);
37559243Sobrien	    printf("Warning: BIOS sector numbering starts with sector 1\n");
37659243Sobrien	    printf("Information from DOS bootblock is:\n");
37759243Sobrien	    if (partition == -1)
37859243Sobrien		for (i = 0; i < NDOSPART; i++)
37959243Sobrien		    change_part(i);
38059243Sobrien	    else
38159243Sobrien		change_part(partition);
38259243Sobrien
38359243Sobrien	    if (u_flag || a_flag)
38459243Sobrien		change_active(partition);
38559243Sobrien
38659243Sobrien	    if (u_flag || a_flag) {
38759243Sobrien		if (!t_flag)
38859243Sobrien		{
38959243Sobrien		    printf("\nWe haven't changed the partition table yet.  ");
39059243Sobrien		    printf("This is your last chance.\n");
39159243Sobrien		}
39259243Sobrien		print_s0(-1);
39359243Sobrien		if (!t_flag)
39459243Sobrien		{
39559243Sobrien		    if (ok("Should we write new partition table?"))
39659243Sobrien			write_s0();
39759243Sobrien		}
39859243Sobrien		else
39959243Sobrien		{
40059243Sobrien		    printf("\n-t flag specified -- partition table not written.\n");
40159243Sobrien		}
40259243Sobrien	    }
40359243Sobrien	}
40459243Sobrien
40559243Sobrien	exit(0);
40659243Sobrien
40759243Sobrienusage:
40859243Sobrien	printf("fdisk {-a|-i|-u} [-f <config file> [-t] [-v]] [-{0,1,2,3}] [disk]\n");
40959243Sobrien	return(1);
41059243Sobrien}
41159243Sobrien
41259243Sobrienstatic void
41359243Sobrienprint_s0(int which)
41459243Sobrien{
41559243Sobrienint	i;
41659243Sobrien
41759243Sobrien	print_params();
41859243Sobrien	printf("Information from DOS bootblock is:\n");
41959243Sobrien	if (which == -1)
42059243Sobrien		for (i = 0; i < NDOSPART; i++)
42159243Sobrien			printf("%d: ", i), print_part(i);
42259243Sobrien	else
42359243Sobrien		print_part(which);
42459243Sobrien}
42559243Sobrien
42659243Sobrienstatic struct dos_partition mtpart = { 0 };
42759243Sobrien
42859243Sobrienstatic void
42959243Sobrienprint_part(int i)
43059243Sobrien{
43159243Sobrienstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
43259243Sobrien
43359243Sobrien
43459243Sobrien	if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
43559243Sobrien		printf("<UNUSED>\n");
43659243Sobrien		return;
43759243Sobrien	}
43859243Sobrien	printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
43959243Sobrien	printf("    start %ld, size %ld (%ld Meg), flag %x\n",
44059243Sobrien		partp->dp_start,
44159243Sobrien		partp->dp_size, partp->dp_size * secsize / (1024 * 1024),
44259243Sobrien		partp->dp_flag);
44359243Sobrien	printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
44459243Sobrien		,DPCYL(partp->dp_scyl, partp->dp_ssect)
44559243Sobrien		,DPSECT(partp->dp_ssect)
44659243Sobrien		,partp->dp_shd
44759243Sobrien		,DPCYL(partp->dp_ecyl, partp->dp_esect)
44859243Sobrien		,DPSECT(partp->dp_esect)
449145479Smp		,partp->dp_ehd);
45059243Sobrien}
45159243Sobrien
45259243Sobrien
45359243Sobrienstatic void
45459243Sobrieninit_boot(void)
45559243Sobrien{
45659243Sobrien	memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
45759243Sobrien	mboot.signature = BOOT_MAGIC;
45859243Sobrien}
45959243Sobrien
46059243Sobrien
46159243Sobrienstatic void
46259243Sobrieninit_sector0(unsigned long start)
46359243Sobrien{
46459243Sobrienstruct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
46559243Sobrienunsigned long size = disksecs - start;
46659243Sobrien
467145479Smp	init_boot();
46859243Sobrien
469145479Smp	partp->dp_typ = DOSPTYP_386BSD;
47059243Sobrien	partp->dp_flag = ACTIVE;
47159243Sobrien	partp->dp_start = start;
47259243Sobrien	partp->dp_size = size;
47359243Sobrien
47459243Sobrien	dos(partp->dp_start, partp->dp_size,
47559243Sobrien	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
47659243Sobrien	dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
47759243Sobrien	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
47859243Sobrien}
47959243Sobrien
48059243Sobrienstatic void
48159243Sobrienchange_part(int i)
48259243Sobrien{
48359243Sobrienstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
48459243Sobrien
48559243Sobrien    printf("The data for partition %d is:\n", i);
48659243Sobrien    print_part(i);
48759243Sobrien
48859243Sobrien    if (u_flag && ok("Do you want to change it?")) {
48959243Sobrien	int tmp;
49059243Sobrien
49159243Sobrien	if (i_flag) {
492145479Smp		bzero((char *)partp, sizeof (struct dos_partition));
49359243Sobrien		if (i == 3) {
49459243Sobrien			init_sector0(1);
49559243Sobrien			printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
49659243Sobrien			print_part(i);
49759243Sobrien		}
49859243Sobrien	}
49959243Sobrien
50059243Sobrien	do {
50159243Sobrien		Decimal("sysid", partp->dp_typ, tmp);
50259243Sobrien		Decimal("start", partp->dp_start, tmp);
50359243Sobrien		Decimal("size", partp->dp_size, tmp);
50459243Sobrien
50559243Sobrien		if (ok("Explicitly specifiy beg/end address ?"))
50659243Sobrien		{
50759243Sobrien			int	tsec,tcyl,thd;
50859243Sobrien			tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
50959243Sobrien			thd = partp->dp_shd;
51059243Sobrien			tsec = DPSECT(partp->dp_ssect);
51159243Sobrien			Decimal("beginning cylinder", tcyl, tmp);
51259243Sobrien			Decimal("beginning head", thd, tmp);
51359243Sobrien			Decimal("beginning sector", tsec, tmp);
51459243Sobrien			partp->dp_scyl = DOSCYL(tcyl);
51559243Sobrien			partp->dp_ssect = DOSSECT(tsec,tcyl);
51659243Sobrien			partp->dp_shd = thd;
51759243Sobrien
51859243Sobrien			tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
51959243Sobrien			thd = partp->dp_ehd;
52059243Sobrien			tsec = DPSECT(partp->dp_esect);
52159243Sobrien			Decimal("ending cylinder", tcyl, tmp);
52259243Sobrien			Decimal("ending head", thd, tmp);
52359243Sobrien			Decimal("ending sector", tsec, tmp);
524145479Smp			partp->dp_ecyl = DOSCYL(tcyl);
52559243Sobrien			partp->dp_esect = DOSSECT(tsec,tcyl);
52659243Sobrien			partp->dp_ehd = thd;
52759243Sobrien		} else {
52859243Sobrien			dos(partp->dp_start, partp->dp_size,
52959243Sobrien			    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
53059243Sobrien			dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
53159243Sobrien			    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
53259243Sobrien		}
533145479Smp
53459243Sobrien		print_part(i);
535145479Smp	} while (!ok("Are we happy with this entry?"));
53659243Sobrien    }
53759243Sobrien}
53859243Sobrien
53959243Sobrienstatic void
54059243Sobrienprint_params()
54159243Sobrien{
54259243Sobrien	printf("parameters extracted from in-core disklabel are:\n");
54359243Sobrien	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
54459243Sobrien			,cyls,heads,sectors,cylsecs);
54559243Sobrien	if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
54659243Sobrien		printf("Figures below won't work with BIOS for partitions not in cyl 1\n");
54759243Sobrien	printf("parameters to be used for BIOS calculations are:\n");
54859243Sobrien	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
54959243Sobrien		,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
55059243Sobrien}
55159243Sobrien
55259243Sobrienstatic void
55359243Sobrienchange_active(int which)
55459243Sobrien{
55559243Sobrienint i;
55659243Sobrienint active = 3, tmp;
55759243Sobrienstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
55859243Sobrien
55959243Sobrien	if (a_flag && which != -1)
56059243Sobrien		active = which;
56159243Sobrien	if (!ok("Do you want to change the active partition?"))
56259243Sobrien		return;
563145479Smp	do
56459243Sobrien		Decimal("active partition", active, tmp);
56559243Sobrien	while (!ok("Are you happy with this choice"));
56659243Sobrien	for (i = 0; i < NDOSPART; i++)
56759243Sobrien		partp[i].dp_flag = 0;
56859243Sobrien	if (active >= 0 && active < NDOSPART)
569100616Smp		partp[active].dp_flag = ACTIVE;
570100616Smp}
57159243Sobrien
57259243Sobrienvoid
57359243Sobrienget_params_to_use()
57459243Sobrien{
57559243Sobrien	int	tmp;
576145479Smp	print_params();
57759243Sobrien	if (ok("Do you want to change our idea of what BIOS thinks ?"))
578145479Smp	{
57959243Sobrien		do
58059243Sobrien		{
58159243Sobrien			Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
58259243Sobrien			Decimal("BIOS's idea of #heads", dos_heads, tmp);
58359243Sobrien			Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
58459243Sobrien			dos_cylsecs = dos_heads * dos_sectors;
58559243Sobrien			print_params();
58659243Sobrien		}
58759243Sobrien		while(!ok("Are you happy with this choice"));
58859243Sobrien	}
58959243Sobrien}
59059243Sobrien
591145479Smp
592145479Smp/***********************************************\
59359243Sobrien* Change real numbers into strange dos numbers	*
59459243Sobrien\***********************************************/
59559243Sobrienstatic void
59659243Sobriendos(sec, size, c, s, h)
59759243Sobrienint sec, size;
59859243Sobrienunsigned char *c, *s, *h;
59959243Sobrien{
60059243Sobrienint cy;
60159243Sobrienint hd;
60259243Sobrien
60359243Sobrien	if (sec == 0 && size == 0) {
60459243Sobrien		*s = *c = *h = 0;
60559243Sobrien		return;
60659243Sobrien	}
60759243Sobrien
60859243Sobrien	cy = sec / ( dos_cylsecs );
60959243Sobrien	sec = sec - cy * ( dos_cylsecs );
61059243Sobrien
61159243Sobrien	hd = sec / dos_sectors;
61259243Sobrien	sec = (sec - hd * dos_sectors) + 1;
61359243Sobrien
614145479Smp	*h = hd;
61559243Sobrien	*c = cy & 0xff;
61659243Sobrien	*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
61759243Sobrien}
61859243Sobrien
61959243Sobrienint fd;
62059243Sobrien
62159243Sobrien	/* Getting device status */
62259243Sobrien
62359243Sobrienstatic int
62459243Sobrienopen_disk(int u_flag)
62559243Sobrien{
62659243Sobrienstruct stat 	st;
627145479Smp
62859243Sobrien	if (stat(disk, &st) == -1) {
62959243Sobrien		fprintf(stderr, "%s: Can't get file status of %s\n",
63059243Sobrien			name, disk);
63159243Sobrien		return -1;
63259243Sobrien	}
63359243Sobrien	if ( !(st.st_mode & S_IFCHR) )
63459243Sobrien		fprintf(stderr,"%s: Device %s is not character special\n",
63559243Sobrien			name, disk);
63659243Sobrien	if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) {
63759243Sobrien		if(errno == ENXIO)
63859243Sobrien			return -2;
63959243Sobrien		fprintf(stderr,"%s: Can't open device %s\n", name, disk);
64059243Sobrien		return -1;
64159243Sobrien	}
64259243Sobrien	if (get_params(0) == -1) {
64359243Sobrien		fprintf(stderr, "%s: Can't get disk parameters on %s\n",
64459243Sobrien			name, disk);
64559243Sobrien		return -1;
64659243Sobrien	}
64759243Sobrien	return fd;
64859243Sobrien}
64959243Sobrien
65059243Sobrienstatic ssize_t
65159243Sobrienread_disk(off_t sector, void *buf)
65259243Sobrien{
65359243Sobrien	lseek(fd,(sector * 512), 0);
65459243Sobrien	if( secsize == 0 )
65559243Sobrien		for( secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; secsize *= 2 )
65659243Sobrien			{
65759243Sobrien			/* try the read */
65859243Sobrien			int size = read(fd, buf, secsize);
65959243Sobrien			if( size == secsize )
66059243Sobrien				/* it worked so return */
66159243Sobrien				return secsize;
66259243Sobrien			}
66359243Sobrien	else
66459243Sobrien		return read( fd, buf, secsize );
66559243Sobrien
66659243Sobrien	/* we failed to read at any of the sizes */
66759243Sobrien	return -1;
66859243Sobrien}
66959243Sobrien
67059243Sobrienstatic ssize_t
67159243Sobrienwrite_disk(off_t sector, void *buf)
67259243Sobrien{
67359243Sobrien	lseek(fd,(sector * 512), 0);
67459243Sobrien	/* write out in the size that the read_disk found worked */
67559243Sobrien	return write(fd, buf, secsize);
67659243Sobrien}
67759243Sobrien
67859243Sobrienstatic int
67959243Sobrienget_params()
68059243Sobrien{
68159243Sobrien
68259243Sobrien    if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
68359243Sobrien	fprintf(stderr,
68459243Sobrien		"%s: Can't get disk parameters on %s; supplying dummy ones\n",
68559243Sobrien		name, disk);
68659243Sobrien	dos_cyls = cyls = 1;
68759243Sobrien	dos_heads = heads = 1;
68859243Sobrien	dos_sectors = sectors = 1;
68959243Sobrien	dos_cylsecs = cylsecs = heads * sectors;
69059243Sobrien	disksecs = cyls * heads * sectors;
69159243Sobrien	return disksecs;
69259243Sobrien    }
69359243Sobrien
69459243Sobrien    dos_cyls = cyls = disklabel.d_ncylinders;
69559243Sobrien    dos_heads = heads = disklabel.d_ntracks;
69659243Sobrien    dos_sectors = sectors = disklabel.d_nsectors;
69759243Sobrien    dos_cylsecs = cylsecs = heads * sectors;
69859243Sobrien    disksecs = cyls * heads * sectors;
699145479Smp
70059243Sobrien    return (disksecs);
70159243Sobrien}
702145479Smp
703145479Smp
70459243Sobrienstatic int
70559243Sobrienread_s0()
70659243Sobrien{
70759243Sobrien	if (read_disk(0, (char *) mboot.bootinst) == -1) {
70859243Sobrien		fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
70959243Sobrien		return -1;
71059243Sobrien	}
71159243Sobrien	if (mboot.signature != BOOT_MAGIC) {
71259243Sobrien		fprintf(stderr, "%s: Invalid fdisk partition table found\n",
71359243Sobrien			name);
71459243Sobrien		/* So should we initialize things */
71559243Sobrien		return -1;
71659243Sobrien	}
71759243Sobrien	return 0;
71859243Sobrien}
71959243Sobrien
72059243Sobrienstatic int
72159243Sobrienwrite_s0()
72259243Sobrien{
72359243Sobrien	int	flag;
72459243Sobrien	if (iotest) {
72559243Sobrien		print_s0(-1);
72659243Sobrien		return 0;
72759243Sobrien	}
72859243Sobrien	/*
72959243Sobrien	 * write enable label sector before write (if necessary),
73059243Sobrien	 * disable after writing.
73159243Sobrien	 * needed if the disklabel protected area also protects
73259243Sobrien	 * sector 0. (e.g. empty disk)
73359243Sobrien	 */
73459243Sobrien	flag = 1;
735145479Smp#ifdef NOT_NOW
73659243Sobrien	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
73759243Sobrien		perror("ioctl DIOCWLABEL");
73859243Sobrien#endif
73959243Sobrien	if (write_disk(0, (char *) mboot.bootinst) == -1) {
74059243Sobrien		fprintf(stderr, "%s: Can't write fdisk partition table\n",
741100616Smp			name);
742100616Smp		return -1;
743100616Smp	flag = 0;
744100616Smp#ifdef NOT_NOW
745100616Smp	(void) ioctl(fd, DIOCWLABEL, &flag);
746100616Smp#endif
74759243Sobrien	}
74859243Sobrien	return(0);
74959243Sobrien}
75059243Sobrien
751131962Smp
752131962Smpstatic int
75359243Sobrienok(str)
75459243Sobrienchar *str;
75559243Sobrien{
75659243Sobrien	printf("%s [n] ", str);
75759243Sobrien	fgets(lbuf, LBUF, stdin);
75859243Sobrien	lbuf[strlen(lbuf)-1] = 0;
75959243Sobrien
76059243Sobrien	if (*lbuf &&
76159243Sobrien		(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
76259243Sobrien		 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
76359243Sobrien		return 1;
76459243Sobrien	else
76559243Sobrien		return 0;
76659243Sobrien}
76759243Sobrien
76859243Sobrienstatic int
76959243Sobriendecimal(char *str, int *num, int deflt)
77059243Sobrien{
77183098Smpint acc = 0, c;
77283098Smpchar *cp;
77359243Sobrien
77459243Sobrien	while (1) {
77559243Sobrien		printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
77659243Sobrien		fgets(lbuf, LBUF, stdin);
77759243Sobrien		lbuf[strlen(lbuf)-1] = 0;
77859243Sobrien
77959243Sobrien		if (!*lbuf)
78059243Sobrien			return 0;
78159243Sobrien
78259243Sobrien		cp = lbuf;
78359243Sobrien		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
78469408Sache		if (!c)
785145479Smp			return 0;
78669408Sache		while ((c = *cp++)) {
78769408Sache			if (c <= '9' && c >= '0')
78859243Sobrien				acc = acc * 10 + c - '0';
78959243Sobrien			else
79059243Sobrien				break;
79159243Sobrien		}
792145479Smp		if (c == ' ' || c == '\t')
79359243Sobrien			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
79459243Sobrien		if (!c) {
795145479Smp			*num = acc;
796145479Smp			return 1;
79759243Sobrien		} else
79859243Sobrien			printf("%s is an invalid decimal number.  Try again\n",
79959243Sobrien				lbuf);
80059243Sobrien	}
80159243Sobrien
80259243Sobrien}
80359243Sobrien
80459243Sobrien#if 0
80559243Sobrienstatic int
80659243Sobrienhex(char *str, int *num, int deflt)
80759243Sobrien{
80859243Sobrienint acc = 0, c;
80959243Sobrienchar *cp;
81059243Sobrien
81159243Sobrien	while (1) {
81259243Sobrien		printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
81359243Sobrien		fgets(lbuf, LBUF, stdin);
814145479Smp		lbuf[strlen(lbuf)-1] = 0;
81559243Sobrien
81659243Sobrien		if (!*lbuf)
81759243Sobrien			return 0;
81859243Sobrien
81959243Sobrien		cp = lbuf;
82059243Sobrien		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
82159243Sobrien		if (!c)
82259243Sobrien			return 0;
823145479Smp		while ((c = *cp++)) {
82459243Sobrien			if (c <= '9' && c >= '0')
825145479Smp				acc = (acc << 4) + c - '0';
826145479Smp			else if (c <= 'f' && c >= 'a')
82759243Sobrien				acc = (acc << 4) + c - 'a' + 10;
82859243Sobrien			else if (c <= 'F' && c >= 'A')
82959243Sobrien				acc = (acc << 4) + c - 'A' + 10;
83059243Sobrien			else
83159243Sobrien				break;
83259243Sobrien		}
83359243Sobrien		if (c == ' ' || c == '\t')
83459243Sobrien			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
83559243Sobrien		if (!c) {
83659243Sobrien			*num = acc;
83759243Sobrien			return 1;
83859243Sobrien		} else
83959243Sobrien			printf("%s is an invalid hex number.  Try again\n",
84059243Sobrien				lbuf);
84159243Sobrien	}
84259243Sobrien
84359243Sobrien}
84459243Sobrien
84559243Sobrienstatic int
84659243Sobrienstring(char *str, char **ans)
84759243Sobrien{
84859243Sobrienint c;
84959243Sobrienchar *cp = lbuf;
85059243Sobrien
85159243Sobrien	while (1) {
85259243Sobrien		printf("Supply a string value for \"%s\" [%s] ", str, *ans);
85359243Sobrien		fgets(lbuf, LBUF, stdin);
85459243Sobrien		lbuf[strlen(lbuf)-1] = 0;
85559243Sobrien
85659243Sobrien		if (!*lbuf)
85759243Sobrien			return 0;
85859243Sobrien
85959243Sobrien		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
86059243Sobrien		if (c == '"') {
86159243Sobrien			c = *++cp;
86259243Sobrien			*ans = cp;
86359243Sobrien			while ((c = *cp) && c != '"') cp++;
86459243Sobrien		} else {
86559243Sobrien			*ans = cp;
86659243Sobrien			while ((c = *cp) && c != ' ' && c != '\t') cp++;
86759243Sobrien		}
86859243Sobrien
86959243Sobrien		if (c)
87059243Sobrien			*cp = 0;
87159243Sobrien		return 1;
87259243Sobrien	}
87359243Sobrien}
87459243Sobrien#endif
87559243Sobrien
876145479Smpstatic char *
87759243Sobrienget_type(int type)
87859243Sobrien{
879145479Smp	int	numentries = (sizeof(part_types)/sizeof(struct part_type));
880145479Smp	int	counter = 0;
88159243Sobrien	struct	part_type *ptr = part_types;
88259243Sobrien
88359243Sobrien
88459243Sobrien	while(counter < numentries)
88559243Sobrien	{
88659243Sobrien		if(ptr->type == type)
88759243Sobrien		{
88859243Sobrien			return(ptr->name);
88959243Sobrien		}
890100616Smp		ptr++;
89159243Sobrien		counter++;
89259243Sobrien	}
89359243Sobrien	return("unknown");
89459243Sobrien}
89559243Sobrien
89659243Sobrien
89759243Sobrienstatic void
89859243Sobrienparse_config_line(line, command)
89959243Sobrien    char	*line;
90059243Sobrien    CMD		*command;
90159243Sobrien{
90259243Sobrien    char	*cp, *end;
90359243Sobrien
90459243Sobrien    cp = line;
90559243Sobrien    while (1)	/* dirty trick used to insure one exit point for this
90659243Sobrien		   function */
90759243Sobrien    {
90859243Sobrien	memset(command, 0, sizeof(*command));
90959243Sobrien
91059243Sobrien	while (isspace(*cp)) ++cp;
91159243Sobrien	if (*cp == '\0' || *cp == '#')
91259243Sobrien	{
91359243Sobrien	    break;
91459243Sobrien	}
91559243Sobrien	command->cmd = *cp++;
91659243Sobrien
91759243Sobrien	/*
91859243Sobrien	 * Parse args
91959243Sobrien	 */
92059243Sobrien	while (1)
92159243Sobrien	{
92259243Sobrien	    while (isspace(*cp)) ++cp;
92359243Sobrien	    if (*cp == '#')
92459243Sobrien	    {
92559243Sobrien		break;		/* found comment */
92659243Sobrien	    }
92759243Sobrien	    if (isalpha(*cp))
92859243Sobrien	    {
92959243Sobrien		command->args[command->n_args].argtype = *cp++;
93059243Sobrien	    }
93159243Sobrien	    if (!isdigit(*cp))
93259243Sobrien	    {
93359243Sobrien		break;		/* assume end of line */
93459243Sobrien	    }
93559243Sobrien	    end = NULL;
93659243Sobrien	    command->args[command->n_args].arg_val = strtol(cp, &end, 0);
93759243Sobrien	    if (cp == end)
93859243Sobrien	    {
93959243Sobrien		break;		/* couldn't parse number */
94059243Sobrien	    }
94159243Sobrien	    cp = end;
94259243Sobrien	    command->n_args++;
94359243Sobrien	}
94459243Sobrien	break;
94559243Sobrien    }
94659243Sobrien}
94759243Sobrien
94859243Sobrien
94959243Sobrienstatic int
95059243Sobrienprocess_geometry(command)
95159243Sobrien    CMD		*command;
95259243Sobrien{
95359243Sobrien    int		status = 1, i;
95459243Sobrien
95559243Sobrien    while (1)
95659243Sobrien    {
95759243Sobrien	geom_processed = 1;
95859243Sobrien	if (part_processed)
95959243Sobrien	{
96059243Sobrien	    fprintf(stderr,
96159243Sobrien		    "%s: ERROR line %d: the geometry specification line must occur before\n\
96259243Sobrien    all partition specifications.\n",
96359243Sobrien		    name, current_line_number);
96459243Sobrien	    status = 0;
96559243Sobrien	    break;
96659243Sobrien	}
96759243Sobrien	if (command->n_args != 3)
96859243Sobrien	{
96959243Sobrien	    fprintf(stderr,
97059243Sobrien		    "%s: ERROR line %d: incorrect number of geometry args\n",
97159243Sobrien		    name, current_line_number);
972145479Smp	    status = 0;
973145479Smp	    break;
97459243Sobrien	}
975145479Smp	dos_cyls = -1;
97659243Sobrien	dos_heads = -1;
97759243Sobrien	dos_sectors = -1;
978145479Smp	for (i = 0; i < 3; ++i)
97959243Sobrien	{
980145479Smp	    switch (command->args[i].argtype)
98159243Sobrien	    {
98259243Sobrien	    case 'c':
98359243Sobrien		dos_cyls = command->args[i].arg_val;
98459243Sobrien		break;
98559243Sobrien	    case 'h':
98659243Sobrien		dos_heads = command->args[i].arg_val;
98759243Sobrien		break;
98859243Sobrien	    case 's':
98959243Sobrien		dos_sectors = command->args[i].arg_val;
99059243Sobrien		break;
99159243Sobrien	    default:
99259243Sobrien		fprintf(stderr,
99359243Sobrien			"%s: ERROR line %d: unknown geometry arg type: '%c' (0x%02x)\n",
99459243Sobrien			name, current_line_number, command->args[i].argtype,
99559243Sobrien			command->args[i].argtype);
99659243Sobrien		status = 0;
99759243Sobrien		break;
99859243Sobrien	    }
99959243Sobrien	}
100059243Sobrien	if (status == 0)
100159243Sobrien	{
100259243Sobrien	    break;
100359243Sobrien	}
100459243Sobrien
100559243Sobrien	dos_cylsecs = dos_heads * dos_sectors;
100659243Sobrien
100759243Sobrien	/*
100859243Sobrien	 * Do sanity checks on parameter values
100959243Sobrien	 */
101059243Sobrien	if (dos_cyls < 0)
101159243Sobrien	{
101259243Sobrien	    fprintf(stderr,
101359243Sobrien		    "%s: ERROR line %d: number of cylinders not specified\n",
101459243Sobrien		    name, current_line_number);
101559243Sobrien	    status = 0;
101659243Sobrien	}
101759243Sobrien	if (dos_cyls == 0 || dos_cyls > 1024)
101859243Sobrien	{
101959243Sobrien	    fprintf(stderr,
102059243Sobrien		    "%s: WARNING line %d: number of cylinders (%d) may be out-of-range\n\
102159243Sobrien    (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\
102259243Sobrien    is dedicated to FreeBSD).\n",
102359243Sobrien		    name, current_line_number, dos_cyls);
102459243Sobrien	}
102559243Sobrien
102659243Sobrien	if (dos_heads < 0)
102759243Sobrien	{
102859243Sobrien	    fprintf(stderr,
102959243Sobrien		    "%s: ERROR line %d: number of heads not specified\n",
103059243Sobrien		    name, current_line_number);
103159243Sobrien	    status = 0;
103259243Sobrien	}
103359243Sobrien	else if (dos_heads < 1 || dos_heads > 256)
103459243Sobrien	{
103559243Sobrien	    fprintf(stderr,
103659243Sobrien		    "%s: ERROR line %d: number of heads must be within (1-256)\n",
103759243Sobrien		    name, current_line_number);
103859243Sobrien	    status = 0;
103959243Sobrien	}
104059243Sobrien
104159243Sobrien	if (dos_sectors < 0)
104259243Sobrien	{
104359243Sobrien	    fprintf(stderr, "%s: ERROR line %d: number of sectors not specified\n",
104459243Sobrien		    name, current_line_number);
104559243Sobrien	    status = 0;
104659243Sobrien	}
104759243Sobrien	else if (dos_sectors < 1 || dos_sectors > 63)
104859243Sobrien	{
104959243Sobrien	    fprintf(stderr,
105059243Sobrien		    "%s: ERROR line %d: number of sectors must be within (1-63)\n",
105159243Sobrien		    name, current_line_number);
105259243Sobrien	    status = 0;
105359243Sobrien	}
105459243Sobrien
105559243Sobrien	break;
105659243Sobrien    }
105759243Sobrien    return (status);
105859243Sobrien}
105959243Sobrien
106059243Sobrien
106159243Sobrienstatic int
106259243Sobrienprocess_partition(command)
106359243Sobrien    CMD		*command;
106459243Sobrien{
106559243Sobrien    int				status = 0, partition;
106659243Sobrien    unsigned long		chunks, adj_size, max_end;
106759243Sobrien    struct dos_partition	*partp;
106859243Sobrien
106959243Sobrien    while (1)
107059243Sobrien    {
107159243Sobrien	part_processed = 1;
107259243Sobrien	if (command->n_args != 4)
107359243Sobrien	{
107459243Sobrien	    fprintf(stderr,
107559243Sobrien		    "%s: ERROR line %d: incorrect number of partition args\n",
107659243Sobrien		    name, current_line_number);
1077145479Smp	    break;
107859243Sobrien	}
107959243Sobrien	partition = command->args[0].arg_val;
1080145479Smp	if (partition < 0 || partition > 3)
1081145479Smp	{
108259243Sobrien	    fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n",
108359243Sobrien		    name, current_line_number, partition);
108459243Sobrien	    break;
108559243Sobrien	}
108659243Sobrien	partp = ((struct dos_partition *) &mboot.parts) + partition;
108759243Sobrien	bzero((char *)partp, sizeof (struct dos_partition));
108859243Sobrien	partp->dp_typ = command->args[1].arg_val;
108959243Sobrien	partp->dp_start = command->args[2].arg_val;
109059243Sobrien	partp->dp_size = command->args[3].arg_val;
109159243Sobrien	max_end = partp->dp_start + partp->dp_size;
109259243Sobrien
109359243Sobrien	if (partp->dp_typ == 0)
109459243Sobrien	{
109559243Sobrien	    /*
109659243Sobrien	     * Get out, the partition is marked as unused.
109759243Sobrien	     */
109859243Sobrien	    /*
109959243Sobrien	     * Insure that it's unused.
110059243Sobrien	     */
110159243Sobrien	    bzero((char *)partp, sizeof (struct dos_partition));
110259243Sobrien	    status = 1;
110359243Sobrien	    break;
110459243Sobrien	}
110559243Sobrien
110659243Sobrien	/*
110759243Sobrien	 * Adjust start upwards, if necessary, to fall on an head boundary.
110859243Sobrien	 */
110959243Sobrien	if (partp->dp_start % dos_sectors != 0)
111059243Sobrien	{
111159243Sobrien	    adj_size =
111259243Sobrien		(partp->dp_start / dos_sectors + 1) * dos_sectors;
111359243Sobrien	    if (adj_size > max_end)
111459243Sobrien	    {
111559243Sobrien		/*
111659243Sobrien		 * Can't go past end of partition
111759243Sobrien		 */
111859243Sobrien		fprintf(stderr,
1119145479Smp			"%s: ERROR line %d: unable to adjust start of partition %d to fall on\n\
112059243Sobrien    a cylinder boundary.\n",
112159243Sobrien			name, current_line_number, partition);
112259243Sobrien		break;
112359243Sobrien	    }
112459243Sobrien	    fprintf(stderr,
112559243Sobrien		    "%s: WARNING: adjusting start offset of partition '%d' from %d\n\
112659243Sobrien    to %d, to round to an head boundary.\n",
112759243Sobrien		    name, partition, partp->dp_start, adj_size);
112859243Sobrien	    partp->dp_start = adj_size;
112959243Sobrien	}
113059243Sobrien
113159243Sobrien	/*
1132145479Smp	 * Adjust size downwards, if necessary, to fall on a cylinder
113359243Sobrien	 * boundary.
1134145479Smp	 */
113559243Sobrien	chunks =
1136145479Smp	    ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs;
113783098Smp	adj_size = chunks - partp->dp_start;
1138145479Smp	if (adj_size != partp->dp_size)
1139100616Smp	{
114059243Sobrien	    fprintf(stderr,
114159243Sobrien		    "%s: WARNING: adjusting size of partition '%d' from %d to %d,\n\
114259243Sobrien    to round to a cylinder boundary.\n",
114359243Sobrien		    name, partition, partp->dp_size, adj_size);
114459243Sobrien	    if (chunks > 0)
114559243Sobrien	    {
114659243Sobrien		partp->dp_size = adj_size;
114759243Sobrien	    }
114859243Sobrien	    else
114959243Sobrien	    {
115059243Sobrien		partp->dp_size = 0;
115159243Sobrien	    }
115259243Sobrien	}
115359243Sobrien	if (partp->dp_size < 1)
115459243Sobrien	{
115559243Sobrien	    fprintf(stderr,
115659243Sobrien		    "%s: ERROR line %d: size for partition '%d' is zero.\n",
115759243Sobrien		    name, current_line_number, partition);
115859243Sobrien	    break;
115959243Sobrien	}
116059243Sobrien
116159243Sobrien	dos(partp->dp_start, partp->dp_size,
116259243Sobrien	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
116359243Sobrien	dos(partp->dp_start+partp->dp_size - 1, partp->dp_size,
116483098Smp	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
116583098Smp	status = 1;
116683098Smp	break;
116783098Smp    }
116883098Smp    return (status);
1169100616Smp}
1170100616Smp
1171100616Smp
1172100616Smpstatic int
1173100616Smpprocess_active(command)
117459243Sobrien    CMD		*command;
117559243Sobrien{
117659243Sobrien    int				status = 0, partition, i;
117759243Sobrien    struct dos_partition	*partp;
117859243Sobrien
117959243Sobrien    while (1)
118059243Sobrien    {
118159243Sobrien	active_processed = 1;
118259243Sobrien	if (command->n_args != 1)
118359243Sobrien	{
118459243Sobrien	    fprintf(stderr,
118559243Sobrien		    "%s: ERROR line %d: incorrect number of active args\n",
118659243Sobrien		    name, current_line_number);
118759243Sobrien	    status = 0;
118859243Sobrien	    break;
118959243Sobrien	}
119059243Sobrien	partition = command->args[0].arg_val;
119159243Sobrien	if (partition < 0 || partition > 3)
119259243Sobrien	{
119359243Sobrien	    fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n",
119459243Sobrien		    name, current_line_number, partition);
119559243Sobrien	    break;
119659243Sobrien	}
119759243Sobrien	/*
119859243Sobrien	 * Reset active partition
119959243Sobrien	 */
120059243Sobrien	partp = ((struct dos_partition *) &mboot.parts);
120159243Sobrien	for (i = 0; i < NDOSPART; i++)
120259243Sobrien	    partp[i].dp_flag = 0;
120359243Sobrien	partp[partition].dp_flag = ACTIVE;
120459243Sobrien
120559243Sobrien	status = 1;
120659243Sobrien	break;
120759243Sobrien    }
120859243Sobrien    return (status);
120959243Sobrien}
121059243Sobrien
121159243Sobrien
121259243Sobrienstatic int
121359243Sobrienprocess_line(line)
121459243Sobrien    char	*line;
121559243Sobrien{
121659243Sobrien    CMD		command;
121759243Sobrien    int		status = 1;
121859243Sobrien
121959243Sobrien    while (1)
122059243Sobrien    {
122159243Sobrien	parse_config_line(line, &command);
122259243Sobrien	switch (command.cmd)
122359243Sobrien	{
122459243Sobrien	case 0:
122559243Sobrien	    /*
122659243Sobrien	     * Comment or blank line
122759243Sobrien	     */
122859243Sobrien	    break;
122959243Sobrien	case 'g':
123059243Sobrien	    /*
123159243Sobrien	     * Set geometry
123259243Sobrien	     */
123359243Sobrien	    status = process_geometry(&command);
123459243Sobrien	    break;
123559243Sobrien	case 'p':
123659243Sobrien	    status = process_partition(&command);
123759243Sobrien	    break;
123859243Sobrien	case 'a':
123959243Sobrien	    status = process_active(&command);
124059243Sobrien	    break;
124159243Sobrien	default:
124259243Sobrien	    status = 0;
124359243Sobrien	    break;
124459243Sobrien	}
1245145479Smp	break;
1246145479Smp    }
1247145479Smp    return (status);
1248145479Smp}
1249145479Smp
1250145479Smp
1251131962Smpstatic int
1252145479Smpread_config(config_file)
1253131962Smp    char *config_file;
1254145479Smp{
1255145479Smp    FILE	*fp = NULL;
1256145479Smp    int		status = 1;
1257145479Smp    char	buf[1010];
125859243Sobrien
125959243Sobrien    while (1)	/* dirty trick used to insure one exit point for this
1260145479Smp		   function */
1261145479Smp    {
1262145479Smp	if (strcmp(config_file, "-") != 0)
1263145479Smp	{
1264145479Smp	    /*
1265145479Smp	     * We're not reading from stdin
1266145479Smp	     */
1267145479Smp	    if ((fp = fopen(config_file, "r")) == NULL)
1268145479Smp	    {
126959243Sobrien		status = 0;
1270145479Smp		break;
1271145479Smp	    }
1272145479Smp	}
1273145479Smp	else
1274145479Smp	{
1275145479Smp	    fp = stdin;
1276145479Smp	}
1277145479Smp	current_line_number = 0;
1278145479Smp	while (!feof(fp))
1279145479Smp	{
1280145479Smp	    if (fgets(buf, sizeof(buf), fp) == NULL)
1281145479Smp	    {
1282145479Smp		break;
128359243Sobrien	    }
128459243Sobrien	    ++current_line_number;
128559243Sobrien	    status = process_line(buf);
128659243Sobrien	    if (status == 0)
1287131962Smp	    {
1288145479Smp		break;
128959243Sobrien	    }
129059243Sobrien	}
129159243Sobrien	break;
129259243Sobrien    }
129359243Sobrien    if (fp)
129459243Sobrien    {
129559243Sobrien	/*
1296	 * It doesn't matter if we're reading from stdin, as we've reached EOF
1297	 */
1298	fclose(fp);
1299    }
1300    return (status);
1301}
1302
1303
1304static void
1305reset_boot(void)
1306{
1307    int				i;
1308    struct dos_partition	*partp;
1309
1310    init_boot();
1311    for (i = 0; i < 4; ++i)
1312    {
1313	partp = ((struct dos_partition *) &mboot.parts) + i;
1314	bzero((char *)partp, sizeof (struct dos_partition));
1315    }
1316}
1317