xref: /freebsd/sbin/fdisk/fdisk.c (revision 26555b64bc129cecde6c14b611fa99dca345f3f0)
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"}
16726555b64SAndrey A. Chernov 	,{0x04, "Primary DOS with 16 bit FAT (<= 32MB)"}
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"}
17426555b64SAndrey A. Chernov 	,{0x0B, "DOS or Windows 95 with 32 bit FAT"}
17526555b64SAndrey A. Chernov 	,{0x0C, "DOS or Windows 95 with 32 bit FAT, LBA"}
17626555b64SAndrey A. Chernov 	,{0x0E, "Primary 'big' DOS (> 32MB, LBA)"}
17726555b64SAndrey A. Chernov 	,{0x0F, "Extended DOS, LBA"}
1785b81b6b3SRodney W. Grimes 	,{0x10, "OPUS"}
1795b81b6b3SRodney W. Grimes 	,{0x40, "VENIX 286"}
1805b81b6b3SRodney W. Grimes 	,{0x50, "DM"}
1815b81b6b3SRodney W. Grimes 	,{0x51, "DM"}
1825b81b6b3SRodney W. Grimes 	,{0x52, "CP/M or Microport SysV/AT"}
1835b81b6b3SRodney W. Grimes 	,{0x56, "GB"}
1845b81b6b3SRodney W. Grimes 	,{0x61, "Speed"}
1855b81b6b3SRodney W. Grimes 	,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
1865b81b6b3SRodney W. Grimes 	,{0x64, "Novell Netware 2.xx"}
1875b81b6b3SRodney W. Grimes 	,{0x65, "Novell Netware 3.xx"}
1885b81b6b3SRodney W. Grimes 	,{0x75, "PCIX"}
1895b81b6b3SRodney W. Grimes 	,{0x80, "Minix 1.1 ... 1.4a"}
1905b81b6b3SRodney W. Grimes 	,{0x81, "Minix 1.4b ... 1.5.10"}
19149f7c177SJordan K. Hubbard 	,{0x82, "Linux swap"}
19249f7c177SJordan K. Hubbard 	,{0x83, "Linux filesystem"}
1935b81b6b3SRodney W. Grimes 	,{0x93, "Amoeba filesystem"}
1945b81b6b3SRodney W. Grimes 	,{0x94, "Amoeba bad block table"}
19549f7c177SJordan K. Hubbard 	,{0xA5, "FreeBSD/NetBSD/386BSD"}
196e37a137dSWarner Losh 	,{0xA6, "OpenBSD"}
1975f0c9424SGary Palmer 	,{0xA7, "NEXTSTEP"}
1985b81b6b3SRodney W. Grimes 	,{0xB7, "BSDI BSD/386 filesystem"}
1995b81b6b3SRodney W. Grimes 	,{0xB8, "BSDI BSD/386 swap"}
2005b81b6b3SRodney W. Grimes 	,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
2015b81b6b3SRodney W. Grimes 	,{0xE1, "Speed"}
2025b81b6b3SRodney W. Grimes 	,{0xE3, "Speed"}
2035b81b6b3SRodney W. Grimes 	,{0xE4, "Speed"}
2045b81b6b3SRodney W. Grimes 	,{0xF1, "Speed"}
2055b81b6b3SRodney W. Grimes 	,{0xF2, "DOS 3.3+ Secondary"}
2065b81b6b3SRodney W. Grimes 	,{0xF4, "Speed"}
2075b81b6b3SRodney W. Grimes 	,{0xFF, "BBT (Bad Blocks Table)"}
2085b81b6b3SRodney W. Grimes };
2095b81b6b3SRodney W. Grimes 
2104be1e61bSAlexander Langer static void print_s0(int which);
2114be1e61bSAlexander Langer static void print_part(int i);
2124be1e61bSAlexander Langer static void init_sector0(unsigned long start);
213f46af505SJordan K. Hubbard static void init_boot(void);
2144be1e61bSAlexander Langer static void change_part(int i);
2154be1e61bSAlexander Langer static void print_params();
2164be1e61bSAlexander Langer static void change_active(int which);
2174be1e61bSAlexander Langer static void get_params_to_use();
218e2975440SBruce Evans static void dos(int sec, int size, unsigned char *c, unsigned char *s,
219e2975440SBruce Evans 		unsigned char *h);
2204be1e61bSAlexander Langer static int open_disk(int u_flag);
2214be1e61bSAlexander Langer static ssize_t read_disk(off_t sector, void *buf);
2224be1e61bSAlexander Langer static ssize_t write_disk(off_t sector, void *buf);
2234be1e61bSAlexander Langer static int get_params();
2244be1e61bSAlexander Langer static int read_s0();
2254be1e61bSAlexander Langer static int write_s0();
2264be1e61bSAlexander Langer static int ok(char *str);
2274be1e61bSAlexander Langer static int decimal(char *str, int *num, int deflt);
2284be1e61bSAlexander Langer static char *get_type(int type);
229f46af505SJordan K. Hubbard static int read_config(char *config_file);
230f46af505SJordan K. Hubbard static void reset_boot(void);
2314be1e61bSAlexander Langer #if 0
2324be1e61bSAlexander Langer static int hex(char *str, int *num, int deflt);
2334be1e61bSAlexander Langer static int string(char *str, char **ans);
2344be1e61bSAlexander Langer #endif
2355b81b6b3SRodney W. Grimes 
2364be1e61bSAlexander Langer 
2374be1e61bSAlexander Langer int
2384be1e61bSAlexander Langer main(int argc, char *argv[])
2395b81b6b3SRodney W. Grimes {
2405b81b6b3SRodney W. Grimes 	int	i;
2415b81b6b3SRodney W. Grimes 
2425b81b6b3SRodney W. Grimes 	name = *argv;
2435b81b6b3SRodney W. Grimes 	{register char *cp = name;
2445b81b6b3SRodney W. Grimes 		while (*cp) if (*cp++ == '/') name = cp;
2455b81b6b3SRodney W. Grimes 	}
2465b81b6b3SRodney W. Grimes 
2475b81b6b3SRodney W. Grimes 	for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
2485b81b6b3SRodney W. Grimes 		if (*token++ != '-' || !*token)
2495b81b6b3SRodney W. Grimes 			break;
2505b81b6b3SRodney W. Grimes 		else { register int flag;
2514be1e61bSAlexander Langer 			for ( ; (flag = *token++) ; ) {
2525b81b6b3SRodney W. Grimes 				switch (flag) {
2535b81b6b3SRodney W. Grimes 				case '1':
2545b81b6b3SRodney W. Grimes 					partition = 1;
2555b81b6b3SRodney W. Grimes 					break;
2565b81b6b3SRodney W. Grimes 				case '2':
2575b81b6b3SRodney W. Grimes 					partition = 2;
2585b81b6b3SRodney W. Grimes 					break;
2595b81b6b3SRodney W. Grimes 				case '3':
2605b81b6b3SRodney W. Grimes 					partition = 3;
2615b81b6b3SRodney W. Grimes 					break;
2624ddd60b9SBrian Somers 				case '4':
2634ddd60b9SBrian Somers 					partition = 4;
2644ddd60b9SBrian Somers 					break;
2655b81b6b3SRodney W. Grimes 				case 'a':
2665b81b6b3SRodney W. Grimes 					a_flag = 1;
2675b81b6b3SRodney W. Grimes 					break;
268f46af505SJordan K. Hubbard 				case 'f':
269f46af505SJordan K. Hubbard 					if (*token)
270f46af505SJordan K. Hubbard 					{
271f46af505SJordan K. Hubbard 					    f_flag = token;
272f46af505SJordan K. Hubbard 					    token = "";
273f46af505SJordan K. Hubbard 					}
274f46af505SJordan K. Hubbard 					else
275f46af505SJordan K. Hubbard 					{
276f46af505SJordan K. Hubbard 					    if (argc == 1)
277f46af505SJordan K. Hubbard 					    {
278f46af505SJordan K. Hubbard 						goto usage;
279f46af505SJordan K. Hubbard 					    }
280f46af505SJordan K. Hubbard 					    --argc;
281f46af505SJordan K. Hubbard 					    f_flag = *++argv;
282f46af505SJordan K. Hubbard 					}
283f46af505SJordan K. Hubbard 					/*
284f46af505SJordan K. Hubbard 					 * u_flag is needed, because we're
285f46af505SJordan K. Hubbard 					 * writing to the disk.
286f46af505SJordan K. Hubbard 					 */
287f46af505SJordan K. Hubbard 					u_flag = 1;
288f46af505SJordan K. Hubbard 					break;
2895b81b6b3SRodney W. Grimes 				case 'i':
2905b81b6b3SRodney W. Grimes 					i_flag = 1;
2915b81b6b3SRodney W. Grimes 				case 'u':
2925b81b6b3SRodney W. Grimes 					u_flag = 1;
2935b81b6b3SRodney W. Grimes 					break;
294f46af505SJordan K. Hubbard 				case 't':
295f46af505SJordan K. Hubbard 					t_flag = 1;
296f46af505SJordan K. Hubbard 				case 'v':
297f46af505SJordan K. Hubbard 					v_flag = 1;
298f46af505SJordan K. Hubbard 					break;
2995b81b6b3SRodney W. Grimes 				default:
3005b81b6b3SRodney W. Grimes 					goto usage;
3015b81b6b3SRodney W. Grimes 				}
3025b81b6b3SRodney W. Grimes 			}
3035b81b6b3SRodney W. Grimes 		}
3045b81b6b3SRodney W. Grimes 	}
3055b81b6b3SRodney W. Grimes 
3065b81b6b3SRodney W. Grimes 	if (argc > 0)
307e3038c6eSJoerg Wunsch 	{
308e3038c6eSJoerg Wunsch 		static char realname[12];
309e3038c6eSJoerg Wunsch 
310e3038c6eSJoerg Wunsch 		if(strncmp(argv[0], "/dev", 4) == 0)
3115b81b6b3SRodney W. Grimes 			disk = argv[0];
312e3038c6eSJoerg Wunsch 		else
313e3038c6eSJoerg Wunsch 		{
314e3038c6eSJoerg Wunsch 			snprintf(realname, 12, "/dev/r%s", argv[0]);
315e3038c6eSJoerg Wunsch 			disk = realname;
316e3038c6eSJoerg Wunsch 		}
3175b81b6b3SRodney W. Grimes 
3185b81b6b3SRodney W. Grimes 		if (open_disk(u_flag) < 0)
319e3038c6eSJoerg Wunsch 		{
320e3038c6eSJoerg Wunsch 			fprintf(stderr, "Cannot open disk %s (%s)\n",
321e3038c6eSJoerg Wunsch 				disk, sys_errlist[errno]);
3225b81b6b3SRodney W. Grimes 			exit(1);
323e3038c6eSJoerg Wunsch 		}
324e3038c6eSJoerg Wunsch 	}
325e3038c6eSJoerg Wunsch 	else
326e3038c6eSJoerg Wunsch 	{
3274be1e61bSAlexander Langer 		int i, rv = 0;
328e3038c6eSJoerg Wunsch 
329e3038c6eSJoerg Wunsch 		for(i = 0; disks[i]; i++)
330e3038c6eSJoerg Wunsch 		{
331e3038c6eSJoerg Wunsch 			disk = disks[i];
332e3038c6eSJoerg Wunsch 			rv = open_disk(u_flag);
333e3038c6eSJoerg Wunsch 			if(rv != -2) break;
334e3038c6eSJoerg Wunsch 		}
335e3038c6eSJoerg Wunsch 		if(rv < 0)
336e3038c6eSJoerg Wunsch 		{
337e3038c6eSJoerg Wunsch 			fprintf(stderr, "Cannot open any disk (%s)\n",
338e3038c6eSJoerg Wunsch 				sys_errlist[errno]);
339e3038c6eSJoerg Wunsch 			exit(1);
340e3038c6eSJoerg Wunsch 		}
341e3038c6eSJoerg Wunsch 	}
3425b81b6b3SRodney W. Grimes 
3435b81b6b3SRodney W. Grimes 	printf("******* Working on device %s *******\n",disk);
344f46af505SJordan K. Hubbard 
345f46af505SJordan K. Hubbard 	if (f_flag)
346f46af505SJordan K. Hubbard 	{
347f46af505SJordan K. Hubbard 	    if (read_s0() || i_flag)
348f46af505SJordan K. Hubbard 	    {
349f46af505SJordan K. Hubbard 		reset_boot();
350f46af505SJordan K. Hubbard 	    }
351f46af505SJordan K. Hubbard 
352f46af505SJordan K. Hubbard 	    if (!read_config(f_flag))
353f46af505SJordan K. Hubbard 	    {
354f46af505SJordan K. Hubbard 		exit(1);
355f46af505SJordan K. Hubbard 	    }
356f46af505SJordan K. Hubbard 	    if (v_flag)
357f46af505SJordan K. Hubbard 	    {
358f46af505SJordan K. Hubbard 		print_s0(-1);
359f46af505SJordan K. Hubbard 	    }
360f46af505SJordan K. Hubbard 	    if (!t_flag)
361f46af505SJordan K. Hubbard 	    {
362f46af505SJordan K. Hubbard 		write_s0();
363f46af505SJordan K. Hubbard 	    }
364f46af505SJordan K. Hubbard 	}
365f46af505SJordan K. Hubbard 	else
366f46af505SJordan K. Hubbard 	{
3675b81b6b3SRodney W. Grimes 	    if(u_flag)
3685b81b6b3SRodney W. Grimes 	    {
3695b81b6b3SRodney W. Grimes 		get_params_to_use();
3705b81b6b3SRodney W. Grimes 	    }
3715b81b6b3SRodney W. Grimes 	    else
3725b81b6b3SRodney W. Grimes 	    {
3735b81b6b3SRodney W. Grimes 		print_params();
3745b81b6b3SRodney W. Grimes 	    }
3755b81b6b3SRodney W. Grimes 
3765b81b6b3SRodney W. Grimes 	    if (read_s0())
3775b81b6b3SRodney W. Grimes 		init_sector0(1);
3785b81b6b3SRodney W. Grimes 
3797cb29d33SSøren Schmidt 	    printf("Media sector size is %d\n", secsize);
3805b81b6b3SRodney W. Grimes 	    printf("Warning: BIOS sector numbering starts with sector 1\n");
3815b81b6b3SRodney W. Grimes 	    printf("Information from DOS bootblock is:\n");
3825b81b6b3SRodney W. Grimes 	    if (partition == -1)
3834ddd60b9SBrian Somers 		for (i = 1; i <= NDOSPART; i++)
3845b81b6b3SRodney W. Grimes 		    change_part(i);
3855b81b6b3SRodney W. Grimes 	    else
3865b81b6b3SRodney W. Grimes 		change_part(partition);
3875b81b6b3SRodney W. Grimes 
3885b81b6b3SRodney W. Grimes 	    if (u_flag || a_flag)
3895b81b6b3SRodney W. Grimes 		change_active(partition);
3905b81b6b3SRodney W. Grimes 
3915b81b6b3SRodney W. Grimes 	    if (u_flag || a_flag) {
392f46af505SJordan K. Hubbard 		if (!t_flag)
393f46af505SJordan K. Hubbard 		{
3945b81b6b3SRodney W. Grimes 		    printf("\nWe haven't changed the partition table yet.  ");
3955b81b6b3SRodney W. Grimes 		    printf("This is your last chance.\n");
396f46af505SJordan K. Hubbard 		}
3975b81b6b3SRodney W. Grimes 		print_s0(-1);
398f46af505SJordan K. Hubbard 		if (!t_flag)
399f46af505SJordan K. Hubbard 		{
4005b81b6b3SRodney W. Grimes 		    if (ok("Should we write new partition table?"))
4015b81b6b3SRodney W. Grimes 			write_s0();
4025b81b6b3SRodney W. Grimes 		}
403f46af505SJordan K. Hubbard 		else
404f46af505SJordan K. Hubbard 		{
405f46af505SJordan K. Hubbard 		    printf("\n-t flag specified -- partition table not written.\n");
406f46af505SJordan K. Hubbard 		}
407f46af505SJordan K. Hubbard 	    }
408f46af505SJordan K. Hubbard 	}
4095b81b6b3SRodney W. Grimes 
4105b81b6b3SRodney W. Grimes 	exit(0);
4115b81b6b3SRodney W. Grimes 
4125b81b6b3SRodney W. Grimes usage:
4134ddd60b9SBrian Somers 	printf("fdisk {-a|-i|-u} [-f <config file> [-t] [-v]] [-{1,2,3,4}] [disk]\n");
4144be1e61bSAlexander Langer 	return(1);
4155b81b6b3SRodney W. Grimes }
4165b81b6b3SRodney W. Grimes 
4174be1e61bSAlexander Langer static void
4184be1e61bSAlexander Langer print_s0(int which)
4195b81b6b3SRodney W. Grimes {
4205b81b6b3SRodney W. Grimes int	i;
4215b81b6b3SRodney W. Grimes 
4225b81b6b3SRodney W. Grimes 	print_params();
4235b81b6b3SRodney W. Grimes 	printf("Information from DOS bootblock is:\n");
4245b81b6b3SRodney W. Grimes 	if (which == -1)
4254ddd60b9SBrian Somers 		for (i = 1; i <= NDOSPART; i++)
4265b81b6b3SRodney W. Grimes 			printf("%d: ", i), print_part(i);
4275b81b6b3SRodney W. Grimes 	else
4285b81b6b3SRodney W. Grimes 		print_part(which);
4295b81b6b3SRodney W. Grimes }
4305b81b6b3SRodney W. Grimes 
4315b81b6b3SRodney W. Grimes static struct dos_partition mtpart = { 0 };
4325b81b6b3SRodney W. Grimes 
4334be1e61bSAlexander Langer static void
4344be1e61bSAlexander Langer print_part(int i)
4355b81b6b3SRodney W. Grimes {
436637fe2f7SJustin T. Gibbs 	struct	  dos_partition *partp;
437637fe2f7SJustin T. Gibbs 	u_int64_t part_mb;
4385b81b6b3SRodney W. Grimes 
4394ddd60b9SBrian Somers 	partp = ((struct dos_partition *) &mboot.parts) + i - 1;
4405b81b6b3SRodney W. Grimes 
4415b81b6b3SRodney W. Grimes 	if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
4425b81b6b3SRodney W. Grimes 		printf("<UNUSED>\n");
4435b81b6b3SRodney W. Grimes 		return;
4445b81b6b3SRodney W. Grimes 	}
445637fe2f7SJustin T. Gibbs 	/*
446637fe2f7SJustin T. Gibbs 	 * Be careful not to overflow.
447637fe2f7SJustin T. Gibbs 	 */
448637fe2f7SJustin T. Gibbs 	part_mb = partp->dp_size;
449637fe2f7SJustin T. Gibbs 	part_mb *= secsize;
450637fe2f7SJustin T. Gibbs 	part_mb /= (1024 * 1024);
4515b81b6b3SRodney W. Grimes 	printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
452637fe2f7SJustin T. Gibbs 	printf("    start %ld, size %ld (%qd Meg), flag %x\n",
4535b81b6b3SRodney W. Grimes 		partp->dp_start,
454637fe2f7SJustin T. Gibbs 		partp->dp_size,
455637fe2f7SJustin T. Gibbs 		part_mb,
4565b81b6b3SRodney W. Grimes 		partp->dp_flag);
4575b81b6b3SRodney W. Grimes 	printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
4585b81b6b3SRodney W. Grimes 		,DPCYL(partp->dp_scyl, partp->dp_ssect)
4595b81b6b3SRodney W. Grimes 		,DPSECT(partp->dp_ssect)
4605b81b6b3SRodney W. Grimes 		,partp->dp_shd
4615b81b6b3SRodney W. Grimes 		,DPCYL(partp->dp_ecyl, partp->dp_esect)
4625b81b6b3SRodney W. Grimes 		,DPSECT(partp->dp_esect)
4635b81b6b3SRodney W. Grimes 		,partp->dp_ehd);
4645b81b6b3SRodney W. Grimes }
4655b81b6b3SRodney W. Grimes 
466f46af505SJordan K. Hubbard 
467f46af505SJordan K. Hubbard static void
468f46af505SJordan K. Hubbard init_boot(void)
469f46af505SJordan K. Hubbard {
470f46af505SJordan K. Hubbard 	memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
471f46af505SJordan K. Hubbard 	mboot.signature = BOOT_MAGIC;
472f46af505SJordan K. Hubbard }
473f46af505SJordan K. Hubbard 
474f46af505SJordan K. Hubbard 
4754be1e61bSAlexander Langer static void
4764be1e61bSAlexander Langer init_sector0(unsigned long start)
4775b81b6b3SRodney W. Grimes {
4785b81b6b3SRodney W. Grimes struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
4794be1e61bSAlexander Langer unsigned long size = disksecs - start;
4805b81b6b3SRodney W. Grimes 
481f46af505SJordan K. Hubbard 	init_boot();
4825b81b6b3SRodney W. Grimes 
4835b81b6b3SRodney W. Grimes 	partp->dp_typ = DOSPTYP_386BSD;
4845b81b6b3SRodney W. Grimes 	partp->dp_flag = ACTIVE;
4855b81b6b3SRodney W. Grimes 	partp->dp_start = start;
4865b81b6b3SRodney W. Grimes 	partp->dp_size = size;
4875b81b6b3SRodney W. Grimes 
488e2975440SBruce Evans 	dos(partp->dp_start, partp->dp_size,
489e2975440SBruce Evans 	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
490e2975440SBruce Evans 	dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
491e2975440SBruce Evans 	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
4925b81b6b3SRodney W. Grimes }
4935b81b6b3SRodney W. Grimes 
4944be1e61bSAlexander Langer static void
4954be1e61bSAlexander Langer change_part(int i)
4965b81b6b3SRodney W. Grimes {
4974ddd60b9SBrian Somers struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i - 1;
4985b81b6b3SRodney W. Grimes 
4995b81b6b3SRodney W. Grimes     printf("The data for partition %d is:\n", i);
5005b81b6b3SRodney W. Grimes     print_part(i);
5015b81b6b3SRodney W. Grimes 
5025b81b6b3SRodney W. Grimes     if (u_flag && ok("Do you want to change it?")) {
5035b81b6b3SRodney W. Grimes 	int tmp;
5045b81b6b3SRodney W. Grimes 
5055b81b6b3SRodney W. Grimes 	if (i_flag) {
5065b81b6b3SRodney W. Grimes 		bzero((char *)partp, sizeof (struct dos_partition));
5074ddd60b9SBrian Somers 		if (i == 4) {
5085b81b6b3SRodney W. Grimes 			init_sector0(1);
5094ddd60b9SBrian Somers 			printf("\nThe static data for the DOS partition 4 has been reinitialized to:\n");
5105b81b6b3SRodney W. Grimes 			print_part(i);
5115b81b6b3SRodney W. Grimes 		}
5125b81b6b3SRodney W. Grimes 	}
5135b81b6b3SRodney W. Grimes 
5145b81b6b3SRodney W. Grimes 	do {
5155b81b6b3SRodney W. Grimes 		Decimal("sysid", partp->dp_typ, tmp);
5165b81b6b3SRodney W. Grimes 		Decimal("start", partp->dp_start, tmp);
5175b81b6b3SRodney W. Grimes 		Decimal("size", partp->dp_size, tmp);
5185b81b6b3SRodney W. Grimes 
5195b81b6b3SRodney W. Grimes 		if (ok("Explicitly specifiy beg/end address ?"))
5205b81b6b3SRodney W. Grimes 		{
5215b81b6b3SRodney W. Grimes 			int	tsec,tcyl,thd;
5225b81b6b3SRodney W. Grimes 			tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
5235b81b6b3SRodney W. Grimes 			thd = partp->dp_shd;
5245b81b6b3SRodney W. Grimes 			tsec = DPSECT(partp->dp_ssect);
5255b81b6b3SRodney W. Grimes 			Decimal("beginning cylinder", tcyl, tmp);
5265b81b6b3SRodney W. Grimes 			Decimal("beginning head", thd, tmp);
5275b81b6b3SRodney W. Grimes 			Decimal("beginning sector", tsec, tmp);
5285b81b6b3SRodney W. Grimes 			partp->dp_scyl = DOSCYL(tcyl);
5295b81b6b3SRodney W. Grimes 			partp->dp_ssect = DOSSECT(tsec,tcyl);
5305b81b6b3SRodney W. Grimes 			partp->dp_shd = thd;
5315b81b6b3SRodney W. Grimes 
5325b81b6b3SRodney W. Grimes 			tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
5335b81b6b3SRodney W. Grimes 			thd = partp->dp_ehd;
5345b81b6b3SRodney W. Grimes 			tsec = DPSECT(partp->dp_esect);
5355b81b6b3SRodney W. Grimes 			Decimal("ending cylinder", tcyl, tmp);
5365b81b6b3SRodney W. Grimes 			Decimal("ending head", thd, tmp);
5375b81b6b3SRodney W. Grimes 			Decimal("ending sector", tsec, tmp);
5385b81b6b3SRodney W. Grimes 			partp->dp_ecyl = DOSCYL(tcyl);
5395b81b6b3SRodney W. Grimes 			partp->dp_esect = DOSSECT(tsec,tcyl);
5405b81b6b3SRodney W. Grimes 			partp->dp_ehd = thd;
5415b81b6b3SRodney W. Grimes 		} else {
542e2975440SBruce Evans 			dos(partp->dp_start, partp->dp_size,
5435b81b6b3SRodney W. Grimes 			    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
544e2975440SBruce Evans 			dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
5455b81b6b3SRodney W. Grimes 			    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
5465b81b6b3SRodney W. Grimes 		}
5475b81b6b3SRodney W. Grimes 
5485b81b6b3SRodney W. Grimes 		print_part(i);
5495b81b6b3SRodney W. Grimes 	} while (!ok("Are we happy with this entry?"));
5505b81b6b3SRodney W. Grimes     }
5515b81b6b3SRodney W. Grimes }
5525b81b6b3SRodney W. Grimes 
5534be1e61bSAlexander Langer static void
5545b81b6b3SRodney W. Grimes print_params()
5555b81b6b3SRodney W. Grimes {
5565b81b6b3SRodney W. Grimes 	printf("parameters extracted from in-core disklabel are:\n");
5575b81b6b3SRodney W. Grimes 	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
5585b81b6b3SRodney W. Grimes 			,cyls,heads,sectors,cylsecs);
5595b81b6b3SRodney W. Grimes 	if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
5605b81b6b3SRodney W. Grimes 		printf("Figures below won't work with BIOS for partitions not in cyl 1\n");
5615b81b6b3SRodney W. Grimes 	printf("parameters to be used for BIOS calculations are:\n");
5625b81b6b3SRodney W. Grimes 	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
5635b81b6b3SRodney W. Grimes 		,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
5645b81b6b3SRodney W. Grimes }
5655b81b6b3SRodney W. Grimes 
5664be1e61bSAlexander Langer static void
5674be1e61bSAlexander Langer change_active(int which)
5685b81b6b3SRodney W. Grimes {
5695b81b6b3SRodney W. Grimes int i;
5704ddd60b9SBrian Somers int active = 4, tmp;
5715b81b6b3SRodney W. Grimes struct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
5725b81b6b3SRodney W. Grimes 
5735b81b6b3SRodney W. Grimes 	if (a_flag && which != -1)
5745b81b6b3SRodney W. Grimes 		active = which;
5750b461cd7SBruce Evans 	if (!ok("Do you want to change the active partition?"))
5760b461cd7SBruce Evans 		return;
5775b81b6b3SRodney W. Grimes 	do
5785b81b6b3SRodney W. Grimes 		Decimal("active partition", active, tmp);
5795b81b6b3SRodney W. Grimes 	while (!ok("Are you happy with this choice"));
5805b81b6b3SRodney W. Grimes 	for (i = 0; i < NDOSPART; i++)
5815b81b6b3SRodney W. Grimes 		partp[i].dp_flag = 0;
5824ddd60b9SBrian Somers 	if (active > 0 && active <= NDOSPART)
5834ddd60b9SBrian Somers 		partp[active-1].dp_flag = ACTIVE;
5845b81b6b3SRodney W. Grimes }
5855b81b6b3SRodney W. Grimes 
5864be1e61bSAlexander Langer void
5875b81b6b3SRodney W. Grimes get_params_to_use()
5885b81b6b3SRodney W. Grimes {
5895b81b6b3SRodney W. Grimes 	int	tmp;
5905b81b6b3SRodney W. Grimes 	print_params();
5915b81b6b3SRodney W. Grimes 	if (ok("Do you want to change our idea of what BIOS thinks ?"))
5925b81b6b3SRodney W. Grimes 	{
5935b81b6b3SRodney W. Grimes 		do
5945b81b6b3SRodney W. Grimes 		{
5955b81b6b3SRodney W. Grimes 			Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
5965b81b6b3SRodney W. Grimes 			Decimal("BIOS's idea of #heads", dos_heads, tmp);
5975b81b6b3SRodney W. Grimes 			Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
5985b81b6b3SRodney W. Grimes 			dos_cylsecs = dos_heads * dos_sectors;
5995b81b6b3SRodney W. Grimes 			print_params();
6005b81b6b3SRodney W. Grimes 		}
6015b81b6b3SRodney W. Grimes 		while(!ok("Are you happy with this choice"));
6025b81b6b3SRodney W. Grimes 	}
6035b81b6b3SRodney W. Grimes }
6045b81b6b3SRodney W. Grimes 
605f46af505SJordan K. Hubbard 
6065b81b6b3SRodney W. Grimes /***********************************************\
6075b81b6b3SRodney W. Grimes * Change real numbers into strange dos numbers	*
6085b81b6b3SRodney W. Grimes \***********************************************/
6094be1e61bSAlexander Langer static void
610e2975440SBruce Evans dos(sec, size, c, s, h)
611e2975440SBruce Evans int sec, size;
6125b81b6b3SRodney W. Grimes unsigned char *c, *s, *h;
6135b81b6b3SRodney W. Grimes {
6145b81b6b3SRodney W. Grimes int cy;
6155b81b6b3SRodney W. Grimes int hd;
6165b81b6b3SRodney W. Grimes 
617e2975440SBruce Evans 	if (sec == 0 && size == 0) {
6180b461cd7SBruce Evans 		*s = *c = *h = 0;
6190b461cd7SBruce Evans 		return;
6200b461cd7SBruce Evans 	}
6210b461cd7SBruce Evans 
6225b81b6b3SRodney W. Grimes 	cy = sec / ( dos_cylsecs );
6235b81b6b3SRodney W. Grimes 	sec = sec - cy * ( dos_cylsecs );
6245b81b6b3SRodney W. Grimes 
6255b81b6b3SRodney W. Grimes 	hd = sec / dos_sectors;
6265b81b6b3SRodney W. Grimes 	sec = (sec - hd * dos_sectors) + 1;
6275b81b6b3SRodney W. Grimes 
6285b81b6b3SRodney W. Grimes 	*h = hd;
6295b81b6b3SRodney W. Grimes 	*c = cy & 0xff;
6305b81b6b3SRodney W. Grimes 	*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
6315b81b6b3SRodney W. Grimes }
6325b81b6b3SRodney W. Grimes 
6335b81b6b3SRodney W. Grimes int fd;
6345b81b6b3SRodney W. Grimes 
6355b81b6b3SRodney W. Grimes 	/* Getting device status */
6365b81b6b3SRodney W. Grimes 
6374be1e61bSAlexander Langer static int
6384be1e61bSAlexander Langer open_disk(int u_flag)
6395b81b6b3SRodney W. Grimes {
6405b81b6b3SRodney W. Grimes struct stat 	st;
6415b81b6b3SRodney W. Grimes 
6425b81b6b3SRodney W. Grimes 	if (stat(disk, &st) == -1) {
6435b81b6b3SRodney W. Grimes 		fprintf(stderr, "%s: Can't get file status of %s\n",
6445b81b6b3SRodney W. Grimes 			name, disk);
6455b81b6b3SRodney W. Grimes 		return -1;
646b60eb395SBruce Evans 	}
647b60eb395SBruce Evans 	if ( !(st.st_mode & S_IFCHR) )
6485b81b6b3SRodney W. Grimes 		fprintf(stderr,"%s: Device %s is not character special\n",
6495b81b6b3SRodney W. Grimes 			name, disk);
6500b461cd7SBruce Evans 	if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) {
651e3038c6eSJoerg Wunsch 		if(errno == ENXIO)
652e3038c6eSJoerg Wunsch 			return -2;
6535b81b6b3SRodney W. Grimes 		fprintf(stderr,"%s: Can't open device %s\n", name, disk);
6545b81b6b3SRodney W. Grimes 		return -1;
6555b81b6b3SRodney W. Grimes 	}
6565b81b6b3SRodney W. Grimes 	if (get_params(0) == -1) {
6575b81b6b3SRodney W. Grimes 		fprintf(stderr, "%s: Can't get disk parameters on %s\n",
6585b81b6b3SRodney W. Grimes 			name, disk);
6595b81b6b3SRodney W. Grimes 		return -1;
6605b81b6b3SRodney W. Grimes 	}
6615b81b6b3SRodney W. Grimes 	return fd;
6625b81b6b3SRodney W. Grimes }
6635b81b6b3SRodney W. Grimes 
6644be1e61bSAlexander Langer static ssize_t
6654be1e61bSAlexander Langer read_disk(off_t sector, void *buf)
6665b81b6b3SRodney W. Grimes {
6675b81b6b3SRodney W. Grimes 	lseek(fd,(sector * 512), 0);
6687cb29d33SSøren Schmidt 	if( secsize == 0 )
6697cb29d33SSøren Schmidt 		for( secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; secsize *= 2 )
6707cb29d33SSøren Schmidt 			{
6717cb29d33SSøren Schmidt 			/* try the read */
6727cb29d33SSøren Schmidt 			int size = read(fd, buf, secsize);
6737cb29d33SSøren Schmidt 			if( size == secsize )
6747cb29d33SSøren Schmidt 				/* it worked so return */
6757cb29d33SSøren Schmidt 				return secsize;
6767cb29d33SSøren Schmidt 			}
6777cb29d33SSøren Schmidt 	else
6787cb29d33SSøren Schmidt 		return read( fd, buf, secsize );
6797cb29d33SSøren Schmidt 
6807cb29d33SSøren Schmidt 	/* we failed to read at any of the sizes */
6817cb29d33SSøren Schmidt 	return -1;
6825b81b6b3SRodney W. Grimes }
6835b81b6b3SRodney W. Grimes 
6844be1e61bSAlexander Langer static ssize_t
6854be1e61bSAlexander Langer write_disk(off_t sector, void *buf)
6865b81b6b3SRodney W. Grimes {
6875b81b6b3SRodney W. Grimes 	lseek(fd,(sector * 512), 0);
6887cb29d33SSøren Schmidt 	/* write out in the size that the read_disk found worked */
6897cb29d33SSøren Schmidt 	return write(fd, buf, secsize);
6905b81b6b3SRodney W. Grimes }
6915b81b6b3SRodney W. Grimes 
6924be1e61bSAlexander Langer static int
6934be1e61bSAlexander Langer get_params()
6945b81b6b3SRodney W. Grimes {
6955b81b6b3SRodney W. Grimes 
6965b81b6b3SRodney W. Grimes     if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
697b60eb395SBruce Evans 	fprintf(stderr,
698b60eb395SBruce Evans 		"%s: Can't get disk parameters on %s; supplying dummy ones\n",
699b60eb395SBruce Evans 		name, disk);
700b60eb395SBruce Evans 	dos_cyls = cyls = 1;
701b60eb395SBruce Evans 	dos_heads = heads = 1;
702b60eb395SBruce Evans 	dos_sectors = sectors = 1;
703b60eb395SBruce Evans 	dos_cylsecs = cylsecs = heads * sectors;
704b60eb395SBruce Evans 	disksecs = cyls * heads * sectors;
705b60eb395SBruce Evans 	return disksecs;
7065b81b6b3SRodney W. Grimes     }
7075b81b6b3SRodney W. Grimes 
7085b81b6b3SRodney W. Grimes     dos_cyls = cyls = disklabel.d_ncylinders;
7095b81b6b3SRodney W. Grimes     dos_heads = heads = disklabel.d_ntracks;
7105b81b6b3SRodney W. Grimes     dos_sectors = sectors = disklabel.d_nsectors;
7115b81b6b3SRodney W. Grimes     dos_cylsecs = cylsecs = heads * sectors;
7125b81b6b3SRodney W. Grimes     disksecs = cyls * heads * sectors;
7135b81b6b3SRodney W. Grimes 
7145b81b6b3SRodney W. Grimes     return (disksecs);
7155b81b6b3SRodney W. Grimes }
7165b81b6b3SRodney W. Grimes 
7175b81b6b3SRodney W. Grimes 
7184be1e61bSAlexander Langer static int
7195b81b6b3SRodney W. Grimes read_s0()
7205b81b6b3SRodney W. Grimes {
7215b81b6b3SRodney W. Grimes 	if (read_disk(0, (char *) mboot.bootinst) == -1) {
7225b81b6b3SRodney W. Grimes 		fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
7235b81b6b3SRodney W. Grimes 		return -1;
7245b81b6b3SRodney W. Grimes 	}
7255b81b6b3SRodney W. Grimes 	if (mboot.signature != BOOT_MAGIC) {
7265b81b6b3SRodney W. Grimes 		fprintf(stderr, "%s: Invalid fdisk partition table found\n",
7275b81b6b3SRodney W. Grimes 			name);
7285b81b6b3SRodney W. Grimes 		/* So should we initialize things */
7295b81b6b3SRodney W. Grimes 		return -1;
7305b81b6b3SRodney W. Grimes 	}
7315b81b6b3SRodney W. Grimes 	return 0;
7325b81b6b3SRodney W. Grimes }
7335b81b6b3SRodney W. Grimes 
7344be1e61bSAlexander Langer static int
7355b81b6b3SRodney W. Grimes write_s0()
7365b81b6b3SRodney W. Grimes {
7375b81b6b3SRodney W. Grimes 	int	flag;
7385b81b6b3SRodney W. Grimes 	if (iotest) {
7395b81b6b3SRodney W. Grimes 		print_s0(-1);
7405b81b6b3SRodney W. Grimes 		return 0;
7415b81b6b3SRodney W. Grimes 	}
7425b81b6b3SRodney W. Grimes 	/*
7435b81b6b3SRodney W. Grimes 	 * write enable label sector before write (if necessary),
7445b81b6b3SRodney W. Grimes 	 * disable after writing.
7455b81b6b3SRodney W. Grimes 	 * needed if the disklabel protected area also protects
7465b81b6b3SRodney W. Grimes 	 * sector 0. (e.g. empty disk)
7475b81b6b3SRodney W. Grimes 	 */
7485b81b6b3SRodney W. Grimes 	flag = 1;
749ba3551dfSJulian Elischer #ifdef NOT_NOW
7505b81b6b3SRodney W. Grimes 	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
7515b81b6b3SRodney W. Grimes 		perror("ioctl DIOCWLABEL");
752ba3551dfSJulian Elischer #endif
7535b81b6b3SRodney W. Grimes 	if (write_disk(0, (char *) mboot.bootinst) == -1) {
7545b81b6b3SRodney W. Grimes 		fprintf(stderr, "%s: Can't write fdisk partition table\n",
7555b81b6b3SRodney W. Grimes 			name);
7565b81b6b3SRodney W. Grimes 		return -1;
7575b81b6b3SRodney W. Grimes 	flag = 0;
758ba3551dfSJulian Elischer #ifdef NOT_NOW
7595b81b6b3SRodney W. Grimes 	(void) ioctl(fd, DIOCWLABEL, &flag);
760ba3551dfSJulian Elischer #endif
7615b81b6b3SRodney W. Grimes 	}
7624be1e61bSAlexander Langer 	return(0);
7635b81b6b3SRodney W. Grimes }
7645b81b6b3SRodney W. Grimes 
7655b81b6b3SRodney W. Grimes 
7664be1e61bSAlexander Langer static int
7675b81b6b3SRodney W. Grimes ok(str)
7685b81b6b3SRodney W. Grimes char *str;
7695b81b6b3SRodney W. Grimes {
7705b81b6b3SRodney W. Grimes 	printf("%s [n] ", str);
7715b81b6b3SRodney W. Grimes 	fgets(lbuf, LBUF, stdin);
7725b81b6b3SRodney W. Grimes 	lbuf[strlen(lbuf)-1] = 0;
7735b81b6b3SRodney W. Grimes 
7745b81b6b3SRodney W. Grimes 	if (*lbuf &&
7755b81b6b3SRodney W. Grimes 		(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
7765b81b6b3SRodney W. Grimes 		 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
7775b81b6b3SRodney W. Grimes 		return 1;
7785b81b6b3SRodney W. Grimes 	else
7795b81b6b3SRodney W. Grimes 		return 0;
7805b81b6b3SRodney W. Grimes }
7815b81b6b3SRodney W. Grimes 
7824be1e61bSAlexander Langer static int
7834be1e61bSAlexander Langer decimal(char *str, int *num, int deflt)
7845b81b6b3SRodney W. Grimes {
7855b81b6b3SRodney W. Grimes int acc = 0, c;
7865b81b6b3SRodney W. Grimes char *cp;
7875b81b6b3SRodney W. Grimes 
7885b81b6b3SRodney W. Grimes 	while (1) {
7895b81b6b3SRodney W. Grimes 		printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
7905b81b6b3SRodney W. Grimes 		fgets(lbuf, LBUF, stdin);
7915b81b6b3SRodney W. Grimes 		lbuf[strlen(lbuf)-1] = 0;
7925b81b6b3SRodney W. Grimes 
7935b81b6b3SRodney W. Grimes 		if (!*lbuf)
7945b81b6b3SRodney W. Grimes 			return 0;
7955b81b6b3SRodney W. Grimes 
7965b81b6b3SRodney W. Grimes 		cp = lbuf;
7975b81b6b3SRodney W. Grimes 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
7985b81b6b3SRodney W. Grimes 		if (!c)
7995b81b6b3SRodney W. Grimes 			return 0;
8004be1e61bSAlexander Langer 		while ((c = *cp++)) {
8015b81b6b3SRodney W. Grimes 			if (c <= '9' && c >= '0')
8025b81b6b3SRodney W. Grimes 				acc = acc * 10 + c - '0';
8035b81b6b3SRodney W. Grimes 			else
8045b81b6b3SRodney W. Grimes 				break;
8055b81b6b3SRodney W. Grimes 		}
8065b81b6b3SRodney W. Grimes 		if (c == ' ' || c == '\t')
8075b81b6b3SRodney W. Grimes 			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8085b81b6b3SRodney W. Grimes 		if (!c) {
8095b81b6b3SRodney W. Grimes 			*num = acc;
8105b81b6b3SRodney W. Grimes 			return 1;
8115b81b6b3SRodney W. Grimes 		} else
8125b81b6b3SRodney W. Grimes 			printf("%s is an invalid decimal number.  Try again\n",
8135b81b6b3SRodney W. Grimes 				lbuf);
8145b81b6b3SRodney W. Grimes 	}
8155b81b6b3SRodney W. Grimes 
8165b81b6b3SRodney W. Grimes }
8175b81b6b3SRodney W. Grimes 
8184be1e61bSAlexander Langer #if 0
8194be1e61bSAlexander Langer static int
8204be1e61bSAlexander Langer hex(char *str, int *num, int deflt)
8215b81b6b3SRodney W. Grimes {
8225b81b6b3SRodney W. Grimes int acc = 0, c;
8235b81b6b3SRodney W. Grimes char *cp;
8245b81b6b3SRodney W. Grimes 
8255b81b6b3SRodney W. Grimes 	while (1) {
8265b81b6b3SRodney W. Grimes 		printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
8275b81b6b3SRodney W. Grimes 		fgets(lbuf, LBUF, stdin);
8285b81b6b3SRodney W. Grimes 		lbuf[strlen(lbuf)-1] = 0;
8295b81b6b3SRodney W. Grimes 
8305b81b6b3SRodney W. Grimes 		if (!*lbuf)
8315b81b6b3SRodney W. Grimes 			return 0;
8325b81b6b3SRodney W. Grimes 
8335b81b6b3SRodney W. Grimes 		cp = lbuf;
8345b81b6b3SRodney W. Grimes 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8355b81b6b3SRodney W. Grimes 		if (!c)
8365b81b6b3SRodney W. Grimes 			return 0;
8374be1e61bSAlexander Langer 		while ((c = *cp++)) {
8385b81b6b3SRodney W. Grimes 			if (c <= '9' && c >= '0')
8395b81b6b3SRodney W. Grimes 				acc = (acc << 4) + c - '0';
8405b81b6b3SRodney W. Grimes 			else if (c <= 'f' && c >= 'a')
8415b81b6b3SRodney W. Grimes 				acc = (acc << 4) + c - 'a' + 10;
8425b81b6b3SRodney W. Grimes 			else if (c <= 'F' && c >= 'A')
8435b81b6b3SRodney W. Grimes 				acc = (acc << 4) + c - 'A' + 10;
8445b81b6b3SRodney W. Grimes 			else
8455b81b6b3SRodney W. Grimes 				break;
8465b81b6b3SRodney W. Grimes 		}
8475b81b6b3SRodney W. Grimes 		if (c == ' ' || c == '\t')
8485b81b6b3SRodney W. Grimes 			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8495b81b6b3SRodney W. Grimes 		if (!c) {
8505b81b6b3SRodney W. Grimes 			*num = acc;
8515b81b6b3SRodney W. Grimes 			return 1;
8525b81b6b3SRodney W. Grimes 		} else
8535b81b6b3SRodney W. Grimes 			printf("%s is an invalid hex number.  Try again\n",
8545b81b6b3SRodney W. Grimes 				lbuf);
8555b81b6b3SRodney W. Grimes 	}
8565b81b6b3SRodney W. Grimes 
8575b81b6b3SRodney W. Grimes }
8585b81b6b3SRodney W. Grimes 
8594be1e61bSAlexander Langer static int
8604be1e61bSAlexander Langer string(char *str, char **ans)
8615b81b6b3SRodney W. Grimes {
8625b81b6b3SRodney W. Grimes int c;
8635b81b6b3SRodney W. Grimes char *cp = lbuf;
8645b81b6b3SRodney W. Grimes 
8655b81b6b3SRodney W. Grimes 	while (1) {
8665b81b6b3SRodney W. Grimes 		printf("Supply a string value for \"%s\" [%s] ", str, *ans);
8675b81b6b3SRodney W. Grimes 		fgets(lbuf, LBUF, stdin);
8685b81b6b3SRodney W. Grimes 		lbuf[strlen(lbuf)-1] = 0;
8695b81b6b3SRodney W. Grimes 
8705b81b6b3SRodney W. Grimes 		if (!*lbuf)
8715b81b6b3SRodney W. Grimes 			return 0;
8725b81b6b3SRodney W. Grimes 
8735b81b6b3SRodney W. Grimes 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8745b81b6b3SRodney W. Grimes 		if (c == '"') {
8755b81b6b3SRodney W. Grimes 			c = *++cp;
8765b81b6b3SRodney W. Grimes 			*ans = cp;
8775b81b6b3SRodney W. Grimes 			while ((c = *cp) && c != '"') cp++;
8785b81b6b3SRodney W. Grimes 		} else {
8795b81b6b3SRodney W. Grimes 			*ans = cp;
8805b81b6b3SRodney W. Grimes 			while ((c = *cp) && c != ' ' && c != '\t') cp++;
8815b81b6b3SRodney W. Grimes 		}
8825b81b6b3SRodney W. Grimes 
8835b81b6b3SRodney W. Grimes 		if (c)
8845b81b6b3SRodney W. Grimes 			*cp = 0;
8855b81b6b3SRodney W. Grimes 		return 1;
8865b81b6b3SRodney W. Grimes 	}
8875b81b6b3SRodney W. Grimes }
8884be1e61bSAlexander Langer #endif
8895b81b6b3SRodney W. Grimes 
8904be1e61bSAlexander Langer static char *
8914be1e61bSAlexander Langer get_type(int type)
8925b81b6b3SRodney W. Grimes {
8935b81b6b3SRodney W. Grimes 	int	numentries = (sizeof(part_types)/sizeof(struct part_type));
8945b81b6b3SRodney W. Grimes 	int	counter = 0;
8955b81b6b3SRodney W. Grimes 	struct	part_type *ptr = part_types;
8965b81b6b3SRodney W. Grimes 
8975b81b6b3SRodney W. Grimes 
8985b81b6b3SRodney W. Grimes 	while(counter < numentries)
8995b81b6b3SRodney W. Grimes 	{
9005b81b6b3SRodney W. Grimes 		if(ptr->type == type)
9015b81b6b3SRodney W. Grimes 		{
9025b81b6b3SRodney W. Grimes 			return(ptr->name);
9035b81b6b3SRodney W. Grimes 		}
9045b81b6b3SRodney W. Grimes 		ptr++;
9055b81b6b3SRodney W. Grimes 		counter++;
9065b81b6b3SRodney W. Grimes 	}
9075b81b6b3SRodney W. Grimes 	return("unknown");
9085b81b6b3SRodney W. Grimes }
909f46af505SJordan K. Hubbard 
910f46af505SJordan K. Hubbard 
911f46af505SJordan K. Hubbard static void
912f46af505SJordan K. Hubbard parse_config_line(line, command)
913f46af505SJordan K. Hubbard     char	*line;
914f46af505SJordan K. Hubbard     CMD		*command;
915f46af505SJordan K. Hubbard {
916f46af505SJordan K. Hubbard     char	*cp, *end;
917f46af505SJordan K. Hubbard 
918f46af505SJordan K. Hubbard     cp = line;
919f46af505SJordan K. Hubbard     while (1)	/* dirty trick used to insure one exit point for this
920f46af505SJordan K. Hubbard 		   function */
921f46af505SJordan K. Hubbard     {
922f46af505SJordan K. Hubbard 	memset(command, 0, sizeof(*command));
923f46af505SJordan K. Hubbard 
924f46af505SJordan K. Hubbard 	while (isspace(*cp)) ++cp;
925f46af505SJordan K. Hubbard 	if (*cp == '\0' || *cp == '#')
926f46af505SJordan K. Hubbard 	{
927f46af505SJordan K. Hubbard 	    break;
928f46af505SJordan K. Hubbard 	}
929f46af505SJordan K. Hubbard 	command->cmd = *cp++;
930f46af505SJordan K. Hubbard 
931f46af505SJordan K. Hubbard 	/*
932f46af505SJordan K. Hubbard 	 * Parse args
933f46af505SJordan K. Hubbard 	 */
934f46af505SJordan K. Hubbard 	while (1)
935f46af505SJordan K. Hubbard 	{
936f46af505SJordan K. Hubbard 	    while (isspace(*cp)) ++cp;
937f46af505SJordan K. Hubbard 	    if (*cp == '#')
938f46af505SJordan K. Hubbard 	    {
939f46af505SJordan K. Hubbard 		break;		/* found comment */
940f46af505SJordan K. Hubbard 	    }
941f46af505SJordan K. Hubbard 	    if (isalpha(*cp))
942f46af505SJordan K. Hubbard 	    {
943f46af505SJordan K. Hubbard 		command->args[command->n_args].argtype = *cp++;
944f46af505SJordan K. Hubbard 	    }
945f46af505SJordan K. Hubbard 	    if (!isdigit(*cp))
946f46af505SJordan K. Hubbard 	    {
947f46af505SJordan K. Hubbard 		break;		/* assume end of line */
948f46af505SJordan K. Hubbard 	    }
949f46af505SJordan K. Hubbard 	    end = NULL;
950f46af505SJordan K. Hubbard 	    command->args[command->n_args].arg_val = strtol(cp, &end, 0);
951f46af505SJordan K. Hubbard 	    if (cp == end)
952f46af505SJordan K. Hubbard 	    {
953f46af505SJordan K. Hubbard 		break;		/* couldn't parse number */
954f46af505SJordan K. Hubbard 	    }
955f46af505SJordan K. Hubbard 	    cp = end;
956f46af505SJordan K. Hubbard 	    command->n_args++;
957f46af505SJordan K. Hubbard 	}
958f46af505SJordan K. Hubbard 	break;
959f46af505SJordan K. Hubbard     }
960f46af505SJordan K. Hubbard }
961f46af505SJordan K. Hubbard 
962f46af505SJordan K. Hubbard 
963f46af505SJordan K. Hubbard static int
964f46af505SJordan K. Hubbard process_geometry(command)
965f46af505SJordan K. Hubbard     CMD		*command;
966f46af505SJordan K. Hubbard {
967f46af505SJordan K. Hubbard     int		status = 1, i;
968f46af505SJordan K. Hubbard 
969f46af505SJordan K. Hubbard     while (1)
970f46af505SJordan K. Hubbard     {
971f46af505SJordan K. Hubbard 	geom_processed = 1;
972f46af505SJordan K. Hubbard 	if (part_processed)
973f46af505SJordan K. Hubbard 	{
974f46af505SJordan K. Hubbard 	    fprintf(stderr,
975f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: the geometry specification line must occur before\n\
976f46af505SJordan K. Hubbard     all partition specifications.\n",
977f46af505SJordan K. Hubbard 		    name, current_line_number);
978f46af505SJordan K. Hubbard 	    status = 0;
979f46af505SJordan K. Hubbard 	    break;
980f46af505SJordan K. Hubbard 	}
981f46af505SJordan K. Hubbard 	if (command->n_args != 3)
982f46af505SJordan K. Hubbard 	{
983f46af505SJordan K. Hubbard 	    fprintf(stderr,
984f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: incorrect number of geometry args\n",
985f46af505SJordan K. Hubbard 		    name, current_line_number);
986f46af505SJordan K. Hubbard 	    status = 0;
987f46af505SJordan K. Hubbard 	    break;
988f46af505SJordan K. Hubbard 	}
989f46af505SJordan K. Hubbard 	dos_cyls = -1;
990f46af505SJordan K. Hubbard 	dos_heads = -1;
991f46af505SJordan K. Hubbard 	dos_sectors = -1;
992f46af505SJordan K. Hubbard 	for (i = 0; i < 3; ++i)
993f46af505SJordan K. Hubbard 	{
994f46af505SJordan K. Hubbard 	    switch (command->args[i].argtype)
995f46af505SJordan K. Hubbard 	    {
996f46af505SJordan K. Hubbard 	    case 'c':
997f46af505SJordan K. Hubbard 		dos_cyls = command->args[i].arg_val;
998f46af505SJordan K. Hubbard 		break;
999f46af505SJordan K. Hubbard 	    case 'h':
1000f46af505SJordan K. Hubbard 		dos_heads = command->args[i].arg_val;
1001f46af505SJordan K. Hubbard 		break;
1002f46af505SJordan K. Hubbard 	    case 's':
1003f46af505SJordan K. Hubbard 		dos_sectors = command->args[i].arg_val;
1004f46af505SJordan K. Hubbard 		break;
1005f46af505SJordan K. Hubbard 	    default:
1006f46af505SJordan K. Hubbard 		fprintf(stderr,
1007f46af505SJordan K. Hubbard 			"%s: ERROR line %d: unknown geometry arg type: '%c' (0x%02x)\n",
1008f46af505SJordan K. Hubbard 			name, current_line_number, command->args[i].argtype,
1009f46af505SJordan K. Hubbard 			command->args[i].argtype);
1010f46af505SJordan K. Hubbard 		status = 0;
1011f46af505SJordan K. Hubbard 		break;
1012f46af505SJordan K. Hubbard 	    }
1013f46af505SJordan K. Hubbard 	}
1014f46af505SJordan K. Hubbard 	if (status == 0)
1015f46af505SJordan K. Hubbard 	{
1016f46af505SJordan K. Hubbard 	    break;
1017f46af505SJordan K. Hubbard 	}
1018f46af505SJordan K. Hubbard 
1019f46af505SJordan K. Hubbard 	dos_cylsecs = dos_heads * dos_sectors;
1020f46af505SJordan K. Hubbard 
1021f46af505SJordan K. Hubbard 	/*
1022f46af505SJordan K. Hubbard 	 * Do sanity checks on parameter values
1023f46af505SJordan K. Hubbard 	 */
1024f46af505SJordan K. Hubbard 	if (dos_cyls < 0)
1025f46af505SJordan K. Hubbard 	{
1026f46af505SJordan K. Hubbard 	    fprintf(stderr,
1027f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: number of cylinders not specified\n",
1028f46af505SJordan K. Hubbard 		    name, current_line_number);
1029f46af505SJordan K. Hubbard 	    status = 0;
1030f46af505SJordan K. Hubbard 	}
1031f46af505SJordan K. Hubbard 	if (dos_cyls == 0 || dos_cyls > 1024)
1032f46af505SJordan K. Hubbard 	{
1033f46af505SJordan K. Hubbard 	    fprintf(stderr,
1034f46af505SJordan K. Hubbard 		    "%s: WARNING line %d: number of cylinders (%d) may be out-of-range\n\
1035f46af505SJordan K. Hubbard     (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\
1036f46af505SJordan K. Hubbard     is dedicated to FreeBSD).\n",
1037f46af505SJordan K. Hubbard 		    name, current_line_number, dos_cyls);
1038f46af505SJordan K. Hubbard 	}
1039f46af505SJordan K. Hubbard 
1040f46af505SJordan K. Hubbard 	if (dos_heads < 0)
1041f46af505SJordan K. Hubbard 	{
1042f46af505SJordan K. Hubbard 	    fprintf(stderr,
1043f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: number of heads not specified\n",
1044f46af505SJordan K. Hubbard 		    name, current_line_number);
1045f46af505SJordan K. Hubbard 	    status = 0;
1046f46af505SJordan K. Hubbard 	}
1047f46af505SJordan K. Hubbard 	else if (dos_heads < 1 || dos_heads > 256)
1048f46af505SJordan K. Hubbard 	{
1049f46af505SJordan K. Hubbard 	    fprintf(stderr,
1050f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: number of heads must be within (1-256)\n",
1051f46af505SJordan K. Hubbard 		    name, current_line_number);
1052f46af505SJordan K. Hubbard 	    status = 0;
1053f46af505SJordan K. Hubbard 	}
1054f46af505SJordan K. Hubbard 
1055f46af505SJordan K. Hubbard 	if (dos_sectors < 0)
1056f46af505SJordan K. Hubbard 	{
1057f46af505SJordan K. Hubbard 	    fprintf(stderr, "%s: ERROR line %d: number of sectors not specified\n",
1058f46af505SJordan K. Hubbard 		    name, current_line_number);
1059f46af505SJordan K. Hubbard 	    status = 0;
1060f46af505SJordan K. Hubbard 	}
1061f46af505SJordan K. Hubbard 	else if (dos_sectors < 1 || dos_sectors > 63)
1062f46af505SJordan K. Hubbard 	{
1063f46af505SJordan K. Hubbard 	    fprintf(stderr,
1064f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: number of sectors must be within (1-63)\n",
1065f46af505SJordan K. Hubbard 		    name, current_line_number);
1066f46af505SJordan K. Hubbard 	    status = 0;
1067f46af505SJordan K. Hubbard 	}
1068f46af505SJordan K. Hubbard 
1069f46af505SJordan K. Hubbard 	break;
1070f46af505SJordan K. Hubbard     }
1071f46af505SJordan K. Hubbard     return (status);
1072f46af505SJordan K. Hubbard }
1073f46af505SJordan K. Hubbard 
1074f46af505SJordan K. Hubbard 
1075f46af505SJordan K. Hubbard static int
1076f46af505SJordan K. Hubbard process_partition(command)
1077f46af505SJordan K. Hubbard     CMD		*command;
1078f46af505SJordan K. Hubbard {
1079f46af505SJordan K. Hubbard     int				status = 0, partition;
1080f46af505SJordan K. Hubbard     unsigned long		chunks, adj_size, max_end;
1081f46af505SJordan K. Hubbard     struct dos_partition	*partp;
1082f46af505SJordan K. Hubbard 
1083f46af505SJordan K. Hubbard     while (1)
1084f46af505SJordan K. Hubbard     {
1085f46af505SJordan K. Hubbard 	part_processed = 1;
1086f46af505SJordan K. Hubbard 	if (command->n_args != 4)
1087f46af505SJordan K. Hubbard 	{
1088f46af505SJordan K. Hubbard 	    fprintf(stderr,
1089f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: incorrect number of partition args\n",
1090f46af505SJordan K. Hubbard 		    name, current_line_number);
1091f46af505SJordan K. Hubbard 	    break;
1092f46af505SJordan K. Hubbard 	}
1093f46af505SJordan K. Hubbard 	partition = command->args[0].arg_val;
10944ddd60b9SBrian Somers 	if (partition < 1 || partition > 4)
1095f46af505SJordan K. Hubbard 	{
1096f46af505SJordan K. Hubbard 	    fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n",
1097f46af505SJordan K. Hubbard 		    name, current_line_number, partition);
1098f46af505SJordan K. Hubbard 	    break;
1099f46af505SJordan K. Hubbard 	}
11004ddd60b9SBrian Somers 	partp = ((struct dos_partition *) &mboot.parts) + partition - 1;
1101f46af505SJordan K. Hubbard 	bzero((char *)partp, sizeof (struct dos_partition));
1102f46af505SJordan K. Hubbard 	partp->dp_typ = command->args[1].arg_val;
1103f46af505SJordan K. Hubbard 	partp->dp_start = command->args[2].arg_val;
1104f46af505SJordan K. Hubbard 	partp->dp_size = command->args[3].arg_val;
1105f46af505SJordan K. Hubbard 	max_end = partp->dp_start + partp->dp_size;
1106f46af505SJordan K. Hubbard 
1107f46af505SJordan K. Hubbard 	if (partp->dp_typ == 0)
1108f46af505SJordan K. Hubbard 	{
1109f46af505SJordan K. Hubbard 	    /*
1110f46af505SJordan K. Hubbard 	     * Get out, the partition is marked as unused.
1111f46af505SJordan K. Hubbard 	     */
1112f46af505SJordan K. Hubbard 	    /*
1113f46af505SJordan K. Hubbard 	     * Insure that it's unused.
1114f46af505SJordan K. Hubbard 	     */
1115f46af505SJordan K. Hubbard 	    bzero((char *)partp, sizeof (struct dos_partition));
1116f46af505SJordan K. Hubbard 	    status = 1;
1117f46af505SJordan K. Hubbard 	    break;
1118f46af505SJordan K. Hubbard 	}
1119f46af505SJordan K. Hubbard 
1120f46af505SJordan K. Hubbard 	/*
1121f46af505SJordan K. Hubbard 	 * Adjust start upwards, if necessary, to fall on an head boundary.
1122f46af505SJordan K. Hubbard 	 */
1123f46af505SJordan K. Hubbard 	if (partp->dp_start % dos_sectors != 0)
1124f46af505SJordan K. Hubbard 	{
1125f46af505SJordan K. Hubbard 	    adj_size =
1126f46af505SJordan K. Hubbard 		(partp->dp_start / dos_sectors + 1) * dos_sectors;
1127f46af505SJordan K. Hubbard 	    if (adj_size > max_end)
1128f46af505SJordan K. Hubbard 	    {
1129f46af505SJordan K. Hubbard 		/*
1130f46af505SJordan K. Hubbard 		 * Can't go past end of partition
1131f46af505SJordan K. Hubbard 		 */
1132f46af505SJordan K. Hubbard 		fprintf(stderr,
1133f46af505SJordan K. Hubbard 			"%s: ERROR line %d: unable to adjust start of partition %d to fall on\n\
1134f46af505SJordan K. Hubbard     a cylinder boundary.\n",
1135f46af505SJordan K. Hubbard 			name, current_line_number, partition);
1136f46af505SJordan K. Hubbard 		break;
1137f46af505SJordan K. Hubbard 	    }
1138f46af505SJordan K. Hubbard 	    fprintf(stderr,
1139f46af505SJordan K. Hubbard 		    "%s: WARNING: adjusting start offset of partition '%d' from %d\n\
1140f46af505SJordan K. Hubbard     to %d, to round to an head boundary.\n",
1141f46af505SJordan K. Hubbard 		    name, partition, partp->dp_start, adj_size);
1142f46af505SJordan K. Hubbard 	    partp->dp_start = adj_size;
1143f46af505SJordan K. Hubbard 	}
1144f46af505SJordan K. Hubbard 
1145f46af505SJordan K. Hubbard 	/*
1146f46af505SJordan K. Hubbard 	 * Adjust size downwards, if necessary, to fall on a cylinder
1147f46af505SJordan K. Hubbard 	 * boundary.
1148f46af505SJordan K. Hubbard 	 */
1149f46af505SJordan K. Hubbard 	chunks =
1150f46af505SJordan K. Hubbard 	    ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs;
1151f46af505SJordan K. Hubbard 	adj_size = chunks - partp->dp_start;
1152f46af505SJordan K. Hubbard 	if (adj_size != partp->dp_size)
1153f46af505SJordan K. Hubbard 	{
1154f46af505SJordan K. Hubbard 	    fprintf(stderr,
1155f46af505SJordan K. Hubbard 		    "%s: WARNING: adjusting size of partition '%d' from %d to %d,\n\
1156f46af505SJordan K. Hubbard     to round to a cylinder boundary.\n",
1157f46af505SJordan K. Hubbard 		    name, partition, partp->dp_size, adj_size);
1158f46af505SJordan K. Hubbard 	    if (chunks > 0)
1159f46af505SJordan K. Hubbard 	    {
1160f46af505SJordan K. Hubbard 		partp->dp_size = adj_size;
1161f46af505SJordan K. Hubbard 	    }
1162f46af505SJordan K. Hubbard 	    else
1163f46af505SJordan K. Hubbard 	    {
1164f46af505SJordan K. Hubbard 		partp->dp_size = 0;
1165f46af505SJordan K. Hubbard 	    }
1166f46af505SJordan K. Hubbard 	}
1167f46af505SJordan K. Hubbard 	if (partp->dp_size < 1)
1168f46af505SJordan K. Hubbard 	{
1169f46af505SJordan K. Hubbard 	    fprintf(stderr,
1170f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: size for partition '%d' is zero.\n",
1171f46af505SJordan K. Hubbard 		    name, current_line_number, partition);
1172f46af505SJordan K. Hubbard 	    break;
1173f46af505SJordan K. Hubbard 	}
1174f46af505SJordan K. Hubbard 
1175f46af505SJordan K. Hubbard 	dos(partp->dp_start, partp->dp_size,
1176f46af505SJordan K. Hubbard 	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
1177f46af505SJordan K. Hubbard 	dos(partp->dp_start+partp->dp_size - 1, partp->dp_size,
1178f46af505SJordan K. Hubbard 	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
1179f46af505SJordan K. Hubbard 	status = 1;
1180f46af505SJordan K. Hubbard 	break;
1181f46af505SJordan K. Hubbard     }
1182f46af505SJordan K. Hubbard     return (status);
1183f46af505SJordan K. Hubbard }
1184f46af505SJordan K. Hubbard 
1185f46af505SJordan K. Hubbard 
1186f46af505SJordan K. Hubbard static int
1187f46af505SJordan K. Hubbard process_active(command)
1188f46af505SJordan K. Hubbard     CMD		*command;
1189f46af505SJordan K. Hubbard {
1190f46af505SJordan K. Hubbard     int				status = 0, partition, i;
1191f46af505SJordan K. Hubbard     struct dos_partition	*partp;
1192f46af505SJordan K. Hubbard 
1193f46af505SJordan K. Hubbard     while (1)
1194f46af505SJordan K. Hubbard     {
1195f46af505SJordan K. Hubbard 	active_processed = 1;
1196f46af505SJordan K. Hubbard 	if (command->n_args != 1)
1197f46af505SJordan K. Hubbard 	{
1198f46af505SJordan K. Hubbard 	    fprintf(stderr,
1199f46af505SJordan K. Hubbard 		    "%s: ERROR line %d: incorrect number of active args\n",
1200f46af505SJordan K. Hubbard 		    name, current_line_number);
1201f46af505SJordan K. Hubbard 	    status = 0;
1202f46af505SJordan K. Hubbard 	    break;
1203f46af505SJordan K. Hubbard 	}
1204f46af505SJordan K. Hubbard 	partition = command->args[0].arg_val;
12054ddd60b9SBrian Somers 	if (partition < 1 || partition > 4)
1206f46af505SJordan K. Hubbard 	{
1207f46af505SJordan K. Hubbard 	    fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n",
1208f46af505SJordan K. Hubbard 		    name, current_line_number, partition);
1209f46af505SJordan K. Hubbard 	    break;
1210f46af505SJordan K. Hubbard 	}
1211f46af505SJordan K. Hubbard 	/*
1212f46af505SJordan K. Hubbard 	 * Reset active partition
1213f46af505SJordan K. Hubbard 	 */
1214f46af505SJordan K. Hubbard 	partp = ((struct dos_partition *) &mboot.parts);
1215f46af505SJordan K. Hubbard 	for (i = 0; i < NDOSPART; i++)
1216f46af505SJordan K. Hubbard 	    partp[i].dp_flag = 0;
12174ddd60b9SBrian Somers 	partp[partition-1].dp_flag = ACTIVE;
1218f46af505SJordan K. Hubbard 
1219f46af505SJordan K. Hubbard 	status = 1;
1220f46af505SJordan K. Hubbard 	break;
1221f46af505SJordan K. Hubbard     }
1222f46af505SJordan K. Hubbard     return (status);
1223f46af505SJordan K. Hubbard }
1224f46af505SJordan K. Hubbard 
1225f46af505SJordan K. Hubbard 
1226f46af505SJordan K. Hubbard static int
1227f46af505SJordan K. Hubbard process_line(line)
1228f46af505SJordan K. Hubbard     char	*line;
1229f46af505SJordan K. Hubbard {
1230f46af505SJordan K. Hubbard     CMD		command;
1231f46af505SJordan K. Hubbard     int		status = 1;
1232f46af505SJordan K. Hubbard 
1233f46af505SJordan K. Hubbard     while (1)
1234f46af505SJordan K. Hubbard     {
1235f46af505SJordan K. Hubbard 	parse_config_line(line, &command);
1236f46af505SJordan K. Hubbard 	switch (command.cmd)
1237f46af505SJordan K. Hubbard 	{
1238f46af505SJordan K. Hubbard 	case 0:
1239f46af505SJordan K. Hubbard 	    /*
1240f46af505SJordan K. Hubbard 	     * Comment or blank line
1241f46af505SJordan K. Hubbard 	     */
1242f46af505SJordan K. Hubbard 	    break;
1243f46af505SJordan K. Hubbard 	case 'g':
1244f46af505SJordan K. Hubbard 	    /*
1245f46af505SJordan K. Hubbard 	     * Set geometry
1246f46af505SJordan K. Hubbard 	     */
1247f46af505SJordan K. Hubbard 	    status = process_geometry(&command);
1248f46af505SJordan K. Hubbard 	    break;
1249f46af505SJordan K. Hubbard 	case 'p':
1250f46af505SJordan K. Hubbard 	    status = process_partition(&command);
1251f46af505SJordan K. Hubbard 	    break;
1252f46af505SJordan K. Hubbard 	case 'a':
1253f46af505SJordan K. Hubbard 	    status = process_active(&command);
1254f46af505SJordan K. Hubbard 	    break;
1255f46af505SJordan K. Hubbard 	default:
1256f46af505SJordan K. Hubbard 	    status = 0;
1257f46af505SJordan K. Hubbard 	    break;
1258f46af505SJordan K. Hubbard 	}
1259f46af505SJordan K. Hubbard 	break;
1260f46af505SJordan K. Hubbard     }
1261f46af505SJordan K. Hubbard     return (status);
1262f46af505SJordan K. Hubbard }
1263f46af505SJordan K. Hubbard 
1264f46af505SJordan K. Hubbard 
1265f46af505SJordan K. Hubbard static int
1266f46af505SJordan K. Hubbard read_config(config_file)
1267f46af505SJordan K. Hubbard     char *config_file;
1268f46af505SJordan K. Hubbard {
1269f46af505SJordan K. Hubbard     FILE	*fp = NULL;
1270f46af505SJordan K. Hubbard     int		status = 1;
1271f46af505SJordan K. Hubbard     char	buf[1010];
1272f46af505SJordan K. Hubbard 
1273f46af505SJordan K. Hubbard     while (1)	/* dirty trick used to insure one exit point for this
1274f46af505SJordan K. Hubbard 		   function */
1275f46af505SJordan K. Hubbard     {
1276f46af505SJordan K. Hubbard 	if (strcmp(config_file, "-") != 0)
1277f46af505SJordan K. Hubbard 	{
1278f46af505SJordan K. Hubbard 	    /*
1279f46af505SJordan K. Hubbard 	     * We're not reading from stdin
1280f46af505SJordan K. Hubbard 	     */
1281f46af505SJordan K. Hubbard 	    if ((fp = fopen(config_file, "r")) == NULL)
1282f46af505SJordan K. Hubbard 	    {
1283f46af505SJordan K. Hubbard 		status = 0;
1284f46af505SJordan K. Hubbard 		break;
1285f46af505SJordan K. Hubbard 	    }
1286f46af505SJordan K. Hubbard 	}
1287f46af505SJordan K. Hubbard 	else
1288f46af505SJordan K. Hubbard 	{
1289f46af505SJordan K. Hubbard 	    fp = stdin;
1290f46af505SJordan K. Hubbard 	}
1291f46af505SJordan K. Hubbard 	current_line_number = 0;
1292f46af505SJordan K. Hubbard 	while (!feof(fp))
1293f46af505SJordan K. Hubbard 	{
1294f46af505SJordan K. Hubbard 	    if (fgets(buf, sizeof(buf), fp) == NULL)
1295f46af505SJordan K. Hubbard 	    {
1296f46af505SJordan K. Hubbard 		break;
1297f46af505SJordan K. Hubbard 	    }
1298f46af505SJordan K. Hubbard 	    ++current_line_number;
1299f46af505SJordan K. Hubbard 	    status = process_line(buf);
1300f46af505SJordan K. Hubbard 	    if (status == 0)
1301f46af505SJordan K. Hubbard 	    {
1302f46af505SJordan K. Hubbard 		break;
1303f46af505SJordan K. Hubbard 	    }
1304f46af505SJordan K. Hubbard 	}
1305f46af505SJordan K. Hubbard 	break;
1306f46af505SJordan K. Hubbard     }
1307f46af505SJordan K. Hubbard     if (fp)
1308f46af505SJordan K. Hubbard     {
1309f46af505SJordan K. Hubbard 	/*
1310f46af505SJordan K. Hubbard 	 * It doesn't matter if we're reading from stdin, as we've reached EOF
1311f46af505SJordan K. Hubbard 	 */
1312f46af505SJordan K. Hubbard 	fclose(fp);
1313f46af505SJordan K. Hubbard     }
1314f46af505SJordan K. Hubbard     return (status);
1315f46af505SJordan K. Hubbard }
1316f46af505SJordan K. Hubbard 
1317f46af505SJordan K. Hubbard 
1318f46af505SJordan K. Hubbard static void
1319f46af505SJordan K. Hubbard reset_boot(void)
1320f46af505SJordan K. Hubbard {
1321f46af505SJordan K. Hubbard     int				i;
1322f46af505SJordan K. Hubbard     struct dos_partition	*partp;
1323f46af505SJordan K. Hubbard 
1324f46af505SJordan K. Hubbard     init_boot();
1325f46af505SJordan K. Hubbard     for (i = 0; i < 4; ++i)
1326f46af505SJordan K. Hubbard     {
1327f46af505SJordan K. Hubbard 	partp = ((struct dos_partition *) &mboot.parts) + i;
1328f46af505SJordan K. Hubbard 	bzero((char *)partp, sizeof (struct dos_partition));
1329f46af505SJordan K. Hubbard     }
1330f46af505SJordan K. Hubbard }
1331