xref: /freebsd/sbin/fdisk/fdisk.c (revision 7cb29d33945b2263c6747f264fb6e1192bde0f61)
15b81b6b3SRodney W. Grimes /*
25b81b6b3SRodney W. Grimes  * Mach Operating System
35b81b6b3SRodney W. Grimes  * Copyright (c) 1992 Carnegie Mellon University
45b81b6b3SRodney W. Grimes  * All Rights Reserved.
55b81b6b3SRodney W. Grimes  *
65b81b6b3SRodney W. Grimes  * Permission to use, copy, modify and distribute this software and its
75b81b6b3SRodney W. Grimes  * documentation is hereby granted, provided that both the copyright
85b81b6b3SRodney W. Grimes  * notice and this permission notice appear in all copies of the
95b81b6b3SRodney W. Grimes  * software, derivative works or modified versions, and any portions
105b81b6b3SRodney W. Grimes  * thereof, and that both notices appear in supporting documentation.
115b81b6b3SRodney W. Grimes  *
125b81b6b3SRodney W. Grimes  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
135b81b6b3SRodney W. Grimes  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
145b81b6b3SRodney W. Grimes  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
155b81b6b3SRodney W. Grimes  *
165b81b6b3SRodney W. Grimes  * Carnegie Mellon requests users of this software to return to
175b81b6b3SRodney W. Grimes  *
185b81b6b3SRodney W. Grimes  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
195b81b6b3SRodney W. Grimes  *  School of Computer Science
205b81b6b3SRodney W. Grimes  *  Carnegie Mellon University
215b81b6b3SRodney W. Grimes  *  Pittsburgh PA 15213-3890
225b81b6b3SRodney W. Grimes  *
235b81b6b3SRodney W. Grimes  * any improvements or extensions that they make and grant Carnegie Mellon
245b81b6b3SRodney W. Grimes  * the rights to redistribute these changes.
255b81b6b3SRodney W. Grimes  */
265b81b6b3SRodney W. Grimes 
275b81b6b3SRodney W. Grimes #include <sys/types.h>
285b81b6b3SRodney W. Grimes #include <sys/disklabel.h>
295b81b6b3SRodney W. Grimes #include <stdio.h>
304be1e61bSAlexander Langer #include <string.h>
31e3038c6eSJoerg Wunsch #include <errno.h>
325b81b6b3SRodney W. Grimes #include <sys/stat.h>
335b81b6b3SRodney W. Grimes #include <sys/ioctl.h>
345b81b6b3SRodney W. Grimes #include <fcntl.h>
354be1e61bSAlexander Langer #include <unistd.h>
365b81b6b3SRodney W. Grimes 
375b81b6b3SRodney W. Grimes int iotest;
385b81b6b3SRodney W. Grimes 
395b81b6b3SRodney W. Grimes #define LBUF 100
405b81b6b3SRodney W. Grimes static char lbuf[LBUF];
415b81b6b3SRodney W. Grimes 
425b81b6b3SRodney W. Grimes /*
435b81b6b3SRodney W. Grimes  *
445b81b6b3SRodney W. Grimes  * Ported to 386bsd by Julian Elischer  Thu Oct 15 20:26:46 PDT 1992
455b81b6b3SRodney W. Grimes  *
465b81b6b3SRodney W. Grimes  * 14-Dec-89  Robert Baron (rvb) at Carnegie-Mellon University
475b81b6b3SRodney W. Grimes  *	Copyright (c) 1989	Robert. V. Baron
485b81b6b3SRodney W. Grimes  *	Created.
495b81b6b3SRodney W. Grimes  */
505b81b6b3SRodney W. Grimes 
515b81b6b3SRodney W. Grimes #define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
525b81b6b3SRodney W. Grimes #define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
535b81b6b3SRodney W. Grimes #define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
545b81b6b3SRodney W. Grimes 
555b81b6b3SRodney W. Grimes #define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
565b81b6b3SRodney W. Grimes 
577cb29d33SSøren Schmidt #define MAX_SEC_SIZE 2048	/* maximum section size that is supported */
587cb29d33SSøren Schmidt #define MIN_SEC_SIZE 512	/* the sector size to start sensing at */
597cb29d33SSøren Schmidt int secsize = 0;		/* the sensed sector size */
605b81b6b3SRodney W. Grimes 
61e3038c6eSJoerg Wunsch const char *disk;
62e3038c6eSJoerg Wunsch const char *disks[] =
63e3038c6eSJoerg Wunsch {
64e3038c6eSJoerg Wunsch   "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0
65e3038c6eSJoerg Wunsch };
66e3038c6eSJoerg Wunsch 
675b81b6b3SRodney W. Grimes char *name;
685b81b6b3SRodney W. Grimes 
695b81b6b3SRodney W. Grimes struct disklabel disklabel;		/* disk parameters */
705b81b6b3SRodney W. Grimes 
715b81b6b3SRodney W. Grimes int cyls, sectors, heads, cylsecs, disksecs;
725b81b6b3SRodney W. Grimes 
735b81b6b3SRodney W. Grimes struct mboot
745b81b6b3SRodney W. Grimes {
755b81b6b3SRodney W. Grimes 	unsigned char padding[2]; /* force the longs to be long alligned */
765b81b6b3SRodney W. Grimes 	unsigned char bootinst[DOSPARTOFF];
775b81b6b3SRodney W. Grimes 	struct	dos_partition parts[4];
785b81b6b3SRodney W. Grimes 	unsigned short int	signature;
797cb29d33SSøren Schmidt 	/* room to read in MBRs that are bigger then DEV_BSIZE */
807cb29d33SSøren Schmidt 	unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE];
815b81b6b3SRodney W. Grimes };
825b81b6b3SRodney W. Grimes struct mboot mboot;
835b81b6b3SRodney W. Grimes 
845b81b6b3SRodney W. Grimes #define ACTIVE 0x80
855b81b6b3SRodney W. Grimes #define BOOT_MAGIC 0xAA55
865b81b6b3SRodney W. Grimes 
875b81b6b3SRodney W. Grimes int dos_cyls;
885b81b6b3SRodney W. Grimes int dos_heads;
895b81b6b3SRodney W. Grimes int dos_sectors;
905b81b6b3SRodney W. Grimes int dos_cylsecs;
915b81b6b3SRodney W. Grimes 
925b81b6b3SRodney W. Grimes #define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
935b81b6b3SRodney W. Grimes #define DOSCYL(c)	(c & 0xff)
945b81b6b3SRodney W. Grimes static int partition = -1;
955b81b6b3SRodney W. Grimes 
965b81b6b3SRodney W. Grimes 
97f46af505SJordan K. Hubbard #define MAX_ARGS	10
98f46af505SJordan K. Hubbard 
99f46af505SJordan K. Hubbard static int	current_line_number;
100f46af505SJordan K. Hubbard 
101f46af505SJordan K. Hubbard static int	geom_processed = 0;
102f46af505SJordan K. Hubbard static int	part_processed = 0;
103f46af505SJordan K. Hubbard static int	active_processed = 0;
104f46af505SJordan K. Hubbard 
105f46af505SJordan K. Hubbard 
106f46af505SJordan K. Hubbard typedef struct cmd {
107f46af505SJordan K. Hubbard     char		cmd;
108f46af505SJordan K. Hubbard     int			n_args;
109f46af505SJordan K. Hubbard     struct arg {
110f46af505SJordan K. Hubbard 	char	argtype;
111f46af505SJordan K. Hubbard 	int	arg_val;
112f46af505SJordan K. Hubbard     }			args[MAX_ARGS];
113f46af505SJordan K. Hubbard } CMD;
114f46af505SJordan K. Hubbard 
115f46af505SJordan K. Hubbard 
1165b81b6b3SRodney W. Grimes static int a_flag  = 0;		/* set active partition */
1175b81b6b3SRodney W. Grimes static int i_flag  = 0;		/* replace partition data */
1185b81b6b3SRodney W. Grimes static int u_flag  = 0;		/* update partition data */
119f46af505SJordan K. Hubbard static int t_flag  = 0;		/* test only, if f_flag is given */
120f46af505SJordan K. Hubbard static char *f_flag = NULL;	/* Read config info from file */
121f46af505SJordan K. Hubbard static int v_flag  = 0;		/* Be verbose */
1225b81b6b3SRodney W. Grimes 
1235b81b6b3SRodney W. Grimes static unsigned char bootcode[] = {
1245b81b6b3SRodney W. Grimes 0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
1255b81b6b3SRodney W. Grimes 0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
1265b81b6b3SRodney W. Grimes 0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
1275b81b6b3SRodney W. Grimes 0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
1285b81b6b3SRodney W. Grimes 0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
1295b81b6b3SRodney W. Grimes 0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
1305b81b6b3SRodney W. Grimes 0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
1315b81b6b3SRodney W. Grimes 0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
1325b81b6b3SRodney W. Grimes 0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
1335b81b6b3SRodney W. Grimes 'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
1345b81b6b3SRodney W. Grimes 	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
1355b81b6b3SRodney W. Grimes 'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
1365b81b6b3SRodney W. Grimes 	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
1375b81b6b3SRodney W. Grimes 'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
1385b81b6b3SRodney W. Grimes 	'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
1395b81b6b3SRodney W. Grimes 'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
1405b81b6b3SRodney W. Grimes 	'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
1415b81b6b3SRodney W. Grimes 
1425b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1435b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1445b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1455b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1465b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1475b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1485b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1495b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1505b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1515b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1525b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1535b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1545b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
1555b81b6b3SRodney W. Grimes };
1565b81b6b3SRodney W. Grimes 
1575b81b6b3SRodney W. Grimes struct part_type
1585b81b6b3SRodney W. Grimes {
1595b81b6b3SRodney W. Grimes  unsigned char type;
1605b81b6b3SRodney W. Grimes  char *name;
1615b81b6b3SRodney W. Grimes }part_types[] =
1625b81b6b3SRodney W. Grimes {
1635b81b6b3SRodney W. Grimes 	 {0x00, "unused"}
1645b81b6b3SRodney W. Grimes 	,{0x01, "Primary DOS with 12 bit FAT"}
1655b81b6b3SRodney W. Grimes 	,{0x02, "XENIX / filesystem"}
1665b81b6b3SRodney W. Grimes 	,{0x03, "XENIX /usr filesystem"}
1675b81b6b3SRodney W. Grimes 	,{0x04, "Primary DOS with 16 bit FAT"}
1685b81b6b3SRodney W. Grimes 	,{0x05, "Extended DOS"}
1695b81b6b3SRodney W. Grimes 	,{0x06, "Primary 'big' DOS (> 32MB)"}
1705b81b6b3SRodney W. Grimes 	,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"}
1715b81b6b3SRodney W. Grimes 	,{0x08, "AIX filesystem"}
1725b81b6b3SRodney W. Grimes 	,{0x09, "AIX boot partition or Coherent"}
1735b81b6b3SRodney W. Grimes 	,{0x0A, "OS/2 Boot Manager or OPUS"}
1745b81b6b3SRodney W. Grimes 	,{0x10, "OPUS"}
1755b81b6b3SRodney W. Grimes 	,{0x40, "VENIX 286"}
1765b81b6b3SRodney W. Grimes 	,{0x50, "DM"}
1775b81b6b3SRodney W. Grimes 	,{0x51, "DM"}
1785b81b6b3SRodney W. Grimes 	,{0x52, "CP/M or Microport SysV/AT"}
1795b81b6b3SRodney W. Grimes 	,{0x56, "GB"}
1805b81b6b3SRodney W. Grimes 	,{0x61, "Speed"}
1815b81b6b3SRodney W. Grimes 	,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
1825b81b6b3SRodney W. Grimes 	,{0x64, "Novell Netware 2.xx"}
1835b81b6b3SRodney W. Grimes 	,{0x65, "Novell Netware 3.xx"}
1845b81b6b3SRodney W. Grimes 	,{0x75, "PCIX"}
1855b81b6b3SRodney W. Grimes 	,{0x80, "Minix 1.1 ... 1.4a"}
1865b81b6b3SRodney W. Grimes 	,{0x81, "Minix 1.4b ... 1.5.10"}
18749f7c177SJordan K. Hubbard 	,{0x82, "Linux swap"}
18849f7c177SJordan K. Hubbard 	,{0x83, "Linux filesystem"}
1895b81b6b3SRodney W. Grimes 	,{0x93, "Amoeba filesystem"}
1905b81b6b3SRodney W. Grimes 	,{0x94, "Amoeba bad block table"}
19149f7c177SJordan K. Hubbard 	,{0xA5, "FreeBSD/NetBSD/386BSD"}
1925f0c9424SGary Palmer 	,{0xA7, "NEXTSTEP"}
1935b81b6b3SRodney W. Grimes 	,{0xB7, "BSDI BSD/386 filesystem"}
1945b81b6b3SRodney W. Grimes 	,{0xB8, "BSDI BSD/386 swap"}
1955b81b6b3SRodney W. Grimes 	,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
1965b81b6b3SRodney W. Grimes 	,{0xE1, "Speed"}
1975b81b6b3SRodney W. Grimes 	,{0xE3, "Speed"}
1985b81b6b3SRodney W. Grimes 	,{0xE4, "Speed"}
1995b81b6b3SRodney W. Grimes 	,{0xF1, "Speed"}
2005b81b6b3SRodney W. Grimes 	,{0xF2, "DOS 3.3+ Secondary"}
2015b81b6b3SRodney W. Grimes 	,{0xF4, "Speed"}
2025b81b6b3SRodney W. Grimes 	,{0xFF, "BBT (Bad Blocks Table)"}
2035b81b6b3SRodney W. Grimes };
2045b81b6b3SRodney W. Grimes 
2054be1e61bSAlexander Langer static void print_s0(int which);
2064be1e61bSAlexander Langer static void print_part(int i);
2074be1e61bSAlexander Langer static void init_sector0(unsigned long start);
208f46af505SJordan K. Hubbard static void init_boot(void);
2094be1e61bSAlexander Langer static void change_part(int i);
2104be1e61bSAlexander Langer static void print_params();
2114be1e61bSAlexander Langer static void change_active(int which);
2124be1e61bSAlexander Langer static void get_params_to_use();
213e2975440SBruce Evans static void dos(int sec, int size, unsigned char *c, unsigned char *s,
214e2975440SBruce Evans 		unsigned char *h);
2154be1e61bSAlexander Langer static int open_disk(int u_flag);
2164be1e61bSAlexander Langer static ssize_t read_disk(off_t sector, void *buf);
2174be1e61bSAlexander Langer static ssize_t write_disk(off_t sector, void *buf);
2184be1e61bSAlexander Langer static int get_params();
2194be1e61bSAlexander Langer static int read_s0();
2204be1e61bSAlexander Langer static int write_s0();
2214be1e61bSAlexander Langer static int ok(char *str);
2224be1e61bSAlexander Langer static int decimal(char *str, int *num, int deflt);
2234be1e61bSAlexander Langer static char *get_type(int type);
224f46af505SJordan K. Hubbard static int read_config(char *config_file);
225f46af505SJordan K. Hubbard static void reset_boot(void);
2264be1e61bSAlexander Langer #if 0
2274be1e61bSAlexander Langer static int hex(char *str, int *num, int deflt);
2284be1e61bSAlexander Langer static int string(char *str, char **ans);
2294be1e61bSAlexander Langer #endif
2305b81b6b3SRodney W. Grimes 
2314be1e61bSAlexander Langer 
2324be1e61bSAlexander Langer int
2334be1e61bSAlexander Langer main(int argc, char *argv[])
2345b81b6b3SRodney W. Grimes {
2355b81b6b3SRodney W. Grimes 	int	i;
2365b81b6b3SRodney W. Grimes 
2375b81b6b3SRodney W. Grimes 	name = *argv;
2385b81b6b3SRodney W. Grimes 	{register char *cp = name;
2395b81b6b3SRodney W. Grimes 		while (*cp) if (*cp++ == '/') name = cp;
2405b81b6b3SRodney W. Grimes 	}
2415b81b6b3SRodney W. Grimes 
2425b81b6b3SRodney W. Grimes 	for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
2435b81b6b3SRodney W. Grimes 		if (*token++ != '-' || !*token)
2445b81b6b3SRodney W. Grimes 			break;
2455b81b6b3SRodney W. Grimes 		else { register int flag;
2464be1e61bSAlexander Langer 			for ( ; (flag = *token++) ; ) {
2475b81b6b3SRodney W. Grimes 				switch (flag) {
2485b81b6b3SRodney W. Grimes 				case '0':
2495b81b6b3SRodney W. Grimes 					partition = 0;
2505b81b6b3SRodney W. Grimes 					break;
2515b81b6b3SRodney W. Grimes 				case '1':
2525b81b6b3SRodney W. Grimes 					partition = 1;
2535b81b6b3SRodney W. Grimes 					break;
2545b81b6b3SRodney W. Grimes 				case '2':
2555b81b6b3SRodney W. Grimes 					partition = 2;
2565b81b6b3SRodney W. Grimes 					break;
2575b81b6b3SRodney W. Grimes 				case '3':
2585b81b6b3SRodney W. Grimes 					partition = 3;
2595b81b6b3SRodney W. Grimes 					break;
2605b81b6b3SRodney W. Grimes 				case 'a':
2615b81b6b3SRodney W. Grimes 					a_flag = 1;
2625b81b6b3SRodney W. Grimes 					break;
263f46af505SJordan K. Hubbard 				case 'f':
264f46af505SJordan K. Hubbard 					if (*token)
265f46af505SJordan K. Hubbard 					{
266f46af505SJordan K. Hubbard 					    f_flag = token;
267f46af505SJordan K. Hubbard 					    token = "";
268f46af505SJordan K. Hubbard 					}
269f46af505SJordan K. Hubbard 					else
270f46af505SJordan K. Hubbard 					{
271f46af505SJordan K. Hubbard 					    if (argc == 1)
272f46af505SJordan K. Hubbard 					    {
273f46af505SJordan K. Hubbard 						goto usage;
274f46af505SJordan K. Hubbard 					    }
275f46af505SJordan K. Hubbard 					    --argc;
276f46af505SJordan K. Hubbard 					    f_flag = *++argv;
277f46af505SJordan K. Hubbard 					}
278f46af505SJordan K. Hubbard 					/*
279f46af505SJordan K. Hubbard 					 * u_flag is needed, because we're
280f46af505SJordan K. Hubbard 					 * writing to the disk.
281f46af505SJordan K. Hubbard 					 */
282f46af505SJordan K. Hubbard 					u_flag = 1;
283f46af505SJordan K. Hubbard 					break;
2845b81b6b3SRodney W. Grimes 				case 'i':
2855b81b6b3SRodney W. Grimes 					i_flag = 1;
2865b81b6b3SRodney W. Grimes 				case 'u':
2875b81b6b3SRodney W. Grimes 					u_flag = 1;
2885b81b6b3SRodney W. Grimes 					break;
289f46af505SJordan K. Hubbard 				case 't':
290f46af505SJordan K. Hubbard 					t_flag = 1;
291f46af505SJordan K. Hubbard 				case 'v':
292f46af505SJordan K. Hubbard 					v_flag = 1;
293f46af505SJordan K. Hubbard 					break;
2945b81b6b3SRodney W. Grimes 				default:
2955b81b6b3SRodney W. Grimes 					goto usage;
2965b81b6b3SRodney W. Grimes 				}
2975b81b6b3SRodney W. Grimes 			}
2985b81b6b3SRodney W. Grimes 		}
2995b81b6b3SRodney W. Grimes 	}
3005b81b6b3SRodney W. Grimes 
3015b81b6b3SRodney W. Grimes 	if (argc > 0)
302e3038c6eSJoerg Wunsch 	{
303e3038c6eSJoerg Wunsch 		static char realname[12];
304e3038c6eSJoerg Wunsch 
305e3038c6eSJoerg Wunsch 		if(strncmp(argv[0], "/dev", 4) == 0)
3065b81b6b3SRodney W. Grimes 			disk = argv[0];
307e3038c6eSJoerg Wunsch 		else
308e3038c6eSJoerg Wunsch 		{
309e3038c6eSJoerg Wunsch 			snprintf(realname, 12, "/dev/r%s", argv[0]);
310e3038c6eSJoerg Wunsch 			disk = realname;
311e3038c6eSJoerg Wunsch 		}
3125b81b6b3SRodney W. Grimes 
3135b81b6b3SRodney W. Grimes 		if (open_disk(u_flag) < 0)
314e3038c6eSJoerg Wunsch 		{
315e3038c6eSJoerg Wunsch 			fprintf(stderr, "Cannot open disk %s (%s)\n",
316e3038c6eSJoerg Wunsch 				disk, sys_errlist[errno]);
3175b81b6b3SRodney W. Grimes 			exit(1);
318e3038c6eSJoerg Wunsch 		}
319e3038c6eSJoerg Wunsch 	}
320e3038c6eSJoerg Wunsch 	else
321e3038c6eSJoerg Wunsch 	{
3224be1e61bSAlexander Langer 		int i, rv = 0;
323e3038c6eSJoerg Wunsch 
324e3038c6eSJoerg Wunsch 		for(i = 0; disks[i]; i++)
325e3038c6eSJoerg Wunsch 		{
326e3038c6eSJoerg Wunsch 			disk = disks[i];
327e3038c6eSJoerg Wunsch 			rv = open_disk(u_flag);
328e3038c6eSJoerg Wunsch 			if(rv != -2) break;
329e3038c6eSJoerg Wunsch 		}
330e3038c6eSJoerg Wunsch 		if(rv < 0)
331e3038c6eSJoerg Wunsch 		{
332e3038c6eSJoerg Wunsch 			fprintf(stderr, "Cannot open any disk (%s)\n",
333e3038c6eSJoerg Wunsch 				sys_errlist[errno]);
334e3038c6eSJoerg Wunsch 			exit(1);
335e3038c6eSJoerg Wunsch 		}
336e3038c6eSJoerg Wunsch 	}
3375b81b6b3SRodney W. Grimes 
3385b81b6b3SRodney W. Grimes 	printf("******* Working on device %s *******\n",disk);
339f46af505SJordan K. Hubbard 
340f46af505SJordan K. Hubbard 	if (f_flag)
341f46af505SJordan K. Hubbard 	{
342f46af505SJordan K. Hubbard 	    if (read_s0() || i_flag)
343f46af505SJordan K. Hubbard 	    {
344f46af505SJordan K. Hubbard 		reset_boot();
345f46af505SJordan K. Hubbard 	    }
346f46af505SJordan K. Hubbard 
347f46af505SJordan K. Hubbard 	    if (!read_config(f_flag))
348f46af505SJordan K. Hubbard 	    {
349f46af505SJordan K. Hubbard 		exit(1);
350f46af505SJordan K. Hubbard 	    }
351f46af505SJordan K. Hubbard 	    if (v_flag)
352f46af505SJordan K. Hubbard 	    {
353f46af505SJordan K. Hubbard 		print_s0(-1);
354f46af505SJordan K. Hubbard 	    }
355f46af505SJordan K. Hubbard 	    if (!t_flag)
356f46af505SJordan K. Hubbard 	    {
357f46af505SJordan K. Hubbard 		write_s0();
358f46af505SJordan K. Hubbard 	    }
359f46af505SJordan K. Hubbard 	}
360f46af505SJordan K. Hubbard 	else
361f46af505SJordan K. Hubbard 	{
3625b81b6b3SRodney W. Grimes 	    if(u_flag)
3635b81b6b3SRodney W. Grimes 	    {
3645b81b6b3SRodney W. Grimes 		get_params_to_use();
3655b81b6b3SRodney W. Grimes 	    }
3665b81b6b3SRodney W. Grimes 	    else
3675b81b6b3SRodney W. Grimes 	    {
3685b81b6b3SRodney W. Grimes 		print_params();
3695b81b6b3SRodney W. Grimes 	    }
3705b81b6b3SRodney W. Grimes 
3715b81b6b3SRodney W. Grimes 	    if (read_s0())
3725b81b6b3SRodney W. Grimes 		init_sector0(1);
3735b81b6b3SRodney W. Grimes 
3747cb29d33SSøren Schmidt 	    printf("Media sector size is %d\n", secsize);
3755b81b6b3SRodney W. Grimes 	    printf("Warning: BIOS sector numbering starts with sector 1\n");
3765b81b6b3SRodney W. Grimes 	    printf("Information from DOS bootblock is:\n");
3775b81b6b3SRodney W. Grimes 	    if (partition == -1)
3785b81b6b3SRodney W. Grimes 		for (i = 0; i < NDOSPART; i++)
3795b81b6b3SRodney W. Grimes 		    change_part(i);
3805b81b6b3SRodney W. Grimes 	    else
3815b81b6b3SRodney W. Grimes 		change_part(partition);
3825b81b6b3SRodney W. Grimes 
3835b81b6b3SRodney W. Grimes 	    if (u_flag || a_flag)
3845b81b6b3SRodney W. Grimes 		change_active(partition);
3855b81b6b3SRodney W. Grimes 
3865b81b6b3SRodney W. Grimes 	    if (u_flag || a_flag) {
387f46af505SJordan K. Hubbard 		if (!t_flag)
388f46af505SJordan K. Hubbard 		{
3895b81b6b3SRodney W. Grimes 		    printf("\nWe haven't changed the partition table yet.  ");
3905b81b6b3SRodney W. Grimes 		    printf("This is your last chance.\n");
391f46af505SJordan K. Hubbard 		}
3925b81b6b3SRodney W. Grimes 		print_s0(-1);
393f46af505SJordan K. Hubbard 		if (!t_flag)
394f46af505SJordan K. Hubbard 		{
3955b81b6b3SRodney W. Grimes 		    if (ok("Should we write new partition table?"))
3965b81b6b3SRodney W. Grimes 			write_s0();
3975b81b6b3SRodney W. Grimes 		}
398f46af505SJordan K. Hubbard 		else
399f46af505SJordan K. Hubbard 		{
400f46af505SJordan K. Hubbard 		    printf("\n-t flag specified -- partition table not written.\n");
401f46af505SJordan K. Hubbard 		}
402f46af505SJordan K. Hubbard 	    }
403f46af505SJordan K. Hubbard 	}
4045b81b6b3SRodney W. Grimes 
4055b81b6b3SRodney W. Grimes 	exit(0);
4065b81b6b3SRodney W. Grimes 
4075b81b6b3SRodney W. Grimes usage:
408f46af505SJordan K. Hubbard 	printf("fdisk {-a|-i|-u} [-f <config file> [-t] [-v]] [-{0,1,2,3}] [disk]\n");
4094be1e61bSAlexander Langer 	return(1);
4105b81b6b3SRodney W. Grimes }
4115b81b6b3SRodney W. Grimes 
4124be1e61bSAlexander Langer static void
4134be1e61bSAlexander Langer print_s0(int which)
4145b81b6b3SRodney W. Grimes {
4155b81b6b3SRodney W. Grimes int	i;
4165b81b6b3SRodney W. Grimes 
4175b81b6b3SRodney W. Grimes 	print_params();
4185b81b6b3SRodney W. Grimes 	printf("Information from DOS bootblock is:\n");
4195b81b6b3SRodney W. Grimes 	if (which == -1)
4205b81b6b3SRodney W. Grimes 		for (i = 0; i < NDOSPART; i++)
4215b81b6b3SRodney W. Grimes 			printf("%d: ", i), print_part(i);
4225b81b6b3SRodney W. Grimes 	else
4235b81b6b3SRodney W. Grimes 		print_part(which);
4245b81b6b3SRodney W. Grimes }
4255b81b6b3SRodney W. Grimes 
4265b81b6b3SRodney W. Grimes static struct dos_partition mtpart = { 0 };
4275b81b6b3SRodney W. Grimes 
4284be1e61bSAlexander Langer static void
4294be1e61bSAlexander Langer print_part(int i)
4305b81b6b3SRodney W. Grimes {
4315b81b6b3SRodney W. Grimes struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
4325b81b6b3SRodney W. Grimes 
4335b81b6b3SRodney W. Grimes 
4345b81b6b3SRodney W. Grimes 	if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
4355b81b6b3SRodney W. Grimes 		printf("<UNUSED>\n");
4365b81b6b3SRodney W. Grimes 		return;
4375b81b6b3SRodney W. Grimes 	}
4385b81b6b3SRodney W. Grimes 	printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
4394be1e61bSAlexander Langer 	printf("    start %ld, size %ld (%ld Meg), flag %x\n",
4405b81b6b3SRodney W. Grimes 		partp->dp_start,
4417cb29d33SSøren Schmidt 		partp->dp_size, partp->dp_size * secsize / (1024 * 1024),
4425b81b6b3SRodney W. Grimes 		partp->dp_flag);
4435b81b6b3SRodney W. Grimes 	printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
4445b81b6b3SRodney W. Grimes 		,DPCYL(partp->dp_scyl, partp->dp_ssect)
4455b81b6b3SRodney W. Grimes 		,DPSECT(partp->dp_ssect)
4465b81b6b3SRodney W. Grimes 		,partp->dp_shd
4475b81b6b3SRodney W. Grimes 		,DPCYL(partp->dp_ecyl, partp->dp_esect)
4485b81b6b3SRodney W. Grimes 		,DPSECT(partp->dp_esect)
4495b81b6b3SRodney W. Grimes 		,partp->dp_ehd);
4505b81b6b3SRodney W. Grimes }
4515b81b6b3SRodney W. Grimes 
452f46af505SJordan K. Hubbard 
453f46af505SJordan K. Hubbard static void
454f46af505SJordan K. Hubbard init_boot(void)
455f46af505SJordan K. Hubbard {
456f46af505SJordan K. Hubbard 	memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
457f46af505SJordan K. Hubbard 	mboot.signature = BOOT_MAGIC;
458f46af505SJordan K. Hubbard }
459f46af505SJordan K. Hubbard 
460f46af505SJordan K. Hubbard 
4614be1e61bSAlexander Langer static void
4624be1e61bSAlexander Langer init_sector0(unsigned long start)
4635b81b6b3SRodney W. Grimes {
4645b81b6b3SRodney W. Grimes struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
4654be1e61bSAlexander Langer unsigned long size = disksecs - start;
4665b81b6b3SRodney W. Grimes 
467f46af505SJordan K. Hubbard 	init_boot();
4685b81b6b3SRodney W. Grimes 
4695b81b6b3SRodney W. Grimes 	partp->dp_typ = DOSPTYP_386BSD;
4705b81b6b3SRodney W. Grimes 	partp->dp_flag = ACTIVE;
4715b81b6b3SRodney W. Grimes 	partp->dp_start = start;
4725b81b6b3SRodney W. Grimes 	partp->dp_size = size;
4735b81b6b3SRodney W. Grimes 
474e2975440SBruce Evans 	dos(partp->dp_start, partp->dp_size,
475e2975440SBruce Evans 	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
476e2975440SBruce Evans 	dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
477e2975440SBruce Evans 	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
4785b81b6b3SRodney W. Grimes }
4795b81b6b3SRodney W. Grimes 
4804be1e61bSAlexander Langer static void
4814be1e61bSAlexander Langer change_part(int i)
4825b81b6b3SRodney W. Grimes {
4835b81b6b3SRodney W. Grimes struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
4845b81b6b3SRodney W. Grimes 
4855b81b6b3SRodney W. Grimes     printf("The data for partition %d is:\n", i);
4865b81b6b3SRodney W. Grimes     print_part(i);
4875b81b6b3SRodney W. Grimes 
4885b81b6b3SRodney W. Grimes     if (u_flag && ok("Do you want to change it?")) {
4895b81b6b3SRodney W. Grimes 	int tmp;
4905b81b6b3SRodney W. Grimes 
4915b81b6b3SRodney W. Grimes 	if (i_flag) {
4925b81b6b3SRodney W. Grimes 		bzero((char *)partp, sizeof (struct dos_partition));
4935b81b6b3SRodney W. Grimes 		if (i == 3) {
4945b81b6b3SRodney W. Grimes 			init_sector0(1);
4955b81b6b3SRodney W. Grimes 			printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
4965b81b6b3SRodney W. Grimes 			print_part(i);
4975b81b6b3SRodney W. Grimes 		}
4985b81b6b3SRodney W. Grimes 	}
4995b81b6b3SRodney W. Grimes 
5005b81b6b3SRodney W. Grimes 	do {
5015b81b6b3SRodney W. Grimes 		Decimal("sysid", partp->dp_typ, tmp);
5025b81b6b3SRodney W. Grimes 		Decimal("start", partp->dp_start, tmp);
5035b81b6b3SRodney W. Grimes 		Decimal("size", partp->dp_size, tmp);
5045b81b6b3SRodney W. Grimes 
5055b81b6b3SRodney W. Grimes 		if (ok("Explicitly specifiy beg/end address ?"))
5065b81b6b3SRodney W. Grimes 		{
5075b81b6b3SRodney W. Grimes 			int	tsec,tcyl,thd;
5085b81b6b3SRodney W. Grimes 			tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
5095b81b6b3SRodney W. Grimes 			thd = partp->dp_shd;
5105b81b6b3SRodney W. Grimes 			tsec = DPSECT(partp->dp_ssect);
5115b81b6b3SRodney W. Grimes 			Decimal("beginning cylinder", tcyl, tmp);
5125b81b6b3SRodney W. Grimes 			Decimal("beginning head", thd, tmp);
5135b81b6b3SRodney W. Grimes 			Decimal("beginning sector", tsec, tmp);
5145b81b6b3SRodney W. Grimes 			partp->dp_scyl = DOSCYL(tcyl);
5155b81b6b3SRodney W. Grimes 			partp->dp_ssect = DOSSECT(tsec,tcyl);
5165b81b6b3SRodney W. Grimes 			partp->dp_shd = thd;
5175b81b6b3SRodney W. Grimes 
5185b81b6b3SRodney W. Grimes 			tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
5195b81b6b3SRodney W. Grimes 			thd = partp->dp_ehd;
5205b81b6b3SRodney W. Grimes 			tsec = DPSECT(partp->dp_esect);
5215b81b6b3SRodney W. Grimes 			Decimal("ending cylinder", tcyl, tmp);
5225b81b6b3SRodney W. Grimes 			Decimal("ending head", thd, tmp);
5235b81b6b3SRodney W. Grimes 			Decimal("ending sector", tsec, tmp);
5245b81b6b3SRodney W. Grimes 			partp->dp_ecyl = DOSCYL(tcyl);
5255b81b6b3SRodney W. Grimes 			partp->dp_esect = DOSSECT(tsec,tcyl);
5265b81b6b3SRodney W. Grimes 			partp->dp_ehd = thd;
5275b81b6b3SRodney W. Grimes 		} else {
528e2975440SBruce Evans 			dos(partp->dp_start, partp->dp_size,
5295b81b6b3SRodney W. Grimes 			    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
530e2975440SBruce Evans 			dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
5315b81b6b3SRodney W. Grimes 			    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
5325b81b6b3SRodney W. Grimes 		}
5335b81b6b3SRodney W. Grimes 
5345b81b6b3SRodney W. Grimes 		print_part(i);
5355b81b6b3SRodney W. Grimes 	} while (!ok("Are we happy with this entry?"));
5365b81b6b3SRodney W. Grimes     }
5375b81b6b3SRodney W. Grimes }
5385b81b6b3SRodney W. Grimes 
5394be1e61bSAlexander Langer static void
5405b81b6b3SRodney W. Grimes print_params()
5415b81b6b3SRodney W. Grimes {
5425b81b6b3SRodney W. Grimes 	printf("parameters extracted from in-core disklabel are:\n");
5435b81b6b3SRodney W. Grimes 	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
5445b81b6b3SRodney W. Grimes 			,cyls,heads,sectors,cylsecs);
5455b81b6b3SRodney W. Grimes 	if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
5465b81b6b3SRodney W. Grimes 		printf("Figures below won't work with BIOS for partitions not in cyl 1\n");
5475b81b6b3SRodney W. Grimes 	printf("parameters to be used for BIOS calculations are:\n");
5485b81b6b3SRodney W. Grimes 	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
5495b81b6b3SRodney W. Grimes 		,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
5505b81b6b3SRodney W. Grimes }
5515b81b6b3SRodney W. Grimes 
5524be1e61bSAlexander Langer static void
5534be1e61bSAlexander Langer change_active(int which)
5545b81b6b3SRodney W. Grimes {
5555b81b6b3SRodney W. Grimes int i;
5565b81b6b3SRodney W. Grimes int active = 3, tmp;
5575b81b6b3SRodney W. Grimes struct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
5585b81b6b3SRodney W. Grimes 
5595b81b6b3SRodney W. Grimes 	if (a_flag && which != -1)
5605b81b6b3SRodney W. Grimes 		active = which;
5610b461cd7SBruce Evans 	if (!ok("Do you want to change the active partition?"))
5620b461cd7SBruce Evans 		return;
5635b81b6b3SRodney W. Grimes 	do
5645b81b6b3SRodney W. Grimes 		Decimal("active partition", active, tmp);
5655b81b6b3SRodney W. Grimes 	while (!ok("Are you happy with this choice"));
5665b81b6b3SRodney W. Grimes 	for (i = 0; i < NDOSPART; i++)
5675b81b6b3SRodney W. Grimes 		partp[i].dp_flag = 0;
568c48cef7dSBruce Evans 	if (active >= 0 && active < NDOSPART)
5695b81b6b3SRodney W. Grimes 		partp[active].dp_flag = ACTIVE;
5705b81b6b3SRodney W. Grimes }
5715b81b6b3SRodney W. Grimes 
5724be1e61bSAlexander Langer void
5735b81b6b3SRodney W. Grimes get_params_to_use()
5745b81b6b3SRodney W. Grimes {
5755b81b6b3SRodney W. Grimes 	int	tmp;
5765b81b6b3SRodney W. Grimes 	print_params();
5775b81b6b3SRodney W. Grimes 	if (ok("Do you want to change our idea of what BIOS thinks ?"))
5785b81b6b3SRodney W. Grimes 	{
5795b81b6b3SRodney W. Grimes 		do
5805b81b6b3SRodney W. Grimes 		{
5815b81b6b3SRodney W. Grimes 			Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
5825b81b6b3SRodney W. Grimes 			Decimal("BIOS's idea of #heads", dos_heads, tmp);
5835b81b6b3SRodney W. Grimes 			Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
5845b81b6b3SRodney W. Grimes 			dos_cylsecs = dos_heads * dos_sectors;
5855b81b6b3SRodney W. Grimes 			print_params();
5865b81b6b3SRodney W. Grimes 		}
5875b81b6b3SRodney W. Grimes 		while(!ok("Are you happy with this choice"));
5885b81b6b3SRodney W. Grimes 	}
5895b81b6b3SRodney W. Grimes }
5905b81b6b3SRodney W. Grimes 
591f46af505SJordan K. Hubbard 
5925b81b6b3SRodney W. Grimes /***********************************************\
5935b81b6b3SRodney W. Grimes * Change real numbers into strange dos numbers	*
5945b81b6b3SRodney W. Grimes \***********************************************/
5954be1e61bSAlexander Langer static void
596e2975440SBruce Evans dos(sec, size, c, s, h)
597e2975440SBruce Evans int sec, size;
5985b81b6b3SRodney W. Grimes unsigned char *c, *s, *h;
5995b81b6b3SRodney W. Grimes {
6005b81b6b3SRodney W. Grimes int cy;
6015b81b6b3SRodney W. Grimes int hd;
6025b81b6b3SRodney W. Grimes 
603e2975440SBruce Evans 	if (sec == 0 && size == 0) {
6040b461cd7SBruce Evans 		*s = *c = *h = 0;
6050b461cd7SBruce Evans 		return;
6060b461cd7SBruce Evans 	}
6070b461cd7SBruce Evans 
6085b81b6b3SRodney W. Grimes 	cy = sec / ( dos_cylsecs );
6095b81b6b3SRodney W. Grimes 	sec = sec - cy * ( dos_cylsecs );
6105b81b6b3SRodney W. Grimes 
6115b81b6b3SRodney W. Grimes 	hd = sec / dos_sectors;
6125b81b6b3SRodney W. Grimes 	sec = (sec - hd * dos_sectors) + 1;
6135b81b6b3SRodney W. Grimes 
6145b81b6b3SRodney W. Grimes 	*h = hd;
6155b81b6b3SRodney W. Grimes 	*c = cy & 0xff;
6165b81b6b3SRodney W. Grimes 	*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
6175b81b6b3SRodney W. Grimes }
6185b81b6b3SRodney W. Grimes 
6195b81b6b3SRodney W. Grimes int fd;
6205b81b6b3SRodney W. Grimes 
6215b81b6b3SRodney W. Grimes 	/* Getting device status */
6225b81b6b3SRodney W. Grimes 
6234be1e61bSAlexander Langer static int
6244be1e61bSAlexander Langer open_disk(int u_flag)
6255b81b6b3SRodney W. Grimes {
6265b81b6b3SRodney W. Grimes struct stat 	st;
6275b81b6b3SRodney W. Grimes 
6285b81b6b3SRodney W. Grimes 	if (stat(disk, &st) == -1) {
6295b81b6b3SRodney W. Grimes 		fprintf(stderr, "%s: Can't get file status of %s\n",
6305b81b6b3SRodney W. Grimes 			name, disk);
6315b81b6b3SRodney W. Grimes 		return -1;
632b60eb395SBruce Evans 	}
633b60eb395SBruce Evans 	if ( !(st.st_mode & S_IFCHR) )
6345b81b6b3SRodney W. Grimes 		fprintf(stderr,"%s: Device %s is not character special\n",
6355b81b6b3SRodney W. Grimes 			name, disk);
6360b461cd7SBruce Evans 	if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) {
637e3038c6eSJoerg Wunsch 		if(errno == ENXIO)
638e3038c6eSJoerg Wunsch 			return -2;
6395b81b6b3SRodney W. Grimes 		fprintf(stderr,"%s: Can't open device %s\n", name, disk);
6405b81b6b3SRodney W. Grimes 		return -1;
6415b81b6b3SRodney W. Grimes 	}
6425b81b6b3SRodney W. Grimes 	if (get_params(0) == -1) {
6435b81b6b3SRodney W. Grimes 		fprintf(stderr, "%s: Can't get disk parameters on %s\n",
6445b81b6b3SRodney W. Grimes 			name, disk);
6455b81b6b3SRodney W. Grimes 		return -1;
6465b81b6b3SRodney W. Grimes 	}
6475b81b6b3SRodney W. Grimes 	return fd;
6485b81b6b3SRodney W. Grimes }
6495b81b6b3SRodney W. Grimes 
6504be1e61bSAlexander Langer static ssize_t
6514be1e61bSAlexander Langer read_disk(off_t sector, void *buf)
6525b81b6b3SRodney W. Grimes {
6535b81b6b3SRodney W. Grimes 	lseek(fd,(sector * 512), 0);
6547cb29d33SSøren Schmidt 	if( secsize == 0 )
6557cb29d33SSøren Schmidt 		for( secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; secsize *= 2 )
6567cb29d33SSøren Schmidt 			{
6577cb29d33SSøren Schmidt 			/* try the read */
6587cb29d33SSøren Schmidt 			int size = read(fd, buf, secsize);
6597cb29d33SSøren Schmidt 			if( size == secsize )
6607cb29d33SSøren Schmidt 				/* it worked so return */
6617cb29d33SSøren Schmidt 				return secsize;
6627cb29d33SSøren Schmidt 			}
6637cb29d33SSøren Schmidt 	else
6647cb29d33SSøren Schmidt 		return read( fd, buf, secsize );
6657cb29d33SSøren Schmidt 
6667cb29d33SSøren Schmidt 	/* we failed to read at any of the sizes */
6677cb29d33SSøren Schmidt 	return -1;
6685b81b6b3SRodney W. Grimes }
6695b81b6b3SRodney W. Grimes 
6704be1e61bSAlexander Langer static ssize_t
6714be1e61bSAlexander Langer write_disk(off_t sector, void *buf)
6725b81b6b3SRodney W. Grimes {
6735b81b6b3SRodney W. Grimes 	lseek(fd,(sector * 512), 0);
6747cb29d33SSøren Schmidt 	/* write out in the size that the read_disk found worked */
6757cb29d33SSøren Schmidt 	return write(fd, buf, secsize);
6765b81b6b3SRodney W. Grimes }
6775b81b6b3SRodney W. Grimes 
6784be1e61bSAlexander Langer static int
6794be1e61bSAlexander Langer get_params()
6805b81b6b3SRodney W. Grimes {
6815b81b6b3SRodney W. Grimes 
6825b81b6b3SRodney W. Grimes     if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
683b60eb395SBruce Evans 	fprintf(stderr,
684b60eb395SBruce Evans 		"%s: Can't get disk parameters on %s; supplying dummy ones\n",
685b60eb395SBruce Evans 		name, disk);
686b60eb395SBruce Evans 	dos_cyls = cyls = 1;
687b60eb395SBruce Evans 	dos_heads = heads = 1;
688b60eb395SBruce Evans 	dos_sectors = sectors = 1;
689b60eb395SBruce Evans 	dos_cylsecs = cylsecs = heads * sectors;
690b60eb395SBruce Evans 	disksecs = cyls * heads * sectors;
691b60eb395SBruce Evans 	return disksecs;
6925b81b6b3SRodney W. Grimes     }
6935b81b6b3SRodney W. Grimes 
6945b81b6b3SRodney W. Grimes     dos_cyls = cyls = disklabel.d_ncylinders;
6955b81b6b3SRodney W. Grimes     dos_heads = heads = disklabel.d_ntracks;
6965b81b6b3SRodney W. Grimes     dos_sectors = sectors = disklabel.d_nsectors;
6975b81b6b3SRodney W. Grimes     dos_cylsecs = cylsecs = heads * sectors;
6985b81b6b3SRodney W. Grimes     disksecs = cyls * heads * sectors;
6995b81b6b3SRodney W. Grimes 
7005b81b6b3SRodney W. Grimes     return (disksecs);
7015b81b6b3SRodney W. Grimes }
7025b81b6b3SRodney W. Grimes 
7035b81b6b3SRodney W. Grimes 
7044be1e61bSAlexander Langer static int
7055b81b6b3SRodney W. Grimes read_s0()
7065b81b6b3SRodney W. Grimes {
7075b81b6b3SRodney W. Grimes 	if (read_disk(0, (char *) mboot.bootinst) == -1) {
7085b81b6b3SRodney W. Grimes 		fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
7095b81b6b3SRodney W. Grimes 		return -1;
7105b81b6b3SRodney W. Grimes 	}
7115b81b6b3SRodney W. Grimes 	if (mboot.signature != BOOT_MAGIC) {
7125b81b6b3SRodney W. Grimes 		fprintf(stderr, "%s: Invalid fdisk partition table found\n",
7135b81b6b3SRodney W. Grimes 			name);
7145b81b6b3SRodney W. Grimes 		/* So should we initialize things */
7155b81b6b3SRodney W. Grimes 		return -1;
7165b81b6b3SRodney W. Grimes 	}
7175b81b6b3SRodney W. Grimes 	return 0;
7185b81b6b3SRodney W. Grimes }
7195b81b6b3SRodney W. Grimes 
7204be1e61bSAlexander Langer static int
7215b81b6b3SRodney W. Grimes write_s0()
7225b81b6b3SRodney W. Grimes {
7235b81b6b3SRodney W. Grimes 	int	flag;
7245b81b6b3SRodney W. Grimes 	if (iotest) {
7255b81b6b3SRodney W. Grimes 		print_s0(-1);
7265b81b6b3SRodney W. Grimes 		return 0;
7275b81b6b3SRodney W. Grimes 	}
7285b81b6b3SRodney W. Grimes 	/*
7295b81b6b3SRodney W. Grimes 	 * write enable label sector before write (if necessary),
7305b81b6b3SRodney W. Grimes 	 * disable after writing.
7315b81b6b3SRodney W. Grimes 	 * needed if the disklabel protected area also protects
7325b81b6b3SRodney W. Grimes 	 * sector 0. (e.g. empty disk)
7335b81b6b3SRodney W. Grimes 	 */
7345b81b6b3SRodney W. Grimes 	flag = 1;
735ba3551dfSJulian Elischer #ifdef NOT_NOW
7365b81b6b3SRodney W. Grimes 	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
7375b81b6b3SRodney W. Grimes 		perror("ioctl DIOCWLABEL");
738ba3551dfSJulian Elischer #endif
7395b81b6b3SRodney W. Grimes 	if (write_disk(0, (char *) mboot.bootinst) == -1) {
7405b81b6b3SRodney W. Grimes 		fprintf(stderr, "%s: Can't write fdisk partition table\n",
7415b81b6b3SRodney W. Grimes 			name);
7425b81b6b3SRodney W. Grimes 		return -1;
7435b81b6b3SRodney W. Grimes 	flag = 0;
744ba3551dfSJulian Elischer #ifdef NOT_NOW
7455b81b6b3SRodney W. Grimes 	(void) ioctl(fd, DIOCWLABEL, &flag);
746ba3551dfSJulian Elischer #endif
7475b81b6b3SRodney W. Grimes 	}
7484be1e61bSAlexander Langer 	return(0);
7495b81b6b3SRodney W. Grimes }
7505b81b6b3SRodney W. Grimes 
7515b81b6b3SRodney W. Grimes 
7524be1e61bSAlexander Langer static int
7535b81b6b3SRodney W. Grimes ok(str)
7545b81b6b3SRodney W. Grimes char *str;
7555b81b6b3SRodney W. Grimes {
7565b81b6b3SRodney W. Grimes 	printf("%s [n] ", str);
7575b81b6b3SRodney W. Grimes 	fgets(lbuf, LBUF, stdin);
7585b81b6b3SRodney W. Grimes 	lbuf[strlen(lbuf)-1] = 0;
7595b81b6b3SRodney W. Grimes 
7605b81b6b3SRodney W. Grimes 	if (*lbuf &&
7615b81b6b3SRodney W. Grimes 		(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
7625b81b6b3SRodney W. Grimes 		 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
7635b81b6b3SRodney W. Grimes 		return 1;
7645b81b6b3SRodney W. Grimes 	else
7655b81b6b3SRodney W. Grimes 		return 0;
7665b81b6b3SRodney W. Grimes }
7675b81b6b3SRodney W. Grimes 
7684be1e61bSAlexander Langer static int
7694be1e61bSAlexander Langer decimal(char *str, int *num, int deflt)
7705b81b6b3SRodney W. Grimes {
7715b81b6b3SRodney W. Grimes int acc = 0, c;
7725b81b6b3SRodney W. Grimes char *cp;
7735b81b6b3SRodney W. Grimes 
7745b81b6b3SRodney W. Grimes 	while (1) {
7755b81b6b3SRodney W. Grimes 		printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
7765b81b6b3SRodney W. Grimes 		fgets(lbuf, LBUF, stdin);
7775b81b6b3SRodney W. Grimes 		lbuf[strlen(lbuf)-1] = 0;
7785b81b6b3SRodney W. Grimes 
7795b81b6b3SRodney W. Grimes 		if (!*lbuf)
7805b81b6b3SRodney W. Grimes 			return 0;
7815b81b6b3SRodney W. Grimes 
7825b81b6b3SRodney W. Grimes 		cp = lbuf;
7835b81b6b3SRodney W. Grimes 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
7845b81b6b3SRodney W. Grimes 		if (!c)
7855b81b6b3SRodney W. Grimes 			return 0;
7864be1e61bSAlexander Langer 		while ((c = *cp++)) {
7875b81b6b3SRodney W. Grimes 			if (c <= '9' && c >= '0')
7885b81b6b3SRodney W. Grimes 				acc = acc * 10 + c - '0';
7895b81b6b3SRodney W. Grimes 			else
7905b81b6b3SRodney W. Grimes 				break;
7915b81b6b3SRodney W. Grimes 		}
7925b81b6b3SRodney W. Grimes 		if (c == ' ' || c == '\t')
7935b81b6b3SRodney W. Grimes 			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
7945b81b6b3SRodney W. Grimes 		if (!c) {
7955b81b6b3SRodney W. Grimes 			*num = acc;
7965b81b6b3SRodney W. Grimes 			return 1;
7975b81b6b3SRodney W. Grimes 		} else
7985b81b6b3SRodney W. Grimes 			printf("%s is an invalid decimal number.  Try again\n",
7995b81b6b3SRodney W. Grimes 				lbuf);
8005b81b6b3SRodney W. Grimes 	}
8015b81b6b3SRodney W. Grimes 
8025b81b6b3SRodney W. Grimes }
8035b81b6b3SRodney W. Grimes 
8044be1e61bSAlexander Langer #if 0
8054be1e61bSAlexander Langer static int
8064be1e61bSAlexander Langer hex(char *str, int *num, int deflt)
8075b81b6b3SRodney W. Grimes {
8085b81b6b3SRodney W. Grimes int acc = 0, c;
8095b81b6b3SRodney W. Grimes char *cp;
8105b81b6b3SRodney W. Grimes 
8115b81b6b3SRodney W. Grimes 	while (1) {
8125b81b6b3SRodney W. Grimes 		printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
8135b81b6b3SRodney W. Grimes 		fgets(lbuf, LBUF, stdin);
8145b81b6b3SRodney W. Grimes 		lbuf[strlen(lbuf)-1] = 0;
8155b81b6b3SRodney W. Grimes 
8165b81b6b3SRodney W. Grimes 		if (!*lbuf)
8175b81b6b3SRodney W. Grimes 			return 0;
8185b81b6b3SRodney W. Grimes 
8195b81b6b3SRodney W. Grimes 		cp = lbuf;
8205b81b6b3SRodney W. Grimes 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8215b81b6b3SRodney W. Grimes 		if (!c)
8225b81b6b3SRodney W. Grimes 			return 0;
8234be1e61bSAlexander Langer 		while ((c = *cp++)) {
8245b81b6b3SRodney W. Grimes 			if (c <= '9' && c >= '0')
8255b81b6b3SRodney W. Grimes 				acc = (acc << 4) + c - '0';
8265b81b6b3SRodney W. Grimes 			else if (c <= 'f' && c >= 'a')
8275b81b6b3SRodney W. Grimes 				acc = (acc << 4) + c - 'a' + 10;
8285b81b6b3SRodney W. Grimes 			else if (c <= 'F' && c >= 'A')
8295b81b6b3SRodney W. Grimes 				acc = (acc << 4) + c - 'A' + 10;
8305b81b6b3SRodney W. Grimes 			else
8315b81b6b3SRodney W. Grimes 				break;
8325b81b6b3SRodney W. Grimes 		}
8335b81b6b3SRodney W. Grimes 		if (c == ' ' || c == '\t')
8345b81b6b3SRodney W. Grimes 			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8355b81b6b3SRodney W. Grimes 		if (!c) {
8365b81b6b3SRodney W. Grimes 			*num = acc;
8375b81b6b3SRodney W. Grimes 			return 1;
8385b81b6b3SRodney W. Grimes 		} else
8395b81b6b3SRodney W. Grimes 			printf("%s is an invalid hex number.  Try again\n",
8405b81b6b3SRodney W. Grimes 				lbuf);
8415b81b6b3SRodney W. Grimes 	}
8425b81b6b3SRodney W. Grimes 
8435b81b6b3SRodney W. Grimes }
8445b81b6b3SRodney W. Grimes 
8454be1e61bSAlexander Langer static int
8464be1e61bSAlexander Langer string(char *str, char **ans)
8475b81b6b3SRodney W. Grimes {
8485b81b6b3SRodney W. Grimes int c;
8495b81b6b3SRodney W. Grimes char *cp = lbuf;
8505b81b6b3SRodney W. Grimes 
8515b81b6b3SRodney W. Grimes 	while (1) {
8525b81b6b3SRodney W. Grimes 		printf("Supply a string value for \"%s\" [%s] ", str, *ans);
8535b81b6b3SRodney W. Grimes 		fgets(lbuf, LBUF, stdin);
8545b81b6b3SRodney W. Grimes 		lbuf[strlen(lbuf)-1] = 0;
8555b81b6b3SRodney W. Grimes 
8565b81b6b3SRodney W. Grimes 		if (!*lbuf)
8575b81b6b3SRodney W. Grimes 			return 0;
8585b81b6b3SRodney W. Grimes 
8595b81b6b3SRodney W. Grimes 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8605b81b6b3SRodney W. Grimes 		if (c == '"') {
8615b81b6b3SRodney W. Grimes 			c = *++cp;
8625b81b6b3SRodney W. Grimes 			*ans = cp;
8635b81b6b3SRodney W. Grimes 			while ((c = *cp) && c != '"') cp++;
8645b81b6b3SRodney W. Grimes 		} else {
8655b81b6b3SRodney W. Grimes 			*ans = cp;
8665b81b6b3SRodney W. Grimes 			while ((c = *cp) && c != ' ' && c != '\t') cp++;
8675b81b6b3SRodney W. Grimes 		}
8685b81b6b3SRodney W. Grimes 
8695b81b6b3SRodney W. Grimes 		if (c)
8705b81b6b3SRodney W. Grimes 			*cp = 0;
8715b81b6b3SRodney W. Grimes 		return 1;
8725b81b6b3SRodney W. Grimes 	}
8735b81b6b3SRodney W. Grimes }
8744be1e61bSAlexander Langer #endif
8755b81b6b3SRodney W. Grimes 
8764be1e61bSAlexander Langer static char *
8774be1e61bSAlexander Langer get_type(int type)
8785b81b6b3SRodney W. Grimes {
8795b81b6b3SRodney W. Grimes 	int	numentries = (sizeof(part_types)/sizeof(struct part_type));
8805b81b6b3SRodney W. Grimes 	int	counter = 0;
8815b81b6b3SRodney W. Grimes 	struct	part_type *ptr = part_types;
8825b81b6b3SRodney W. Grimes 
8835b81b6b3SRodney W. Grimes 
8845b81b6b3SRodney W. Grimes 	while(counter < numentries)
8855b81b6b3SRodney W. Grimes 	{
8865b81b6b3SRodney W. Grimes 		if(ptr->type == type)
8875b81b6b3SRodney W. Grimes 		{
8885b81b6b3SRodney W. Grimes 			return(ptr->name);
8895b81b6b3SRodney W. Grimes 		}
8905b81b6b3SRodney W. Grimes 		ptr++;
8915b81b6b3SRodney W. Grimes 		counter++;
8925b81b6b3SRodney W. Grimes 	}
8935b81b6b3SRodney W. Grimes 	return("unknown");
8945b81b6b3SRodney W. Grimes }
895f46af505SJordan K. Hubbard 
896f46af505SJordan K. Hubbard 
897f46af505SJordan K. Hubbard static void
898f46af505SJordan K. Hubbard parse_config_line(line, command)
899f46af505SJordan K. Hubbard     char	*line;
900f46af505SJordan K. Hubbard     CMD		*command;
901f46af505SJordan K. Hubbard {
902f46af505SJordan K. Hubbard     char	*cp, *end;
903f46af505SJordan K. Hubbard 
904f46af505SJordan K. Hubbard     cp = line;
905f46af505SJordan K. Hubbard     while (1)	/* dirty trick used to insure one exit point for this
906f46af505SJordan K. Hubbard 		   function */
907f46af505SJordan K. Hubbard     {
908f46af505SJordan K. Hubbard 	memset(command, 0, sizeof(*command));
909f46af505SJordan K. Hubbard 
910f46af505SJordan K. Hubbard 	while (isspace(*cp)) ++cp;
911f46af505SJordan K. Hubbard 	if (*cp == '\0' || *cp == '#')
912f46af505SJordan K. Hubbard 	{
913f46af505SJordan K. Hubbard 	    break;
914f46af505SJordan K. Hubbard 	}
915f46af505SJordan K. Hubbard 	command->cmd = *cp++;
916f46af505SJordan K. Hubbard 
917f46af505SJordan K. Hubbard 	/*
918f46af505SJordan K. Hubbard 	 * Parse args
919f46af505SJordan K. Hubbard 	 */
920f46af505SJordan K. Hubbard 	while (1)
921f46af505SJordan K. Hubbard 	{
922f46af505SJordan K. Hubbard 	    while (isspace(*cp)) ++cp;
923f46af505SJordan K. Hubbard 	    if (*cp == '#')
924f46af505SJordan K. Hubbard 	    {
925f46af505SJordan K. Hubbard 		break;		/* found comment */
926f46af505SJordan K. Hubbard 	    }
927f46af505SJordan K. Hubbard 	    if (isalpha(*cp))
928f46af505SJordan K. Hubbard 	    {
929f46af505SJordan K. Hubbard 		command->args[command->n_args].argtype = *cp++;
930f46af505SJordan K. Hubbard 	    }
931f46af505SJordan K. Hubbard 	    if (!isdigit(*cp))
932f46af505SJordan K. Hubbard 	    {
933f46af505SJordan K. Hubbard 		break;		/* assume end of line */
934f46af505SJordan K. Hubbard 	    }
935f46af505SJordan K. Hubbard 	    end = NULL;
936f46af505SJordan K. Hubbard 	    command->args[command->n_args].arg_val = strtol(cp, &end, 0);
937f46af505SJordan K. Hubbard 	    if (cp == end)
938f46af505SJordan K. Hubbard 	    {
939f46af505SJordan K. Hubbard 		break;		/* couldn't parse number */
940f46af505SJordan K. Hubbard 	    }
941f46af505SJordan K. Hubbard 	    cp = end;
942f46af505SJordan K. Hubbard 	    command->n_args++;
943f46af505SJordan K. Hubbard 	}
944f46af505SJordan K. Hubbard 	break;
945f46af505SJordan K. Hubbard     }
946f46af505SJordan K. Hubbard }
947f46af505SJordan K. Hubbard 
948f46af505SJordan K. Hubbard 
949f46af505SJordan K. Hubbard static int
950f46af505SJordan K. Hubbard process_geometry(command)
951f46af505SJordan K. Hubbard     CMD		*command;
952f46af505SJordan K. Hubbard {
953f46af505SJordan K. Hubbard     int		status = 1, i;
954f46af505SJordan K. Hubbard 
955f46af505SJordan K. Hubbard     while (1)
956f46af505SJordan K. Hubbard     {
957f46af505SJordan K. Hubbard 	geom_processed = 1;
958f46af505SJordan K. Hubbard 	if (part_processed)
959f46af505SJordan K. Hubbard 	{
960f46af505SJordan K. Hubbard 	    fprintf(stderr,
961f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: the geometry specification line must occur before\n\
962f46af505SJordan K. Hubbard     all partition specifications.\n",
963f46af505SJordan K. Hubbard 		    name, current_line_number);
964f46af505SJordan K. Hubbard 	    status = 0;
965f46af505SJordan K. Hubbard 	    break;
966f46af505SJordan K. Hubbard 	}
967f46af505SJordan K. Hubbard 	if (command->n_args != 3)
968f46af505SJordan K. Hubbard 	{
969f46af505SJordan K. Hubbard 	    fprintf(stderr,
970f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: incorrect number of geometry args\n",
971f46af505SJordan K. Hubbard 		    name, current_line_number);
972f46af505SJordan K. Hubbard 	    status = 0;
973f46af505SJordan K. Hubbard 	    break;
974f46af505SJordan K. Hubbard 	}
975f46af505SJordan K. Hubbard 	dos_cyls = -1;
976f46af505SJordan K. Hubbard 	dos_heads = -1;
977f46af505SJordan K. Hubbard 	dos_sectors = -1;
978f46af505SJordan K. Hubbard 	for (i = 0; i < 3; ++i)
979f46af505SJordan K. Hubbard 	{
980f46af505SJordan K. Hubbard 	    switch (command->args[i].argtype)
981f46af505SJordan K. Hubbard 	    {
982f46af505SJordan K. Hubbard 	    case 'c':
983f46af505SJordan K. Hubbard 		dos_cyls = command->args[i].arg_val;
984f46af505SJordan K. Hubbard 		break;
985f46af505SJordan K. Hubbard 	    case 'h':
986f46af505SJordan K. Hubbard 		dos_heads = command->args[i].arg_val;
987f46af505SJordan K. Hubbard 		break;
988f46af505SJordan K. Hubbard 	    case 's':
989f46af505SJordan K. Hubbard 		dos_sectors = command->args[i].arg_val;
990f46af505SJordan K. Hubbard 		break;
991f46af505SJordan K. Hubbard 	    default:
992f46af505SJordan K. Hubbard 		fprintf(stderr,
993f46af505SJordan K. Hubbard 			"%s: ERROR line %d: unknown geometry arg type: '%c' (0x%02x)\n",
994f46af505SJordan K. Hubbard 			name, current_line_number, command->args[i].argtype,
995f46af505SJordan K. Hubbard 			command->args[i].argtype);
996f46af505SJordan K. Hubbard 		status = 0;
997f46af505SJordan K. Hubbard 		break;
998f46af505SJordan K. Hubbard 	    }
999f46af505SJordan K. Hubbard 	}
1000f46af505SJordan K. Hubbard 	if (status == 0)
1001f46af505SJordan K. Hubbard 	{
1002f46af505SJordan K. Hubbard 	    break;
1003f46af505SJordan K. Hubbard 	}
1004f46af505SJordan K. Hubbard 
1005f46af505SJordan K. Hubbard 	dos_cylsecs = dos_heads * dos_sectors;
1006f46af505SJordan K. Hubbard 
1007f46af505SJordan K. Hubbard 	/*
1008f46af505SJordan K. Hubbard 	 * Do sanity checks on parameter values
1009f46af505SJordan K. Hubbard 	 */
1010f46af505SJordan K. Hubbard 	if (dos_cyls < 0)
1011f46af505SJordan K. Hubbard 	{
1012f46af505SJordan K. Hubbard 	    fprintf(stderr,
1013f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: number of cylinders not specified\n",
1014f46af505SJordan K. Hubbard 		    name, current_line_number);
1015f46af505SJordan K. Hubbard 	    status = 0;
1016f46af505SJordan K. Hubbard 	}
1017f46af505SJordan K. Hubbard 	if (dos_cyls == 0 || dos_cyls > 1024)
1018f46af505SJordan K. Hubbard 	{
1019f46af505SJordan K. Hubbard 	    fprintf(stderr,
1020f46af505SJordan K. Hubbard 		    "%s: WARNING line %d: number of cylinders (%d) may be out-of-range\n\
1021f46af505SJordan K. Hubbard     (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\
1022f46af505SJordan K. Hubbard     is dedicated to FreeBSD).\n",
1023f46af505SJordan K. Hubbard 		    name, current_line_number, dos_cyls);
1024f46af505SJordan K. Hubbard 	}
1025f46af505SJordan K. Hubbard 
1026f46af505SJordan K. Hubbard 	if (dos_heads < 0)
1027f46af505SJordan K. Hubbard 	{
1028f46af505SJordan K. Hubbard 	    fprintf(stderr,
1029f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: number of heads not specified\n",
1030f46af505SJordan K. Hubbard 		    name, current_line_number);
1031f46af505SJordan K. Hubbard 	    status = 0;
1032f46af505SJordan K. Hubbard 	}
1033f46af505SJordan K. Hubbard 	else if (dos_heads < 1 || dos_heads > 256)
1034f46af505SJordan K. Hubbard 	{
1035f46af505SJordan K. Hubbard 	    fprintf(stderr,
1036f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: number of heads must be within (1-256)\n",
1037f46af505SJordan K. Hubbard 		    name, current_line_number);
1038f46af505SJordan K. Hubbard 	    status = 0;
1039f46af505SJordan K. Hubbard 	}
1040f46af505SJordan K. Hubbard 
1041f46af505SJordan K. Hubbard 	if (dos_sectors < 0)
1042f46af505SJordan K. Hubbard 	{
1043f46af505SJordan K. Hubbard 	    fprintf(stderr, "%s: ERROR line %d: number of sectors not specified\n",
1044f46af505SJordan K. Hubbard 		    name, current_line_number);
1045f46af505SJordan K. Hubbard 	    status = 0;
1046f46af505SJordan K. Hubbard 	}
1047f46af505SJordan K. Hubbard 	else if (dos_sectors < 1 || dos_sectors > 63)
1048f46af505SJordan K. Hubbard 	{
1049f46af505SJordan K. Hubbard 	    fprintf(stderr,
1050f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: number of sectors must be within (1-63)\n",
1051f46af505SJordan K. Hubbard 		    name, current_line_number);
1052f46af505SJordan K. Hubbard 	    status = 0;
1053f46af505SJordan K. Hubbard 	}
1054f46af505SJordan K. Hubbard 
1055f46af505SJordan K. Hubbard 	break;
1056f46af505SJordan K. Hubbard     }
1057f46af505SJordan K. Hubbard     return (status);
1058f46af505SJordan K. Hubbard }
1059f46af505SJordan K. Hubbard 
1060f46af505SJordan K. Hubbard 
1061f46af505SJordan K. Hubbard static int
1062f46af505SJordan K. Hubbard process_partition(command)
1063f46af505SJordan K. Hubbard     CMD		*command;
1064f46af505SJordan K. Hubbard {
1065f46af505SJordan K. Hubbard     int				status = 0, partition;
1066f46af505SJordan K. Hubbard     unsigned long		chunks, adj_size, max_end;
1067f46af505SJordan K. Hubbard     struct dos_partition	*partp;
1068f46af505SJordan K. Hubbard 
1069f46af505SJordan K. Hubbard     while (1)
1070f46af505SJordan K. Hubbard     {
1071f46af505SJordan K. Hubbard 	part_processed = 1;
1072f46af505SJordan K. Hubbard 	if (command->n_args != 4)
1073f46af505SJordan K. Hubbard 	{
1074f46af505SJordan K. Hubbard 	    fprintf(stderr,
1075f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: incorrect number of partition args\n",
1076f46af505SJordan K. Hubbard 		    name, current_line_number);
1077f46af505SJordan K. Hubbard 	    break;
1078f46af505SJordan K. Hubbard 	}
1079f46af505SJordan K. Hubbard 	partition = command->args[0].arg_val;
1080f46af505SJordan K. Hubbard 	if (partition < 0 || partition > 3)
1081f46af505SJordan K. Hubbard 	{
1082f46af505SJordan K. Hubbard 	    fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n",
1083f46af505SJordan K. Hubbard 		    name, current_line_number, partition);
1084f46af505SJordan K. Hubbard 	    break;
1085f46af505SJordan K. Hubbard 	}
1086f46af505SJordan K. Hubbard 	partp = ((struct dos_partition *) &mboot.parts) + partition;
1087f46af505SJordan K. Hubbard 	bzero((char *)partp, sizeof (struct dos_partition));
1088f46af505SJordan K. Hubbard 	partp->dp_typ = command->args[1].arg_val;
1089f46af505SJordan K. Hubbard 	partp->dp_start = command->args[2].arg_val;
1090f46af505SJordan K. Hubbard 	partp->dp_size = command->args[3].arg_val;
1091f46af505SJordan K. Hubbard 	max_end = partp->dp_start + partp->dp_size;
1092f46af505SJordan K. Hubbard 
1093f46af505SJordan K. Hubbard 	if (partp->dp_typ == 0)
1094f46af505SJordan K. Hubbard 	{
1095f46af505SJordan K. Hubbard 	    /*
1096f46af505SJordan K. Hubbard 	     * Get out, the partition is marked as unused.
1097f46af505SJordan K. Hubbard 	     */
1098f46af505SJordan K. Hubbard 	    /*
1099f46af505SJordan K. Hubbard 	     * Insure that it's unused.
1100f46af505SJordan K. Hubbard 	     */
1101f46af505SJordan K. Hubbard 	    bzero((char *)partp, sizeof (struct dos_partition));
1102f46af505SJordan K. Hubbard 	    status = 1;
1103f46af505SJordan K. Hubbard 	    break;
1104f46af505SJordan K. Hubbard 	}
1105f46af505SJordan K. Hubbard 
1106f46af505SJordan K. Hubbard 	/*
1107f46af505SJordan K. Hubbard 	 * Adjust start upwards, if necessary, to fall on an head boundary.
1108f46af505SJordan K. Hubbard 	 */
1109f46af505SJordan K. Hubbard 	if (partp->dp_start % dos_sectors != 0)
1110f46af505SJordan K. Hubbard 	{
1111f46af505SJordan K. Hubbard 	    adj_size =
1112f46af505SJordan K. Hubbard 		(partp->dp_start / dos_sectors + 1) * dos_sectors;
1113f46af505SJordan K. Hubbard 	    if (adj_size > max_end)
1114f46af505SJordan K. Hubbard 	    {
1115f46af505SJordan K. Hubbard 		/*
1116f46af505SJordan K. Hubbard 		 * Can't go past end of partition
1117f46af505SJordan K. Hubbard 		 */
1118f46af505SJordan K. Hubbard 		fprintf(stderr,
1119f46af505SJordan K. Hubbard 			"%s: ERROR line %d: unable to adjust start of partition %d to fall on\n\
1120f46af505SJordan K. Hubbard     a cylinder boundary.\n",
1121f46af505SJordan K. Hubbard 			name, current_line_number, partition);
1122f46af505SJordan K. Hubbard 		break;
1123f46af505SJordan K. Hubbard 	    }
1124f46af505SJordan K. Hubbard 	    fprintf(stderr,
1125f46af505SJordan K. Hubbard 		    "%s: WARNING: adjusting start offset of partition '%d' from %d\n\
1126f46af505SJordan K. Hubbard     to %d, to round to an head boundary.\n",
1127f46af505SJordan K. Hubbard 		    name, partition, partp->dp_start, adj_size);
1128f46af505SJordan K. Hubbard 	    partp->dp_start = adj_size;
1129f46af505SJordan K. Hubbard 	}
1130f46af505SJordan K. Hubbard 
1131f46af505SJordan K. Hubbard 	/*
1132f46af505SJordan K. Hubbard 	 * Adjust size downwards, if necessary, to fall on a cylinder
1133f46af505SJordan K. Hubbard 	 * boundary.
1134f46af505SJordan K. Hubbard 	 */
1135f46af505SJordan K. Hubbard 	chunks =
1136f46af505SJordan K. Hubbard 	    ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs;
1137f46af505SJordan K. Hubbard 	adj_size = chunks - partp->dp_start;
1138f46af505SJordan K. Hubbard 	if (adj_size != partp->dp_size)
1139f46af505SJordan K. Hubbard 	{
1140f46af505SJordan K. Hubbard 	    fprintf(stderr,
1141f46af505SJordan K. Hubbard 		    "%s: WARNING: adjusting size of partition '%d' from %d to %d,\n\
1142f46af505SJordan K. Hubbard     to round to a cylinder boundary.\n",
1143f46af505SJordan K. Hubbard 		    name, partition, partp->dp_size, adj_size);
1144f46af505SJordan K. Hubbard 	    if (chunks > 0)
1145f46af505SJordan K. Hubbard 	    {
1146f46af505SJordan K. Hubbard 		partp->dp_size = adj_size;
1147f46af505SJordan K. Hubbard 	    }
1148f46af505SJordan K. Hubbard 	    else
1149f46af505SJordan K. Hubbard 	    {
1150f46af505SJordan K. Hubbard 		partp->dp_size = 0;
1151f46af505SJordan K. Hubbard 	    }
1152f46af505SJordan K. Hubbard 	}
1153f46af505SJordan K. Hubbard 	if (partp->dp_size < 1)
1154f46af505SJordan K. Hubbard 	{
1155f46af505SJordan K. Hubbard 	    fprintf(stderr,
1156f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: size for partition '%d' is zero.\n",
1157f46af505SJordan K. Hubbard 		    name, current_line_number, partition);
1158f46af505SJordan K. Hubbard 	    break;
1159f46af505SJordan K. Hubbard 	}
1160f46af505SJordan K. Hubbard 
1161f46af505SJordan K. Hubbard 	dos(partp->dp_start, partp->dp_size,
1162f46af505SJordan K. Hubbard 	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
1163f46af505SJordan K. Hubbard 	dos(partp->dp_start+partp->dp_size - 1, partp->dp_size,
1164f46af505SJordan K. Hubbard 	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
1165f46af505SJordan K. Hubbard 	status = 1;
1166f46af505SJordan K. Hubbard 	break;
1167f46af505SJordan K. Hubbard     }
1168f46af505SJordan K. Hubbard     return (status);
1169f46af505SJordan K. Hubbard }
1170f46af505SJordan K. Hubbard 
1171f46af505SJordan K. Hubbard 
1172f46af505SJordan K. Hubbard static int
1173f46af505SJordan K. Hubbard process_active(command)
1174f46af505SJordan K. Hubbard     CMD		*command;
1175f46af505SJordan K. Hubbard {
1176f46af505SJordan K. Hubbard     int				status = 0, partition, i;
1177f46af505SJordan K. Hubbard     struct dos_partition	*partp;
1178f46af505SJordan K. Hubbard 
1179f46af505SJordan K. Hubbard     while (1)
1180f46af505SJordan K. Hubbard     {
1181f46af505SJordan K. Hubbard 	active_processed = 1;
1182f46af505SJordan K. Hubbard 	if (command->n_args != 1)
1183f46af505SJordan K. Hubbard 	{
1184f46af505SJordan K. Hubbard 	    fprintf(stderr,
1185f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: incorrect number of active args\n",
1186f46af505SJordan K. Hubbard 		    name, current_line_number);
1187f46af505SJordan K. Hubbard 	    status = 0;
1188f46af505SJordan K. Hubbard 	    break;
1189f46af505SJordan K. Hubbard 	}
1190f46af505SJordan K. Hubbard 	partition = command->args[0].arg_val;
1191f46af505SJordan K. Hubbard 	if (partition < 0 || partition > 3)
1192f46af505SJordan K. Hubbard 	{
1193f46af505SJordan K. Hubbard 	    fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n",
1194f46af505SJordan K. Hubbard 		    name, current_line_number, partition);
1195f46af505SJordan K. Hubbard 	    break;
1196f46af505SJordan K. Hubbard 	}
1197f46af505SJordan K. Hubbard 	/*
1198f46af505SJordan K. Hubbard 	 * Reset active partition
1199f46af505SJordan K. Hubbard 	 */
1200f46af505SJordan K. Hubbard 	partp = ((struct dos_partition *) &mboot.parts);
1201f46af505SJordan K. Hubbard 	for (i = 0; i < NDOSPART; i++)
1202f46af505SJordan K. Hubbard 	    partp[i].dp_flag = 0;
1203f46af505SJordan K. Hubbard 	partp[partition].dp_flag = ACTIVE;
1204f46af505SJordan K. Hubbard 
1205f46af505SJordan K. Hubbard 	status = 1;
1206f46af505SJordan K. Hubbard 	break;
1207f46af505SJordan K. Hubbard     }
1208f46af505SJordan K. Hubbard     return (status);
1209f46af505SJordan K. Hubbard }
1210f46af505SJordan K. Hubbard 
1211f46af505SJordan K. Hubbard 
1212f46af505SJordan K. Hubbard static int
1213f46af505SJordan K. Hubbard process_line(line)
1214f46af505SJordan K. Hubbard     char	*line;
1215f46af505SJordan K. Hubbard {
1216f46af505SJordan K. Hubbard     CMD		command;
1217f46af505SJordan K. Hubbard     int		status = 1;
1218f46af505SJordan K. Hubbard 
1219f46af505SJordan K. Hubbard     while (1)
1220f46af505SJordan K. Hubbard     {
1221f46af505SJordan K. Hubbard 	parse_config_line(line, &command);
1222f46af505SJordan K. Hubbard 	switch (command.cmd)
1223f46af505SJordan K. Hubbard 	{
1224f46af505SJordan K. Hubbard 	case 0:
1225f46af505SJordan K. Hubbard 	    /*
1226f46af505SJordan K. Hubbard 	     * Comment or blank line
1227f46af505SJordan K. Hubbard 	     */
1228f46af505SJordan K. Hubbard 	    break;
1229f46af505SJordan K. Hubbard 	case 'g':
1230f46af505SJordan K. Hubbard 	    /*
1231f46af505SJordan K. Hubbard 	     * Set geometry
1232f46af505SJordan K. Hubbard 	     */
1233f46af505SJordan K. Hubbard 	    status = process_geometry(&command);
1234f46af505SJordan K. Hubbard 	    break;
1235f46af505SJordan K. Hubbard 	case 'p':
1236f46af505SJordan K. Hubbard 	    status = process_partition(&command);
1237f46af505SJordan K. Hubbard 	    break;
1238f46af505SJordan K. Hubbard 	case 'a':
1239f46af505SJordan K. Hubbard 	    status = process_active(&command);
1240f46af505SJordan K. Hubbard 	    break;
1241f46af505SJordan K. Hubbard 	default:
1242f46af505SJordan K. Hubbard 	    status = 0;
1243f46af505SJordan K. Hubbard 	    break;
1244f46af505SJordan K. Hubbard 	}
1245f46af505SJordan K. Hubbard 	break;
1246f46af505SJordan K. Hubbard     }
1247f46af505SJordan K. Hubbard     return (status);
1248f46af505SJordan K. Hubbard }
1249f46af505SJordan K. Hubbard 
1250f46af505SJordan K. Hubbard 
1251f46af505SJordan K. Hubbard static int
1252f46af505SJordan K. Hubbard read_config(config_file)
1253f46af505SJordan K. Hubbard     char *config_file;
1254f46af505SJordan K. Hubbard {
1255f46af505SJordan K. Hubbard     FILE	*fp = NULL;
1256f46af505SJordan K. Hubbard     int		status = 1;
1257f46af505SJordan K. Hubbard     char	buf[1010];
1258f46af505SJordan K. Hubbard 
1259f46af505SJordan K. Hubbard     while (1)	/* dirty trick used to insure one exit point for this
1260f46af505SJordan K. Hubbard 		   function */
1261f46af505SJordan K. Hubbard     {
1262f46af505SJordan K. Hubbard 	if (strcmp(config_file, "-") != 0)
1263f46af505SJordan K. Hubbard 	{
1264f46af505SJordan K. Hubbard 	    /*
1265f46af505SJordan K. Hubbard 	     * We're not reading from stdin
1266f46af505SJordan K. Hubbard 	     */
1267f46af505SJordan K. Hubbard 	    if ((fp = fopen(config_file, "r")) == NULL)
1268f46af505SJordan K. Hubbard 	    {
1269f46af505SJordan K. Hubbard 		status = 0;
1270f46af505SJordan K. Hubbard 		break;
1271f46af505SJordan K. Hubbard 	    }
1272f46af505SJordan K. Hubbard 	}
1273f46af505SJordan K. Hubbard 	else
1274f46af505SJordan K. Hubbard 	{
1275f46af505SJordan K. Hubbard 	    fp = stdin;
1276f46af505SJordan K. Hubbard 	}
1277f46af505SJordan K. Hubbard 	current_line_number = 0;
1278f46af505SJordan K. Hubbard 	while (!feof(fp))
1279f46af505SJordan K. Hubbard 	{
1280f46af505SJordan K. Hubbard 	    if (fgets(buf, sizeof(buf), fp) == NULL)
1281f46af505SJordan K. Hubbard 	    {
1282f46af505SJordan K. Hubbard 		break;
1283f46af505SJordan K. Hubbard 	    }
1284f46af505SJordan K. Hubbard 	    ++current_line_number;
1285f46af505SJordan K. Hubbard 	    status = process_line(buf);
1286f46af505SJordan K. Hubbard 	    if (status == 0)
1287f46af505SJordan K. Hubbard 	    {
1288f46af505SJordan K. Hubbard 		break;
1289f46af505SJordan K. Hubbard 	    }
1290f46af505SJordan K. Hubbard 	}
1291f46af505SJordan K. Hubbard 	break;
1292f46af505SJordan K. Hubbard     }
1293f46af505SJordan K. Hubbard     if (fp)
1294f46af505SJordan K. Hubbard     {
1295f46af505SJordan K. Hubbard 	/*
1296f46af505SJordan K. Hubbard 	 * It doesn't matter if we're reading from stdin, as we've reached EOF
1297f46af505SJordan K. Hubbard 	 */
1298f46af505SJordan K. Hubbard 	fclose(fp);
1299f46af505SJordan K. Hubbard     }
1300f46af505SJordan K. Hubbard     return (status);
1301f46af505SJordan K. Hubbard }
1302f46af505SJordan K. Hubbard 
1303f46af505SJordan K. Hubbard 
1304f46af505SJordan K. Hubbard static void
1305f46af505SJordan K. Hubbard reset_boot(void)
1306f46af505SJordan K. Hubbard {
1307f46af505SJordan K. Hubbard     int				i;
1308f46af505SJordan K. Hubbard     struct dos_partition	*partp;
1309f46af505SJordan K. Hubbard 
1310f46af505SJordan K. Hubbard     init_boot();
1311f46af505SJordan K. Hubbard     for (i = 0; i < 4; ++i)
1312f46af505SJordan K. Hubbard     {
1313f46af505SJordan K. Hubbard 	partp = ((struct dos_partition *) &mboot.parts) + i;
1314f46af505SJordan K. Hubbard 	bzero((char *)partp, sizeof (struct dos_partition));
1315f46af505SJordan K. Hubbard     }
1316f46af505SJordan K. Hubbard }
1317