fdisk.c revision 104459
158234Skato/*
258234Skato * Mach Operating System
358234Skato * Copyright (c) 1992 Carnegie Mellon University
458234Skato * All Rights Reserved.
558234Skato *
658234Skato * Permission to use, copy, modify and distribute this software and its
758234Skato * documentation is hereby granted, provided that both the copyright
858234Skato * notice and this permission notice appear in all copies of the
958234Skato * software, derivative works or modified versions, and any portions
1058234Skato * thereof, and that both notices appear in supporting documentation.
1158234Skato *
1258234Skato * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
1358234Skato * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
1458234Skato * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1558234Skato *
1658234Skato * Carnegie Mellon requests users of this software to return to
1758234Skato *
1858234Skato *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
1958234Skato *  School of Computer Science
2058234Skato *  Carnegie Mellon University
2158234Skato *  Pittsburgh PA 15213-3890
2258234Skato *
2358234Skato * any improvements or extensions that they make and grant Carnegie Mellon
2458234Skato * the rights to redistribute these changes.
2558234Skato */
2658234Skato
2758234Skato#ifndef lint
2858234Skatostatic const char rcsid[] =
2958234Skato  "$FreeBSD: head/sbin/fdisk_pc98/fdisk.c 104459 2002-10-04 14:05:00Z nyan $";
3058234Skato#endif /* not lint */
3158234Skato
3258234Skato#include <sys/disklabel.h>
33104459Snyan#include <sys/diskpc98.h>
3458234Skato#include <sys/stat.h>
3558234Skato#include <ctype.h>
3658234Skato#include <fcntl.h>
3758234Skato#include <err.h>
3858234Skato#include <errno.h>
3969793Sobrien#include <paths.h>
4058234Skato#include <stdio.h>
4158234Skato#include <stdlib.h>
4258234Skato#include <string.h>
4358234Skato#include <unistd.h>
4458234Skato
4558234Skatoint iotest;
4658234Skato
4758234Skato#define LBUF 100
4858234Skatostatic char lbuf[LBUF];
4958234Skato
5058234Skato/*
5158234Skato *
5258234Skato * Ported to 386bsd by Julian Elischer  Thu Oct 15 20:26:46 PDT 1992
5358234Skato *
5458234Skato * 14-Dec-89  Robert Baron (rvb) at Carnegie-Mellon University
5558234Skato *	Copyright (c) 1989	Robert. V. Baron
5658234Skato *	Created.
5758234Skato */
5858234Skato
5958234Skato#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
6058234Skato#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
6158234Skato#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
6258234Skato
6358234Skato#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
6458234Skato
6558234Skato#define MAX_SEC_SIZE 2048	/* maximum section size that is supported */
6658234Skato#define MIN_SEC_SIZE 512	/* the sector size to start sensing at */
6758234Skatoint secsize = 0;		/* the sensed sector size */
6858234Skato
6958234Skatoconst char *disk;
7058234Skatoconst char *disks[] =
7158234Skato{
7261278Snyan  "/dev/ad0", "/dev/wd0", "/dev/da0", "/dev/od0", 0
7358234Skato};
7458234Skato
7558234Skatostruct disklabel disklabel;		/* disk parameters */
7658234Skato
7758234Skatoint cyls, sectors, heads, cylsecs, disksecs;
7858234Skato
7958234Skatostruct mboot
8058234Skato{
8158234Skato	unsigned char padding[2]; /* force the longs to be long aligned */
8258234Skato#ifdef PC98
8358234Skato	unsigned char bootinst[510];
8458234Skato#else
8558234Skato	unsigned char bootinst[DOSPARTOFF];
8658234Skato	struct	dos_partition parts[4];
8758234Skato#endif
8858234Skato	unsigned short int	signature;
8958234Skato
9058234Skato#ifdef PC98
9158234Skato	struct	dos_partition parts[8];
9258234Skato#endif
9358234Skato	/* room to read in MBRs that are bigger then DEV_BSIZE */
9458234Skato	unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE];
9558234Skato};
9658234Skatostruct mboot mboot;
9758234Skato
9858234Skato#define ACTIVE 0x80
9958234Skato#define BOOT_MAGIC 0xAA55
10058234Skato
10158234Skatoint dos_cyls;
10258234Skatoint dos_heads;
10358234Skatoint dos_sectors;
10458234Skatoint dos_cylsecs;
10558234Skato
10658234Skato#ifdef PC98
10758234Skato#define DOSSECT(s,c) (s)
10858234Skato#define DOSCYL(c)	(c)
10958234Skato#else
11058234Skato#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
11158234Skato#define DOSCYL(c)	(c & 0xff)
11258234Skato#endif
11358234Skatostatic int partition = -1;
11458234Skato
11558234Skato
11658234Skato#define MAX_ARGS	10
11758234Skato
11858234Skatostatic int	current_line_number;
11958234Skato
12058234Skatostatic int	geom_processed = 0;
12158234Skatostatic int	part_processed = 0;
12258234Skatostatic int	active_processed = 0;
12358234Skato
12458234Skato
12558234Skatotypedef struct cmd {
12658234Skato    char		cmd;
12758234Skato    int			n_args;
12858234Skato    struct arg {
12958234Skato	char	argtype;
13058234Skato	int	arg_val;
13158234Skato    }			args[MAX_ARGS];
13258234Skato} CMD;
13358234Skato
13458234Skato
13558234Skatostatic int B_flag  = 0;		/* replace boot code */
13658234Skatostatic int I_flag  = 0;		/* use entire disk for FreeBSD */
13758234Skatostatic int a_flag  = 0;		/* set active partition */
13858234Skatostatic char *b_flag = NULL;	/* path to boot code */
13958234Skatostatic int i_flag  = 0;		/* replace partition data */
14058234Skatostatic int u_flag  = 0;		/* update partition data */
14158234Skatostatic int s_flag  = 0;		/* Print a summary and exit */
14258234Skatostatic int t_flag  = 0;		/* test only, if f_flag is given */
14358234Skatostatic char *f_flag = NULL;	/* Read config info from file */
14458234Skatostatic int v_flag  = 0;		/* Be verbose */
14558234Skato
14658234Skatostruct part_type
14758234Skato{
14858234Skato unsigned char type;
14958234Skato char *name;
15058234Skato}part_types[] =
15158234Skato{
15258234Skato	 {0x00, "unused"}
15358234Skato	,{0x01, "Primary DOS with 12 bit FAT"}
15458234Skato#ifdef PC98
15558234Skato	,{0x11, "MSDOS"}
15658234Skato	,{0x20, "MSDOS"}
15758234Skato	,{0x21, "MSDOS"}
15858234Skato	,{0x22, "MSDOS"}
15958234Skato	,{0x23, "MSDOS"}
160102231Strhodes	,{0x02, "XENIX / file system"}
161102231Strhodes	,{0x03, "XENIX /usr file system"}
16258234Skato	,{0x04, "PC-UX"}
16358234Skato	,{0x05, "Extended DOS"}
16458234Skato	,{0x06, "Primary 'big' DOS (> 32MB)"}
16558234Skato	,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"}
166102231Strhodes	,{0x08, "AIX file system"}
16758234Skato	,{0x09, "AIX boot partition or Coherent"}
16858234Skato	,{0x0A, "OS/2 Boot Manager or OPUS"}
16958234Skato	,{0x10, "OPUS"}
17058234Skato	,{0x14, "FreeBSD/NetBSD/386BSD"}
17158234Skato	,{0x94, "FreeBSD/NetBSD/386BSD"}
17258234Skato	,{0x40, "VENIX 286"}
17358234Skato	,{0x50, "DM"}
17458234Skato	,{0x51, "DM"}
17558234Skato	,{0x52, "CP/M or Microport SysV/AT"}
17658234Skato	,{0x56, "GB"}
17758234Skato	,{0x61, "Speed"}
17858234Skato	,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
17958234Skato	,{0x64, "Novell Netware 2.xx"}
18058234Skato	,{0x65, "Novell Netware 3.xx"}
18158234Skato	,{0x75, "PCIX"}
18258234Skato	,{0x40, "Minix"}
18358234Skato#else
184102231Strhodes	,{0x02, "XENIX / file system"}
185102231Strhodes	,{0x03, "XENIX /usr file system"}
18658234Skato	,{0x04, "Primary DOS with 16 bit FAT (<= 32MB)"}
18758234Skato	,{0x05, "Extended DOS"}
18858234Skato	,{0x06, "Primary 'big' DOS (> 32MB)"}
18958234Skato	,{0x07, "OS/2 HPFS, NTFS, QNX or Advanced UNIX"}
190102231Strhodes	,{0x08, "AIX file system"}
19158234Skato	,{0x09, "AIX boot partition or Coherent"}
19258234Skato	,{0x0A, "OS/2 Boot Manager or OPUS"}
19358234Skato	,{0x0B, "DOS or Windows 95 with 32 bit FAT"}
19458234Skato	,{0x0C, "DOS or Windows 95 with 32 bit FAT, LBA"}
19558234Skato	,{0x0E, "Primary 'big' DOS (> 32MB, LBA)"}
19658234Skato	,{0x0F, "Extended DOS, LBA"}
19758234Skato	,{0x10, "OPUS"}
19858234Skato	,{0x40, "VENIX 286"}
19958234Skato	,{0x50, "DM"}
20058234Skato	,{0x51, "DM"}
20158234Skato	,{0x52, "CP/M or Microport SysV/AT"}
20258234Skato	,{0x56, "GB"}
20358234Skato	,{0x61, "Speed"}
20458234Skato	,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
20558234Skato	,{0x64, "Novell Netware 2.xx"}
20658234Skato	,{0x65, "Novell Netware 3.xx"}
20758234Skato	,{0x75, "PCIX"}
20858234Skato	,{0x80, "Minix 1.1 ... 1.4a"}
20958234Skato	,{0x81, "Minix 1.4b ... 1.5.10"}
21058234Skato	,{0x82, "Linux swap or Solaris x86"}
211102231Strhodes	,{0x83, "Linux file system"}
212102231Strhodes	,{0x93, "Amoeba file system"}
21358234Skato	,{0x94, "Amoeba bad block table"}
21458234Skato	,{0x9F, "BSD/OS"}
21558234Skato	,{0xA5, "FreeBSD/NetBSD/386BSD"}
21658234Skato	,{0xA6, "OpenBSD"}
21758234Skato	,{0xA7, "NEXTSTEP"}
21858234Skato	,{0xA9, "NetBSD"}
219102231Strhodes	,{0xB7, "BSDI BSD/386 file system"}
22058234Skato	,{0xB8, "BSDI BSD/386 swap"}
22158234Skato	,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
22258234Skato	,{0xE1, "Speed"}
22358234Skato	,{0xE3, "Speed"}
22458234Skato	,{0xE4, "Speed"}
22558234Skato	,{0xF1, "Speed"}
22658234Skato	,{0xF2, "DOS 3.3+ Secondary"}
22758234Skato	,{0xF4, "Speed"}
22858234Skato	,{0xFF, "BBT (Bad Blocks Table)"}
22958234Skato#endif
23058234Skato};
23158234Skato
23258234Skatostatic void print_s0(int which);
23358234Skatostatic void print_part(int i);
23458234Skatostatic void init_sector0(unsigned long start);
23558234Skatostatic void init_boot(void);
23658234Skatostatic void change_part(int i);
23758234Skatostatic void print_params();
23858234Skatostatic void change_active(int which);
23958234Skatostatic void change_code();
24058234Skatostatic void get_params_to_use();
24158234Skato#ifdef PC98
24258234Skatostatic void dos(int sec, int size, unsigned short *c, unsigned char *s,
24358234Skato		unsigned char *h);
24458234Skato#else
24558234Skatostatic void dos(int sec, int size, unsigned char *c, unsigned char *s,
24658234Skato		unsigned char *h);
24758234Skato#endif
24858234Skatostatic int open_disk(int u_flag);
24958234Skatostatic ssize_t read_disk(off_t sector, void *buf);
25058234Skatostatic ssize_t write_disk(off_t sector, void *buf);
25158234Skatostatic int get_params();
25258234Skatostatic int read_s0();
25358234Skatostatic int write_s0();
25458234Skatostatic int ok(char *str);
25558234Skatostatic int decimal(char *str, int *num, int deflt);
25658234Skatostatic char *get_type(int type);
25758234Skatostatic int read_config(char *config_file);
25858234Skatostatic void reset_boot(void);
25958234Skatostatic void usage(void);
26058234Skato#if 0
26158234Skatostatic int hex(char *str, int *num, int deflt);
26258234Skato#endif
26358234Skato#ifdef PC98
26458234Skatostatic int string(char *str, char **ans);
26558234Skato#endif
26658234Skato
26758234Skato
26858234Skato
26958234Skatoint
27058234Skatomain(int argc, char *argv[])
27158234Skato{
27258234Skato	int	c, i;
27358234Skato
27458234Skato#ifdef PC98
27558234Skato	while ((c = getopt(argc, argv, "Bab:f:istuv12345678")) != -1)
27658234Skato#else
27758234Skato	while ((c = getopt(argc, argv, "BIab:f:istuv1234")) != -1)
27858234Skato#endif
27958234Skato		switch (c) {
28058234Skato		case 'B':
28158234Skato			B_flag = 1;
28258234Skato			break;
28358234Skato		case 'I':
28458234Skato			I_flag = 1;
28558234Skato			break;
28658234Skato		case 'a':
28758234Skato			a_flag = 1;
28858234Skato			break;
28958234Skato		case 'b':
29058234Skato			b_flag = optarg;
29158234Skato			break;
29258234Skato		case 'f':
29358234Skato			f_flag = optarg;
29458234Skato			break;
29558234Skato		case 'i':
29658234Skato			i_flag = 1;
29758234Skato			break;
29858234Skato		case 's':
29958234Skato			s_flag = 1;
30058234Skato			break;
30158234Skato		case 't':
30258234Skato			t_flag = 1;
30358234Skato			break;
30458234Skato		case 'u':
30558234Skato			u_flag = 1;
30658234Skato			break;
30758234Skato		case 'v':
30858234Skato			v_flag = 1;
30958234Skato			break;
31058234Skato		case '1':
31158234Skato		case '2':
31258234Skato		case '3':
31358234Skato		case '4':
31458234Skato#ifdef PC98
31558234Skato		case '5':
31658234Skato		case '6':
31758234Skato		case '7':
31858234Skato		case '8':
31958234Skato#endif
32058234Skato			partition = c - '0';
32158234Skato			break;
32258234Skato		default:
32358234Skato			usage();
32458234Skato		}
32558234Skato	if (f_flag || i_flag)
32658234Skato		u_flag = 1;
32758234Skato	if (t_flag)
32858234Skato		v_flag = 1;
32958234Skato	argc -= optind;
33058234Skato	argv += optind;
33158234Skato
33258234Skato	if (argc > 0)
33358234Skato	{
33458234Skato		static char realname[12];
33558234Skato
33669793Sobrien		if(strncmp(argv[0], _PATH_DEV, sizeof _PATH_DEV - 2) == 0)
33758234Skato			disk = argv[0];
33858234Skato		else
33958234Skato		{
34069793Sobrien			snprintf(realname, 12, "%s%s", _PATH_DEV, argv[0]);
34158234Skato			disk = realname;
34258234Skato		}
34358234Skato
34458234Skato		if (open_disk(u_flag) < 0)
34558234Skato			err(1, "cannot open disk %s", disk);
34658234Skato	}
34758234Skato	else
34858234Skato	{
34958234Skato		int rv = 0;
35058234Skato
35158234Skato		for(i = 0; disks[i]; i++)
35258234Skato		{
35358234Skato			disk = disks[i];
35458234Skato			rv = open_disk(u_flag);
35558234Skato			if(rv != -2) break;
35658234Skato		}
35758234Skato		if(rv < 0)
35858234Skato			err(1, "cannot open any disk");
35958234Skato	}
36058234Skato	if (s_flag)
36158234Skato	{
36258234Skato		int i;
36358234Skato		struct dos_partition *partp;
36458234Skato
36558234Skato		if (read_s0())
36658234Skato			err(1, "read_s0");
36758234Skato		printf("%s: %d cyl %d hd %d sec\n", disk, dos_cyls, dos_heads,
36858234Skato		    dos_sectors);
36958234Skato#ifdef PC98
37058234Skato		printf("Part  %11s %11s SID\n", "Start", "Size");
37158234Skato#else
37258234Skato		printf("Part  %11s %11s Type Flags\n", "Start", "Size");
37358234Skato#endif
37458234Skato		for (i = 0; i < NDOSPART; i++) {
37558234Skato			partp = ((struct dos_partition *) &mboot.parts) + i;
37658234Skato#ifdef PC98
37758234Skato			if (partp->dp_sid == 0)
37858234Skato#else
37958234Skato			if (partp->dp_start == 0 && partp->dp_size == 0)
38058234Skato#endif
38158234Skato				continue;
38293266Simp			printf("%4d: %11lu %11lu 0x%02x\n", i + 1,
38358234Skato#ifdef PC98
38458234Skato			    partp->dp_scyl * cylsecs,
38558234Skato			    (partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs,
38658234Skato				partp->dp_sid);
38758234Skato#else
38858234Skato			    (u_long) partp->dp_start,
38958234Skato			    (u_long) partp->dp_size, partp->dp_typ,
39058234Skato			    partp->dp_flag);
39158234Skato#endif
39258234Skato		}
39358234Skato		exit(0);
39458234Skato	}
39558234Skato
39658234Skato	printf("******* Working on device %s *******\n",disk);
39758234Skato
39858234Skato#ifndef PC98
39958234Skato	if (I_flag)
40058234Skato	{
40158234Skato		struct dos_partition *partp;
40258234Skato
40358234Skato		read_s0();
40458234Skato		reset_boot();
40558234Skato		partp = (struct dos_partition *) (&mboot.parts[0]);
40658234Skato		partp->dp_typ = DOSPTYP_386BSD;
40758234Skato		partp->dp_flag = ACTIVE;
40858234Skato		partp->dp_start = dos_sectors;
40958234Skato		partp->dp_size = disksecs - dos_sectors;
41058234Skato
41158234Skato		dos(partp->dp_start, partp->dp_size,
41258234Skato		    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
41358234Skato		dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
41458234Skato		    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
41558234Skato		if (v_flag)
41658234Skato			print_s0(-1);
41758234Skato		write_s0();
41858234Skato		exit(0);
41958234Skato	}
42058234Skato#endif
42158234Skato	if (f_flag)
42258234Skato	{
42358234Skato#ifndef PC98
42458234Skato	    if (read_s0() || i_flag)
42558234Skato	    {
42658234Skato		reset_boot();
42758234Skato	    }
42858234Skato
42958234Skato	    if (!read_config(f_flag))
43058234Skato	    {
43158234Skato		exit(1);
43258234Skato	    }
43358234Skato#endif
43458234Skato	    if (v_flag)
43558234Skato	    {
43658234Skato		print_s0(-1);
43758234Skato	    }
43858234Skato	    if (!t_flag)
43958234Skato	    {
44058234Skato		write_s0();
44158234Skato	    }
44258234Skato	}
44358234Skato	else
44458234Skato	{
44558234Skato	    if(u_flag)
44658234Skato	    {
44758234Skato		get_params_to_use();
44858234Skato	    }
44958234Skato	    else
45058234Skato	    {
45158234Skato		print_params();
45258234Skato	    }
45358234Skato
45458234Skato	    if (read_s0())
45558234Skato		init_sector0(1);
45658234Skato
45758234Skato	    printf("Media sector size is %d\n", secsize);
45858234Skato	    printf("Warning: BIOS sector numbering starts with sector 1\n");
45958234Skato	    printf("Information from DOS bootblock is:\n");
46058234Skato	    if (partition == -1)
46158234Skato		for (i = 1; i <= NDOSPART; i++)
46258234Skato		    change_part(i);
46358234Skato	    else
46458234Skato		change_part(partition);
46558234Skato
46658234Skato	    if (u_flag || a_flag)
46758234Skato		change_active(partition);
46858234Skato
46958234Skato	    if (B_flag)
47058234Skato		change_code();
47158234Skato
47258234Skato	    if (u_flag || a_flag || B_flag) {
47358234Skato		if (!t_flag)
47458234Skato		{
47558234Skato		    printf("\nWe haven't changed the partition table yet.  ");
47658234Skato		    printf("This is your last chance.\n");
47758234Skato		}
47858234Skato		print_s0(-1);
47958234Skato		if (!t_flag)
48058234Skato		{
48158234Skato		    if (ok("Should we write new partition table?"))
48258234Skato			write_s0();
48358234Skato		}
48458234Skato		else
48558234Skato		{
48658234Skato		    printf("\n-t flag specified -- partition table not written.\n");
48758234Skato		}
48858234Skato	    }
48958234Skato	}
49058234Skato
49158234Skato	exit(0);
49258234Skato}
49358234Skato
49458234Skatostatic void
49558234Skatousage()
49658234Skato{
49758234Skato	fprintf(stderr, "%s%s",
49858234Skato		"usage: fdisk [-Batu] [-b bootcode] [-12345678] [disk]\n",
49958234Skato 		"       fdisk -f configfile [-itv] [disk]\n");
50058234Skato        exit(1);
50158234Skato}
50258234Skato
50358234Skatostatic void
50458234Skatoprint_s0(int which)
50558234Skato{
50658234Skatoint	i;
50758234Skato
50858234Skato	print_params();
50958234Skato	printf("Information from DOS bootblock is:\n");
51058234Skato	if (which == -1)
51158234Skato		for (i = 1; i <= NDOSPART; i++)
51258234Skato			printf("%d: ", i), print_part(i);
51358234Skato	else
51458234Skato		print_part(which);
51558234Skato}
51658234Skato
51758234Skatostatic struct dos_partition mtpart = { 0 };
51858234Skato
51958234Skatostatic void
52058234Skatoprint_part(int i)
52158234Skato{
52258234Skato	struct	  dos_partition *partp;
52358234Skato	u_int64_t part_mb;
52458234Skato
52558234Skato	partp = ((struct dos_partition *) &mboot.parts) + i - 1;
52658234Skato
52758234Skato	if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
52858234Skato		printf("<UNUSED>\n");
52958234Skato		return;
53058234Skato	}
53158234Skato	/*
53258234Skato	 * Be careful not to overflow.
53358234Skato	 */
53458234Skato#ifdef PC98
53558234Skato	printf("sysmid %d,(%s)\n", partp->dp_mid, get_type(partp->dp_mid));
53658234Skato	printf("    start %d, size %d (%d Meg), sid %d\n",
53758234Skato		partp->dp_scyl * cylsecs ,
53858234Skato		(partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs,
53958234Skato		(partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs * 512 / (1024 * 1024),
54058234Skato		partp->dp_sid);
54158234Skato#else
54258234Skato	part_mb = partp->dp_size;
54358234Skato	part_mb *= secsize;
54458234Skato	part_mb /= (1024 * 1024);
54558234Skato	printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
54658234Skato	printf("    start %lu, size %lu (%qd Meg), flag %x%s\n",
54758234Skato		(u_long)partp->dp_start,
54858234Skato		(u_long)partp->dp_size,
54958234Skato		part_mb,
55058234Skato		partp->dp_flag,
55158234Skato		partp->dp_flag == ACTIVE ? " (active)" : "");
55258234Skato#endif
55358234Skato	printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
55458234Skato		,DPCYL(partp->dp_scyl, partp->dp_ssect)
55558234Skato		,DPSECT(partp->dp_ssect)
55658234Skato		,partp->dp_shd
55758234Skato		,DPCYL(partp->dp_ecyl, partp->dp_esect)
55858234Skato		,DPSECT(partp->dp_esect)
55958234Skato		,partp->dp_ehd);
56058234Skato#ifdef PC98
56158234Skato	printf ("\tsystem Name %.16s\n",partp->dp_name);
56258234Skato#endif
56358234Skato}
56458234Skato
56558234Skato
56658234Skatostatic void
56758234Skatoinit_boot(void)
56858234Skato{
56958234Skato#ifndef PC98
57058234Skato	const char *fname;
57158234Skato	int fd;
57258234Skato
57358234Skato	fname = b_flag ? b_flag : "/boot/mbr";
57458234Skato	if ((fd = open(fname, O_RDONLY)) == -1 ||
57558234Skato	    read(fd, mboot.bootinst, DOSPARTOFF) == -1 ||
57658234Skato	    close(fd))
57758234Skato		err(1, "%s", fname);
57858234Skato#endif
57958234Skato	mboot.signature = BOOT_MAGIC;
58058234Skato}
58158234Skato
58258234Skato
58358234Skatostatic void
58458234Skatoinit_sector0(unsigned long start)
58558234Skato{
58658234Skatostruct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
58758234Skatounsigned long size = disksecs - start;
58858234Skato
58958234Skato	init_boot();
59058234Skato
59158234Skato#ifdef PC98
59258234Skato	partp->dp_mid = DOSMID_386BSD;
59358234Skato	partp->dp_sid = DOSSID_386BSD;
59458234Skato
59558234Skato	dos(start, size, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
59658234Skato	partp->dp_ipl_cyl = partp->dp_scyl;
59758234Skato	partp->dp_ipl_sct = partp->dp_ssect;
59858234Skato	partp->dp_ipl_head = partp->dp_shd;
59958234Skato	dos(start+size-cylsecs, size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
60058234Skato#else
60158234Skato	partp->dp_typ = DOSPTYP_386BSD;
60258234Skato	partp->dp_flag = ACTIVE;
60358234Skato	partp->dp_start = start;
60458234Skato	partp->dp_size = size;
60558234Skato
60658234Skato	dos(partp->dp_start, partp->dp_size,
60758234Skato	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
60858234Skato	dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
60958234Skato	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
61058234Skato#endif
61158234Skato}
61258234Skato
61358234Skatostatic void
61458234Skatochange_part(int i)
61558234Skato{
61658234Skatostruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i - 1;
61758234Skato
61858234Skato    printf("The data for partition %d is:\n", i);
61958234Skato    print_part(i);
62058234Skato
62158234Skato    if (u_flag && ok("Do you want to change it?")) {
62258234Skato	int tmp;
62358234Skato
62458234Skato	if (i_flag) {
62558234Skato		bzero((char *)partp, sizeof (struct dos_partition));
62658234Skato		if (i == 4) {
62758234Skato			init_sector0(1);
62858234Skato			printf("\nThe static data for the DOS partition 4 has been reinitialized to:\n");
62958234Skato			print_part(i);
63058234Skato		}
63158234Skato	}
63258234Skato
63358234Skato	do {
63458234Skato#ifdef PC98
63558234Skato		int x_start = partp->dp_scyl * cylsecs ;
63658234Skato		int x_size  = (partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs;
63758234Skato		Decimal("sysmid", partp->dp_mid, tmp);
63858234Skato		Decimal("syssid", partp->dp_sid, tmp);
63958234Skato		String ("system name", partp->dp_name, 16);
64058234Skato		Decimal("start", x_start, tmp);
64158234Skato		Decimal("size", x_size, tmp);
64258234Skato#else
64358234Skato		Decimal("sysid (165=FreeBSD)", partp->dp_typ, tmp);
64458234Skato		Decimal("start", partp->dp_start, tmp);
64558234Skato		Decimal("size", partp->dp_size, tmp);
64658234Skato#endif
64758234Skato		if (ok("Explicitly specify beg/end address ?"))
64858234Skato		{
64958234Skato			int	tsec,tcyl,thd;
65058234Skato			tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
65158234Skato			thd = partp->dp_shd;
65258234Skato			tsec = DPSECT(partp->dp_ssect);
65358234Skato			Decimal("beginning cylinder", tcyl, tmp);
65458234Skato			Decimal("beginning head", thd, tmp);
65558234Skato			Decimal("beginning sector", tsec, tmp);
65658234Skato			partp->dp_scyl = DOSCYL(tcyl);
65758234Skato			partp->dp_ssect = DOSSECT(tsec,tcyl);
65858234Skato			partp->dp_shd = thd;
65958234Skato#ifdef PC98
66058234Skato			partp->dp_ipl_cyl = partp->dp_scyl;
66158234Skato			partp->dp_ipl_sct = partp->dp_ssect;
66258234Skato			partp->dp_ipl_head = partp->dp_shd;
66358234Skato#endif
66458234Skato
66558234Skato			tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
66658234Skato			thd = partp->dp_ehd;
66758234Skato			tsec = DPSECT(partp->dp_esect);
66858234Skato			Decimal("ending cylinder", tcyl, tmp);
66958234Skato			Decimal("ending head", thd, tmp);
67058234Skato			Decimal("ending sector", tsec, tmp);
67158234Skato			partp->dp_ecyl = DOSCYL(tcyl);
67258234Skato			partp->dp_esect = DOSSECT(tsec,tcyl);
67358234Skato			partp->dp_ehd = thd;
67458234Skato		} else {
67558234Skato#ifdef PC98
67658234Skato			dos(x_start, x_size, &partp->dp_scyl,
67758234Skato			    &partp->dp_ssect, &partp->dp_shd);
67858234Skato			partp->dp_ipl_cyl = partp->dp_scyl;
67958234Skato			partp->dp_ipl_sct = partp->dp_ssect;
68058234Skato			partp->dp_ipl_head = partp->dp_shd;
68158234Skato			dos(x_start+x_size - cylsecs, x_size, &partp->dp_ecyl,
68258234Skato			    &partp->dp_esect, &partp->dp_ehd);
68358234Skato#else
68458234Skato			dos(partp->dp_start, partp->dp_size,
68558234Skato			    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
68658234Skato			dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
68758234Skato			    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
68858234Skato#endif
68958234Skato		}
69058234Skato
69158234Skato		print_part(i);
69258234Skato	} while (!ok("Are we happy with this entry?"));
69358234Skato    }
69458234Skato}
69558234Skato
69658234Skatostatic void
69758234Skatoprint_params()
69858234Skato{
69958234Skato	printf("parameters extracted from in-core disklabel are:\n");
70058234Skato	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
70158234Skato			,cyls,heads,sectors,cylsecs);
70258234Skato#ifndef PC98
70358234Skato	if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
70458234Skato		printf("Figures below won't work with BIOS for partitions not in cyl 1\n");
70558234Skato#endif
70658234Skato	printf("parameters to be used for BIOS calculations are:\n");
70758234Skato	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
70858234Skato		,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
70958234Skato}
71058234Skato
71158234Skatostatic void
71258234Skatochange_active(int which)
71358234Skato{
71458234Skatoint i;
71558234Skato#ifdef PC98
71658234Skatoint active = 8, tmp;
71758234Skato#else
71858234Skatoint active = 4, tmp;
71958234Skato#endif
72058234Skato
72158234Skatostruct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
72258234Skato
72358234Skato	if (a_flag && which != -1)
72458234Skato		active = which;
72558234Skato	if (!ok("Do you want to change the active partition?"))
72658234Skato		return;
72758234Skatosetactive:
72858234Skato#ifdef PC98
72958234Skato	active = 4;
73058234Skato#else
73158234Skato	active = 4;
73258234Skato#endif
73358234Skato	do {
73458234Skato		Decimal("active partition", active, tmp);
73558234Skato#ifdef PC98
73658234Skato		if (active < 1 || 8 < active) {
73758234Skato			printf("Active partition number must be in range 1-8."
73858234Skato					"  Try again.\n");
73958234Skato			goto setactive;
74058234Skato		}
74158234Skato#else
74258234Skato		if (active < 1 || 4 < active) {
74358234Skato			printf("Active partition number must be in range 1-4."
74458234Skato					"  Try again.\n");
74558234Skato			goto setactive;
74658234Skato		}
74758234Skato#endif
74858234Skato	} while (!ok("Are you happy with this choice"));
74958234Skato#ifdef PC98
75058234Skato	partp[active].dp_sid |= ACTIVE;
75158234Skato#else
75258234Skato	for (i = 0; i < NDOSPART; i++)
75358234Skato		partp[i].dp_flag = 0;
75458234Skato	if (active > 0 && active <= NDOSPART)
75558234Skato		partp[active-1].dp_flag = ACTIVE;
75658234Skato#endif
75758234Skato}
75858234Skato
75958234Skatostatic void
76058234Skatochange_code()
76158234Skato{
76258234Skato	if (ok("Do you want to change the boot code?"))
76358234Skato		init_boot();
76458234Skato
76558234Skato}
76658234Skato
76758234Skatovoid
76858234Skatoget_params_to_use()
76958234Skato{
77058234Skato	int	tmp;
77158234Skato	print_params();
77258234Skato	if (ok("Do you want to change our idea of what BIOS thinks ?"))
77358234Skato	{
77458234Skato		do
77558234Skato		{
77658234Skato			Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
77758234Skato			Decimal("BIOS's idea of #heads", dos_heads, tmp);
77858234Skato			Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
77958234Skato			dos_cylsecs = dos_heads * dos_sectors;
78058234Skato			print_params();
78158234Skato		}
78258234Skato		while(!ok("Are you happy with this choice"));
78358234Skato	}
78458234Skato}
78558234Skato
78658234Skato
78758234Skato/***********************************************\
78858234Skato* Change real numbers into strange dos numbers	*
78958234Skato\***********************************************/
79058234Skatostatic void
79158234Skatodos(sec, size, c, s, h)
79258234Skatoint sec, size;
79358234Skato#ifdef PC98
79458234Skatounsigned short *c;
79558234Skatounsigned char *s, *h;
79658234Skato#else
79758234Skatounsigned char *c, *s, *h;
79858234Skato#endif
79958234Skato{
80058234Skatoint cy;
80158234Skatoint hd;
80258234Skato
80358234Skato	if (sec == 0 && size == 0) {
80458234Skato		*s = *c = *h = 0;
80558234Skato		return;
80658234Skato	}
80758234Skato
80858234Skato	cy = sec / ( dos_cylsecs );
80958234Skato	sec = sec - cy * ( dos_cylsecs );
81058234Skato
81158234Skato	hd = sec / dos_sectors;
81258234Skato#ifdef PC98
81358234Skato	sec = (sec - hd * dos_sectors);
81458234Skato
81558234Skato	*h = hd;
81658234Skato	*c = cy;
81758234Skato	*s = sec;
81858234Skato#else
81958234Skato	sec = (sec - hd * dos_sectors) + 1;
82058234Skato
82158234Skato	*h = hd;
82258234Skato	*c = cy & 0xff;
82358234Skato	*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
82458234Skato#endif
82558234Skato}
82658234Skato
82758234Skatoint fd;
82858234Skato
82958234Skato	/* Getting device status */
83058234Skato
83158234Skatostatic int
83258234Skatoopen_disk(int u_flag)
83358234Skato{
83458234Skatostruct stat 	st;
83558234Skato
83658234Skato	if (stat(disk, &st) == -1) {
83758234Skato		warnx("can't get file status of %s", disk);
83858234Skato		return -1;
83958234Skato	}
84058234Skato	if ( !(st.st_mode & S_IFCHR) )
84158234Skato		warnx("device %s is not character special", disk);
84258234Skato	if ((fd = open(disk,
84358234Skato	    a_flag || I_flag || B_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) {
84458234Skato		if(errno == ENXIO)
84558234Skato			return -2;
84658234Skato		warnx("can't open device %s", disk);
84758234Skato		return -1;
84858234Skato	}
84958234Skato	if (get_params(0) == -1) {
85058234Skato		warnx("can't get disk parameters on %s", disk);
85158234Skato		return -1;
85258234Skato	}
85358234Skato	return fd;
85458234Skato}
85558234Skato
85658234Skatostatic ssize_t
85758234Skatoread_disk(off_t sector, void *buf)
85858234Skato{
85958234Skato	lseek(fd,(sector * 512), 0);
86058234Skato#ifdef PC98
86158234Skato	return read(fd, buf, secsize > MIN_SEC_SIZE ? secsize : MIN_SEC_SIZE * 2);
86258234Skato#else
86358234Skato	if( secsize == 0 )
86458234Skato		for( secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; secsize *= 2 )
86558234Skato			{
86658234Skato			/* try the read */
86758234Skato			int size = read(fd, buf, secsize);
86858234Skato			if( size == secsize )
86958234Skato				/* it worked so return */
87058234Skato				return secsize;
87158234Skato			}
87258234Skato	else
87358234Skato		return read( fd, buf, secsize );
87458234Skato
87558234Skato	/* we failed to read at any of the sizes */
87658234Skato	return -1;
87758234Skato#endif
87858234Skato}
87958234Skato
88058234Skatostatic ssize_t
88158234Skatowrite_disk(off_t sector, void *buf)
88258234Skato{
88358234Skato	lseek(fd,(sector * 512), 0);
88458234Skato	/* write out in the size that the read_disk found worked */
88558234Skato#ifdef PC98
88658234Skato	return write(fd, buf, secsize > MIN_SEC_SIZE ? secsize : MIN_SEC_SIZE * 2);
88758234Skato#else
88858234Skato	return write(fd, buf, secsize);
88958234Skato#endif
89058234Skato}
89158234Skato
89258234Skatostatic int
89358234Skatoget_params()
89458234Skato{
89558234Skato
89658234Skato    if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
89758234Skato	warnx("can't get disk parameters on %s; supplying dummy ones", disk);
89858234Skato	dos_cyls = cyls = 1;
89958234Skato	dos_heads = heads = 1;
90058234Skato	dos_sectors = sectors = 1;
90158234Skato	dos_cylsecs = cylsecs = heads * sectors;
90258234Skato	disksecs = cyls * heads * sectors;
90358234Skato#ifdef PC98
90458234Skato	secsize = disklabel.d_secsize;
90558234Skato#endif
90658234Skato	return disksecs;
90758234Skato    }
90858234Skato
90958234Skato    dos_cyls = cyls = disklabel.d_ncylinders;
91058234Skato    dos_heads = heads = disklabel.d_ntracks;
91158234Skato    dos_sectors = sectors = disklabel.d_nsectors;
91258234Skato    dos_cylsecs = cylsecs = heads * sectors;
91358234Skato    disksecs = cyls * heads * sectors;
91458234Skato#ifdef PC98
91558234Skato    secsize = disklabel.d_secsize;
91658234Skato#endif
91758234Skato    return (disksecs);
91858234Skato}
91958234Skato
92058234Skato
92158234Skatostatic int
92258234Skatoread_s0()
92358234Skato{
92458234Skato	if (read_disk(0, (char *) mboot.bootinst) == -1) {
92558234Skato		warnx("can't read fdisk partition table");
92658234Skato		return -1;
92758234Skato	}
92858234Skato	if (mboot.signature != BOOT_MAGIC) {
92958234Skato		warnx("invalid fdisk partition table found");
93058234Skato		/* So should we initialize things */
93158234Skato		return -1;
93258234Skato	}
93358234Skato	return 0;
93458234Skato}
93558234Skato
93658234Skatostatic int
93758234Skatowrite_s0()
93858234Skato{
93958234Skato#ifdef NOT_NOW
94058234Skato	int	flag;
94158234Skato#endif
94258234Skato	if (iotest) {
94358234Skato		print_s0(-1);
94458234Skato		return 0;
94558234Skato	}
94658234Skato	/*
94758234Skato	 * write enable label sector before write (if necessary),
94858234Skato	 * disable after writing.
94958234Skato	 * needed if the disklabel protected area also protects
95058234Skato	 * sector 0. (e.g. empty disk)
95158234Skato	 */
95258234Skato#ifdef NOT_NOW
95358234Skato	flag = 1;
95458234Skato	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
95558234Skato		warn("ioctl DIOCWLABEL");
95658234Skato#endif
95758234Skato	if (write_disk(0, (char *) mboot.bootinst) == -1) {
95858234Skato		warn("can't write fdisk partition table");
95958234Skato		return -1;
96058234Skato#ifdef NOT_NOW
96158234Skato	flag = 0;
96258234Skato	(void) ioctl(fd, DIOCWLABEL, &flag);
96358234Skato#endif
96458234Skato	}
96558234Skato	return(0);
96658234Skato}
96758234Skato
96858234Skato
96958234Skatostatic int
97058234Skatook(str)
97158234Skatochar *str;
97258234Skato{
97358234Skato	printf("%s [n] ", str);
97458234Skato	fgets(lbuf, LBUF, stdin);
97558234Skato	lbuf[strlen(lbuf)-1] = 0;
97658234Skato
97758234Skato	if (*lbuf &&
97858234Skato		(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
97958234Skato		 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
98058234Skato		return 1;
98158234Skato	else
98258234Skato		return 0;
98358234Skato}
98458234Skato
98558234Skatostatic int
98658234Skatodecimal(char *str, int *num, int deflt)
98758234Skato{
98858234Skatoint acc = 0, c;
98958234Skatochar *cp;
99058234Skato
99158234Skato	while (1) {
99258234Skato		printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
99358234Skato		fgets(lbuf, LBUF, stdin);
99458234Skato		lbuf[strlen(lbuf)-1] = 0;
99558234Skato
99658234Skato		if (!*lbuf)
99758234Skato			return 0;
99858234Skato
99958234Skato		cp = lbuf;
100058234Skato		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
100158234Skato		if (!c)
100258234Skato			return 0;
100358234Skato		while ((c = *cp++)) {
100458234Skato			if (c <= '9' && c >= '0')
100558234Skato				acc = acc * 10 + c - '0';
100658234Skato			else
100758234Skato				break;
100858234Skato		}
100958234Skato		if (c == ' ' || c == '\t')
101058234Skato			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
101158234Skato		if (!c) {
101258234Skato			*num = acc;
101358234Skato			return 1;
101458234Skato		} else
101558234Skato			printf("%s is an invalid decimal number.  Try again.\n",
101658234Skato				lbuf);
101758234Skato	}
101858234Skato
101958234Skato}
102058234Skato
102158234Skato#if 0
102258234Skatostatic int
102358234Skatohex(char *str, int *num, int deflt)
102458234Skato{
102558234Skatoint acc = 0, c;
102658234Skatochar *cp;
102758234Skato
102858234Skato	while (1) {
102958234Skato		printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
103058234Skato		fgets(lbuf, LBUF, stdin);
103158234Skato		lbuf[strlen(lbuf)-1] = 0;
103258234Skato
103358234Skato		if (!*lbuf)
103458234Skato			return 0;
103558234Skato
103658234Skato		cp = lbuf;
103758234Skato		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
103858234Skato		if (!c)
103958234Skato			return 0;
104058234Skato		while ((c = *cp++)) {
104158234Skato			if (c <= '9' && c >= '0')
104258234Skato				acc = (acc << 4) + c - '0';
104358234Skato			else if (c <= 'f' && c >= 'a')
104458234Skato				acc = (acc << 4) + c - 'a' + 10;
104558234Skato			else if (c <= 'F' && c >= 'A')
104658234Skato				acc = (acc << 4) + c - 'A' + 10;
104758234Skato			else
104858234Skato				break;
104958234Skato		}
105058234Skato		if (c == ' ' || c == '\t')
105158234Skato			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
105258234Skato		if (!c) {
105358234Skato			*num = acc;
105458234Skato			return 1;
105558234Skato		} else
105658234Skato			printf("%s is an invalid hex number.  Try again.\n",
105758234Skato				lbuf);
105858234Skato	}
105958234Skato
106058234Skato}
106158234Skato#endif
106258234Skato
106358234Skato#ifdef PC98
106458234Skatostatic int
106558234Skatostring(char *str, char **ans)
106658234Skato{
106758234Skato#ifdef PC98
106858234Skatoint i;
106958234Skato#endif
107058234Skatoint c;
107158234Skatochar *cp = lbuf;
107258234Skato
107358234Skato	while (1) {
107458234Skato		printf("Supply a string value for \"%s\" [%s] ", str, *ans);
107558234Skato		fgets(lbuf, LBUF, stdin);
107658234Skato		lbuf[strlen(lbuf)-1] = 0;
107758234Skato
107858234Skato		if (!*lbuf)
107958234Skato			return 0;
108058234Skato
108158234Skato		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
108258234Skato		if (c == '"') {
108358234Skato			c = *++cp;
108458234Skato			*ans = cp;
108558234Skato			while ((c = *cp) && c != '"') cp++;
108658234Skato		} else {
108758234Skato			*ans = cp;
108858234Skato			while ((c = *cp) && c != ' ' && c != '\t') cp++;
108958234Skato		}
109058234Skato
109158234Skato#ifdef PC98
109258234Skato		for (i = strlen(*ans); i < 16; i++)
109358234Skato			(*ans)[i] = ' ';
109458234Skato		(*ans)[16] = 0;
109558234Skato#else
109658234Skato		if (c)
109758234Skato			*cp = 0;
109858234Skato#endif
109958234Skato		return 1;
110058234Skato	}
110158234Skato}
110258234Skato#endif
110358234Skato
110458234Skatostatic char *
110558234Skatoget_type(int type)
110658234Skato{
110758234Skato	int	numentries = (sizeof(part_types)/sizeof(struct part_type));
110858234Skato	int	counter = 0;
110958234Skato	struct	part_type *ptr = part_types;
111058234Skato
111158234Skato
111258234Skato	while(counter < numentries)
111358234Skato	{
111458234Skato#ifdef PC98
111558234Skato		if(ptr->type == (type & 0x7f))
111658234Skato#else
111758234Skato		if(ptr->type == type)
111858234Skato#endif
111958234Skato		{
112058234Skato			return(ptr->name);
112158234Skato		}
112258234Skato		ptr++;
112358234Skato		counter++;
112458234Skato	}
112558234Skato	return("unknown");
112658234Skato}
112758234Skato
112858234Skato#ifndef PC98
112958234Skatostatic void
113058234Skatoparse_config_line(line, command)
113158234Skato    char	*line;
113258234Skato    CMD		*command;
113358234Skato{
113458234Skato    char	*cp, *end;
113558234Skato
113658234Skato    cp = line;
113758234Skato    while (1)	/* dirty trick used to insure one exit point for this
113858234Skato		   function */
113958234Skato    {
114058234Skato	memset(command, 0, sizeof(*command));
114158234Skato
114258234Skato	while (isspace(*cp)) ++cp;
114358234Skato	if (*cp == '\0' || *cp == '#')
114458234Skato	{
114558234Skato	    break;
114658234Skato	}
114758234Skato	command->cmd = *cp++;
114858234Skato
114958234Skato	/*
115058234Skato	 * Parse args
115158234Skato	 */
115258234Skato	while (1)
115358234Skato	{
115458234Skato	    while (isspace(*cp)) ++cp;
115558234Skato	    if (*cp == '#')
115658234Skato	    {
115758234Skato		break;		/* found comment */
115858234Skato	    }
115958234Skato	    if (isalpha(*cp))
116058234Skato	    {
116158234Skato		command->args[command->n_args].argtype = *cp++;
116258234Skato	    }
116358234Skato	    if (!isdigit(*cp))
116458234Skato	    {
116558234Skato		break;		/* assume end of line */
116658234Skato	    }
116758234Skato	    end = NULL;
116858234Skato	    command->args[command->n_args].arg_val = strtol(cp, &end, 0);
116958234Skato	    if (cp == end)
117058234Skato	    {
117158234Skato		break;		/* couldn't parse number */
117258234Skato	    }
117358234Skato	    cp = end;
117458234Skato	    command->n_args++;
117558234Skato	}
117658234Skato	break;
117758234Skato    }
117858234Skato}
117958234Skato
118058234Skato
118158234Skatostatic int
118258234Skatoprocess_geometry(command)
118358234Skato    CMD		*command;
118458234Skato{
118558234Skato    int		status = 1, i;
118658234Skato
118758234Skato    while (1)
118858234Skato    {
118958234Skato	geom_processed = 1;
119058234Skato	if (part_processed)
119158234Skato	{
119258234Skato	    warnx(
119358234Skato	"ERROR line %d: the geometry specification line must occur before\n\
119458234Skato    all partition specifications",
119558234Skato		    current_line_number);
119658234Skato	    status = 0;
119758234Skato	    break;
119858234Skato	}
119958234Skato	if (command->n_args != 3)
120058234Skato	{
120158234Skato	    warnx("ERROR line %d: incorrect number of geometry args",
120258234Skato		    current_line_number);
120358234Skato	    status = 0;
120458234Skato	    break;
120558234Skato	}
120658234Skato	dos_cyls = -1;
120758234Skato	dos_heads = -1;
120858234Skato	dos_sectors = -1;
120958234Skato	for (i = 0; i < 3; ++i)
121058234Skato	{
121158234Skato	    switch (command->args[i].argtype)
121258234Skato	    {
121358234Skato	    case 'c':
121458234Skato		dos_cyls = command->args[i].arg_val;
121558234Skato		break;
121658234Skato	    case 'h':
121758234Skato		dos_heads = command->args[i].arg_val;
121858234Skato		break;
121958234Skato	    case 's':
122058234Skato		dos_sectors = command->args[i].arg_val;
122158234Skato		break;
122258234Skato	    default:
122358234Skato		warnx(
122458234Skato		"ERROR line %d: unknown geometry arg type: '%c' (0x%02x)",
122558234Skato			current_line_number, command->args[i].argtype,
122658234Skato			command->args[i].argtype);
122758234Skato		status = 0;
122858234Skato		break;
122958234Skato	    }
123058234Skato	}
123158234Skato	if (status == 0)
123258234Skato	{
123358234Skato	    break;
123458234Skato	}
123558234Skato
123658234Skato	dos_cylsecs = dos_heads * dos_sectors;
123758234Skato
123858234Skato	/*
123958234Skato	 * Do sanity checks on parameter values
124058234Skato	 */
124158234Skato	if (dos_cyls < 0)
124258234Skato	{
124358234Skato	    warnx("ERROR line %d: number of cylinders not specified",
124458234Skato		    current_line_number);
124558234Skato	    status = 0;
124658234Skato	}
124758234Skato	if (dos_cyls == 0 || dos_cyls > 1024)
124858234Skato	{
124958234Skato	    warnx(
125058234Skato	"WARNING line %d: number of cylinders (%d) may be out-of-range\n\
125158234Skato    (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\
125258234Skato    is dedicated to FreeBSD)",
125358234Skato		    current_line_number, dos_cyls);
125458234Skato	}
125558234Skato
125658234Skato	if (dos_heads < 0)
125758234Skato	{
125858234Skato	    warnx("ERROR line %d: number of heads not specified",
125958234Skato		    current_line_number);
126058234Skato	    status = 0;
126158234Skato	}
126258234Skato	else if (dos_heads < 1 || dos_heads > 256)
126358234Skato	{
126458234Skato	    warnx("ERROR line %d: number of heads must be within (1-256)",
126558234Skato		    current_line_number);
126658234Skato	    status = 0;
126758234Skato	}
126858234Skato
126958234Skato	if (dos_sectors < 0)
127058234Skato	{
127158234Skato	    warnx("ERROR line %d: number of sectors not specified",
127258234Skato		    current_line_number);
127358234Skato	    status = 0;
127458234Skato	}
127558234Skato	else if (dos_sectors < 1 || dos_sectors > 63)
127658234Skato	{
127758234Skato	    warnx("ERROR line %d: number of sectors must be within (1-63)",
127858234Skato		    current_line_number);
127958234Skato	    status = 0;
128058234Skato	}
128158234Skato
128258234Skato	break;
128358234Skato    }
128458234Skato    return (status);
128558234Skato}
128658234Skato
128758234Skato
128858234Skatostatic int
128958234Skatoprocess_partition(command)
129058234Skato    CMD		*command;
129158234Skato{
129258234Skato    int				status = 0, partition;
129358234Skato    unsigned long		chunks, adj_size, max_end;
129458234Skato    struct dos_partition	*partp;
129558234Skato
129658234Skato    while (1)
129758234Skato    {
129858234Skato	part_processed = 1;
129958234Skato	if (command->n_args != 4)
130058234Skato	{
130158234Skato	    warnx("ERROR line %d: incorrect number of partition args",
130258234Skato		    current_line_number);
130358234Skato	    break;
130458234Skato	}
130558234Skato	partition = command->args[0].arg_val;
130658234Skato	if (partition < 1 || partition > 4)
130758234Skato	{
130858234Skato	    warnx("ERROR line %d: invalid partition number %d",
130958234Skato		    current_line_number, partition);
131058234Skato	    break;
131158234Skato	}
131258234Skato	partp = ((struct dos_partition *) &mboot.parts) + partition - 1;
131358234Skato	bzero((char *)partp, sizeof (struct dos_partition));
131458234Skato	partp->dp_typ = command->args[1].arg_val;
131558234Skato	partp->dp_start = command->args[2].arg_val;
131658234Skato	partp->dp_size = command->args[3].arg_val;
131758234Skato	max_end = partp->dp_start + partp->dp_size;
131858234Skato
131958234Skato	if (partp->dp_typ == 0)
132058234Skato	{
132158234Skato	    /*
132258234Skato	     * Get out, the partition is marked as unused.
132358234Skato	     */
132458234Skato	    /*
132558234Skato	     * Insure that it's unused.
132658234Skato	     */
132758234Skato	    bzero((char *)partp, sizeof (struct dos_partition));
132858234Skato	    status = 1;
132958234Skato	    break;
133058234Skato	}
133158234Skato
133258234Skato	/*
133358234Skato	 * Adjust start upwards, if necessary, to fall on an head boundary.
133458234Skato	 */
133558234Skato	if (partp->dp_start % dos_sectors != 0)
133658234Skato	{
133758234Skato	    adj_size =
133858234Skato		(partp->dp_start / dos_sectors + 1) * dos_sectors;
133958234Skato	    if (adj_size > max_end)
134058234Skato	    {
134158234Skato		/*
134258234Skato		 * Can't go past end of partition
134358234Skato		 */
134458234Skato		warnx(
134558234Skato	"ERROR line %d: unable to adjust start of partition %d to fall on\n\
134658234Skato    a cylinder boundary",
134758234Skato			current_line_number, partition);
134858234Skato		break;
134958234Skato	    }
135058234Skato	    warnx(
135158234Skato	"WARNING: adjusting start offset of partition '%d' from %lu\n\
135258234Skato    to %lu, to round to an head boundary",
135358234Skato		    partition, (u_long)partp->dp_start, adj_size);
135458234Skato	    partp->dp_start = adj_size;
135558234Skato	}
135658234Skato
135758234Skato	/*
135858234Skato	 * Adjust size downwards, if necessary, to fall on a cylinder
135958234Skato	 * boundary.
136058234Skato	 */
136158234Skato	chunks =
136258234Skato	    ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs;
136358234Skato	adj_size = chunks - partp->dp_start;
136458234Skato	if (adj_size != partp->dp_size)
136558234Skato	{
136658234Skato	    warnx(
136758234Skato	"WARNING: adjusting size of partition '%d' from %lu to %lu,\n\
136858234Skato    to round to a cylinder boundary",
136958234Skato		    partition, (u_long)partp->dp_size, adj_size);
137058234Skato	    if (chunks > 0)
137158234Skato	    {
137258234Skato		partp->dp_size = adj_size;
137358234Skato	    }
137458234Skato	    else
137558234Skato	    {
137658234Skato		partp->dp_size = 0;
137758234Skato	    }
137858234Skato	}
137958234Skato	if (partp->dp_size < 1)
138058234Skato	{
138158234Skato	    warnx("ERROR line %d: size for partition '%d' is zero",
138258234Skato		    current_line_number, partition);
138358234Skato	    break;
138458234Skato	}
138558234Skato
138658234Skato	dos(partp->dp_start, partp->dp_size,
138758234Skato	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
138858234Skato	dos(partp->dp_start+partp->dp_size - 1, partp->dp_size,
138958234Skato	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
139058234Skato	status = 1;
139158234Skato	break;
139258234Skato    }
139358234Skato    return (status);
139458234Skato}
139558234Skato
139658234Skato
139758234Skatostatic int
139858234Skatoprocess_active(command)
139958234Skato    CMD		*command;
140058234Skato{
140158234Skato    int				status = 0, partition, i;
140258234Skato    struct dos_partition	*partp;
140358234Skato
140458234Skato    while (1)
140558234Skato    {
140658234Skato	active_processed = 1;
140758234Skato	if (command->n_args != 1)
140858234Skato	{
140958234Skato	    warnx("ERROR line %d: incorrect number of active args",
141058234Skato		    current_line_number);
141158234Skato	    status = 0;
141258234Skato	    break;
141358234Skato	}
141458234Skato	partition = command->args[0].arg_val;
141558234Skato	if (partition < 1 || partition > 4)
141658234Skato	{
141758234Skato	    warnx("ERROR line %d: invalid partition number %d",
141858234Skato		    current_line_number, partition);
141958234Skato	    break;
142058234Skato	}
142158234Skato	/*
142258234Skato	 * Reset active partition
142358234Skato	 */
142458234Skato	partp = ((struct dos_partition *) &mboot.parts);
142558234Skato	for (i = 0; i < NDOSPART; i++)
142658234Skato	    partp[i].dp_flag = 0;
142758234Skato	partp[partition-1].dp_flag = ACTIVE;
142858234Skato
142958234Skato	status = 1;
143058234Skato	break;
143158234Skato    }
143258234Skato    return (status);
143358234Skato}
143458234Skato
143558234Skato
143658234Skatostatic int
143758234Skatoprocess_line(line)
143858234Skato    char	*line;
143958234Skato{
144058234Skato    CMD		command;
144158234Skato    int		status = 1;
144258234Skato
144358234Skato    while (1)
144458234Skato    {
144558234Skato	parse_config_line(line, &command);
144658234Skato	switch (command.cmd)
144758234Skato	{
144858234Skato	case 0:
144958234Skato	    /*
145058234Skato	     * Comment or blank line
145158234Skato	     */
145258234Skato	    break;
145358234Skato	case 'g':
145458234Skato	    /*
145558234Skato	     * Set geometry
145658234Skato	     */
145758234Skato	    status = process_geometry(&command);
145858234Skato	    break;
145958234Skato	case 'p':
146058234Skato	    status = process_partition(&command);
146158234Skato	    break;
146258234Skato	case 'a':
146358234Skato	    status = process_active(&command);
146458234Skato	    break;
146558234Skato	default:
146658234Skato	    status = 0;
146758234Skato	    break;
146858234Skato	}
146958234Skato	break;
147058234Skato    }
147158234Skato    return (status);
147258234Skato}
147358234Skato
147458234Skato
147558234Skatostatic int
147658234Skatoread_config(config_file)
147758234Skato    char *config_file;
147858234Skato{
147958234Skato    FILE	*fp = NULL;
148058234Skato    int		status = 1;
148158234Skato    char	buf[1010];
148258234Skato
148358234Skato    while (1)	/* dirty trick used to insure one exit point for this
148458234Skato		   function */
148558234Skato    {
148658234Skato	if (strcmp(config_file, "-") != 0)
148758234Skato	{
148858234Skato	    /*
148958234Skato	     * We're not reading from stdin
149058234Skato	     */
149158234Skato	    if ((fp = fopen(config_file, "r")) == NULL)
149258234Skato	    {
149358234Skato		status = 0;
149458234Skato		break;
149558234Skato	    }
149658234Skato	}
149758234Skato	else
149858234Skato	{
149958234Skato	    fp = stdin;
150058234Skato	}
150158234Skato	current_line_number = 0;
150258234Skato	while (!feof(fp))
150358234Skato	{
150458234Skato	    if (fgets(buf, sizeof(buf), fp) == NULL)
150558234Skato	    {
150658234Skato		break;
150758234Skato	    }
150858234Skato	    ++current_line_number;
150958234Skato	    status = process_line(buf);
151058234Skato	    if (status == 0)
151158234Skato	    {
151258234Skato		break;
151358234Skato	    }
151458234Skato	}
151558234Skato	break;
151658234Skato    }
151758234Skato    if (fp)
151858234Skato    {
151958234Skato	/*
152058234Skato	 * It doesn't matter if we're reading from stdin, as we've reached EOF
152158234Skato	 */
152258234Skato	fclose(fp);
152358234Skato    }
152458234Skato    return (status);
152558234Skato}
152658234Skato
152758234Skato
152858234Skatostatic void
152958234Skatoreset_boot(void)
153058234Skato{
153158234Skato    int				i;
153258234Skato    struct dos_partition	*partp;
153358234Skato
153458234Skato    init_boot();
153558234Skato    for (i = 0; i < 4; ++i)
153658234Skato    {
153758234Skato	partp = ((struct dos_partition *) &mboot.parts) + i;
153858234Skato	bzero((char *)partp, sizeof (struct dos_partition));
153958234Skato    }
154058234Skato}
154158234Skato#endif
1542