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