xref: /freebsd/sbin/fdisk/fdisk.c (revision 698b4def3f559aae45195e06ced20aee40cea238)
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 
27d98b1668SPhilippe Charnier #ifndef lint
28d98b1668SPhilippe Charnier static const char rcsid[] =
29698b4defSJoerg Wunsch 	"$Id: fdisk.c,v 1.26 1998/11/06 03:43:21 alex Exp $";
30d98b1668SPhilippe Charnier #endif /* not lint */
31d98b1668SPhilippe Charnier 
325b81b6b3SRodney W. Grimes #include <sys/disklabel.h>
335b81b6b3SRodney W. Grimes #include <sys/stat.h>
34d98b1668SPhilippe Charnier #include <ctype.h>
355b81b6b3SRodney W. Grimes #include <fcntl.h>
36d98b1668SPhilippe Charnier #include <err.h>
37d98b1668SPhilippe Charnier #include <errno.h>
38d98b1668SPhilippe Charnier #include <stdio.h>
39d98b1668SPhilippe Charnier #include <stdlib.h>
40d98b1668SPhilippe Charnier #include <string.h>
414be1e61bSAlexander Langer #include <unistd.h>
425b81b6b3SRodney W. Grimes 
435b81b6b3SRodney W. Grimes int iotest;
445b81b6b3SRodney W. Grimes 
455b81b6b3SRodney W. Grimes #define LBUF 100
465b81b6b3SRodney W. Grimes static char lbuf[LBUF];
475b81b6b3SRodney W. Grimes 
485b81b6b3SRodney W. Grimes /*
495b81b6b3SRodney W. Grimes  *
505b81b6b3SRodney W. Grimes  * Ported to 386bsd by Julian Elischer  Thu Oct 15 20:26:46 PDT 1992
515b81b6b3SRodney W. Grimes  *
525b81b6b3SRodney W. Grimes  * 14-Dec-89  Robert Baron (rvb) at Carnegie-Mellon University
535b81b6b3SRodney W. Grimes  *	Copyright (c) 1989	Robert. V. Baron
545b81b6b3SRodney W. Grimes  *	Created.
555b81b6b3SRodney W. Grimes  */
565b81b6b3SRodney W. Grimes 
575b81b6b3SRodney W. Grimes #define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
585b81b6b3SRodney W. Grimes #define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
595b81b6b3SRodney W. Grimes #define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
605b81b6b3SRodney W. Grimes 
615b81b6b3SRodney W. Grimes #define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
625b81b6b3SRodney W. Grimes 
637cb29d33SSøren Schmidt #define MAX_SEC_SIZE 2048	/* maximum section size that is supported */
647cb29d33SSøren Schmidt #define MIN_SEC_SIZE 512	/* the sector size to start sensing at */
657cb29d33SSøren Schmidt int secsize = 0;		/* the sensed sector size */
665b81b6b3SRodney W. Grimes 
67e3038c6eSJoerg Wunsch const char *disk;
68e3038c6eSJoerg Wunsch const char *disks[] =
69e3038c6eSJoerg Wunsch {
70698b4defSJoerg Wunsch   "/dev/rwd0", "/dev/rda0", "/dev/rod0", 0
71e3038c6eSJoerg Wunsch };
72e3038c6eSJoerg Wunsch 
735b81b6b3SRodney W. Grimes struct disklabel disklabel;		/* disk parameters */
745b81b6b3SRodney W. Grimes 
755b81b6b3SRodney W. Grimes int cyls, sectors, heads, cylsecs, disksecs;
765b81b6b3SRodney W. Grimes 
775b81b6b3SRodney W. Grimes struct mboot
785b81b6b3SRodney W. Grimes {
79d98b1668SPhilippe Charnier 	unsigned char padding[2]; /* force the longs to be long aligned */
805b81b6b3SRodney W. Grimes 	unsigned char bootinst[DOSPARTOFF];
815b81b6b3SRodney W. Grimes 	struct	dos_partition parts[4];
825b81b6b3SRodney W. Grimes 	unsigned short int	signature;
837cb29d33SSøren Schmidt 	/* room to read in MBRs that are bigger then DEV_BSIZE */
847cb29d33SSøren Schmidt 	unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE];
855b81b6b3SRodney W. Grimes };
865b81b6b3SRodney W. Grimes struct mboot mboot;
875b81b6b3SRodney W. Grimes 
885b81b6b3SRodney W. Grimes #define ACTIVE 0x80
895b81b6b3SRodney W. Grimes #define BOOT_MAGIC 0xAA55
905b81b6b3SRodney W. Grimes 
915b81b6b3SRodney W. Grimes int dos_cyls;
925b81b6b3SRodney W. Grimes int dos_heads;
935b81b6b3SRodney W. Grimes int dos_sectors;
945b81b6b3SRodney W. Grimes int dos_cylsecs;
955b81b6b3SRodney W. Grimes 
965b81b6b3SRodney W. Grimes #define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
975b81b6b3SRodney W. Grimes #define DOSCYL(c)	(c & 0xff)
985b81b6b3SRodney W. Grimes static int partition = -1;
995b81b6b3SRodney W. Grimes 
1005b81b6b3SRodney W. Grimes 
101f46af505SJordan K. Hubbard #define MAX_ARGS	10
102f46af505SJordan K. Hubbard 
103f46af505SJordan K. Hubbard static int	current_line_number;
104f46af505SJordan K. Hubbard 
105f46af505SJordan K. Hubbard static int	geom_processed = 0;
106f46af505SJordan K. Hubbard static int	part_processed = 0;
107f46af505SJordan K. Hubbard static int	active_processed = 0;
108f46af505SJordan K. Hubbard 
109f46af505SJordan K. Hubbard 
110f46af505SJordan K. Hubbard typedef struct cmd {
111f46af505SJordan K. Hubbard     char		cmd;
112f46af505SJordan K. Hubbard     int			n_args;
113f46af505SJordan K. Hubbard     struct arg {
114f46af505SJordan K. Hubbard 	char	argtype;
115f46af505SJordan K. Hubbard 	int	arg_val;
116f46af505SJordan K. Hubbard     }			args[MAX_ARGS];
117f46af505SJordan K. Hubbard } CMD;
118f46af505SJordan K. Hubbard 
119f46af505SJordan K. Hubbard 
1205b81b6b3SRodney W. Grimes static int a_flag  = 0;		/* set active partition */
1215b81b6b3SRodney W. Grimes static int i_flag  = 0;		/* replace partition data */
1225b81b6b3SRodney W. Grimes static int u_flag  = 0;		/* update partition data */
123f46af505SJordan K. Hubbard static int t_flag  = 0;		/* test only, if f_flag is given */
124f46af505SJordan K. Hubbard static char *f_flag = NULL;	/* Read config info from file */
125f46af505SJordan K. Hubbard static int v_flag  = 0;		/* Be verbose */
1265b81b6b3SRodney W. Grimes 
1275b81b6b3SRodney W. Grimes static unsigned char bootcode[] = {
1285b81b6b3SRodney W. Grimes 0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
1295b81b6b3SRodney W. Grimes 0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
1305b81b6b3SRodney W. Grimes 0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
1315b81b6b3SRodney W. Grimes 0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
1325b81b6b3SRodney W. Grimes 0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
1335b81b6b3SRodney W. Grimes 0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
1345b81b6b3SRodney W. Grimes 0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
1355b81b6b3SRodney W. Grimes 0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
1365b81b6b3SRodney W. Grimes 0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
1375b81b6b3SRodney W. Grimes 'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
1385b81b6b3SRodney W. Grimes 	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
1395b81b6b3SRodney W. Grimes 'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
1405b81b6b3SRodney W. Grimes 	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
1415b81b6b3SRodney W. Grimes 'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
1425b81b6b3SRodney W. Grimes 	'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
1435b81b6b3SRodney W. Grimes 'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
1445b81b6b3SRodney W. Grimes 	'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
1455b81b6b3SRodney W. Grimes 
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,   0,   0,
1555b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1565b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1575b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1585b81b6b3SRodney W. Grimes   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
1595b81b6b3SRodney W. Grimes };
1605b81b6b3SRodney W. Grimes 
1615b81b6b3SRodney W. Grimes struct part_type
1625b81b6b3SRodney W. Grimes {
1635b81b6b3SRodney W. Grimes  unsigned char type;
1645b81b6b3SRodney W. Grimes  char *name;
1655b81b6b3SRodney W. Grimes }part_types[] =
1665b81b6b3SRodney W. Grimes {
1675b81b6b3SRodney W. Grimes 	 {0x00, "unused"}
1685b81b6b3SRodney W. Grimes 	,{0x01, "Primary DOS with 12 bit FAT"}
1695b81b6b3SRodney W. Grimes 	,{0x02, "XENIX / filesystem"}
1705b81b6b3SRodney W. Grimes 	,{0x03, "XENIX /usr filesystem"}
17126555b64SAndrey A. Chernov 	,{0x04, "Primary DOS with 16 bit FAT (<= 32MB)"}
1725b81b6b3SRodney W. Grimes 	,{0x05, "Extended DOS"}
1735b81b6b3SRodney W. Grimes 	,{0x06, "Primary 'big' DOS (> 32MB)"}
174680426beSDavid E. O'Brien 	,{0x07, "OS/2 HPFS, NTFS, QNX or Advanced UNIX"}
1755b81b6b3SRodney W. Grimes 	,{0x08, "AIX filesystem"}
1765b81b6b3SRodney W. Grimes 	,{0x09, "AIX boot partition or Coherent"}
1775b81b6b3SRodney W. Grimes 	,{0x0A, "OS/2 Boot Manager or OPUS"}
17826555b64SAndrey A. Chernov 	,{0x0B, "DOS or Windows 95 with 32 bit FAT"}
17926555b64SAndrey A. Chernov 	,{0x0C, "DOS or Windows 95 with 32 bit FAT, LBA"}
18026555b64SAndrey A. Chernov 	,{0x0E, "Primary 'big' DOS (> 32MB, LBA)"}
18126555b64SAndrey A. Chernov 	,{0x0F, "Extended DOS, LBA"}
1825b81b6b3SRodney W. Grimes 	,{0x10, "OPUS"}
1835b81b6b3SRodney W. Grimes 	,{0x40, "VENIX 286"}
1845b81b6b3SRodney W. Grimes 	,{0x50, "DM"}
1855b81b6b3SRodney W. Grimes 	,{0x51, "DM"}
1865b81b6b3SRodney W. Grimes 	,{0x52, "CP/M or Microport SysV/AT"}
1875b81b6b3SRodney W. Grimes 	,{0x56, "GB"}
1885b81b6b3SRodney W. Grimes 	,{0x61, "Speed"}
1895b81b6b3SRodney W. Grimes 	,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
1905b81b6b3SRodney W. Grimes 	,{0x64, "Novell Netware 2.xx"}
1915b81b6b3SRodney W. Grimes 	,{0x65, "Novell Netware 3.xx"}
1925b81b6b3SRodney W. Grimes 	,{0x75, "PCIX"}
1935b81b6b3SRodney W. Grimes 	,{0x80, "Minix 1.1 ... 1.4a"}
1945b81b6b3SRodney W. Grimes 	,{0x81, "Minix 1.4b ... 1.5.10"}
19563ab6f1cSDavid E. O'Brien 	,{0x82, "Linux swap or Solaris x86"}
19649f7c177SJordan K. Hubbard 	,{0x83, "Linux filesystem"}
1975b81b6b3SRodney W. Grimes 	,{0x93, "Amoeba filesystem"}
1985b81b6b3SRodney W. Grimes 	,{0x94, "Amoeba bad block table"}
199d1b7313fSJoseph Koshy 	,{0x9F, "BSD/OS"}
20049f7c177SJordan K. Hubbard 	,{0xA5, "FreeBSD/NetBSD/386BSD"}
201e37a137dSWarner Losh 	,{0xA6, "OpenBSD"}
2025f0c9424SGary Palmer 	,{0xA7, "NEXTSTEP"}
203ef80de33SAlexander Langer 	,{0xA9, "NetBSD"}
2045b81b6b3SRodney W. Grimes 	,{0xB7, "BSDI BSD/386 filesystem"}
2055b81b6b3SRodney W. Grimes 	,{0xB8, "BSDI BSD/386 swap"}
2065b81b6b3SRodney W. Grimes 	,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
2075b81b6b3SRodney W. Grimes 	,{0xE1, "Speed"}
2085b81b6b3SRodney W. Grimes 	,{0xE3, "Speed"}
2095b81b6b3SRodney W. Grimes 	,{0xE4, "Speed"}
2105b81b6b3SRodney W. Grimes 	,{0xF1, "Speed"}
2115b81b6b3SRodney W. Grimes 	,{0xF2, "DOS 3.3+ Secondary"}
2125b81b6b3SRodney W. Grimes 	,{0xF4, "Speed"}
2135b81b6b3SRodney W. Grimes 	,{0xFF, "BBT (Bad Blocks Table)"}
2145b81b6b3SRodney W. Grimes };
2155b81b6b3SRodney W. Grimes 
2164be1e61bSAlexander Langer static void print_s0(int which);
2174be1e61bSAlexander Langer static void print_part(int i);
2184be1e61bSAlexander Langer static void init_sector0(unsigned long start);
219f46af505SJordan K. Hubbard static void init_boot(void);
2204be1e61bSAlexander Langer static void change_part(int i);
2214be1e61bSAlexander Langer static void print_params();
2224be1e61bSAlexander Langer static void change_active(int which);
2234be1e61bSAlexander Langer static void get_params_to_use();
224e2975440SBruce Evans static void dos(int sec, int size, unsigned char *c, unsigned char *s,
225e2975440SBruce Evans 		unsigned char *h);
2264be1e61bSAlexander Langer static int open_disk(int u_flag);
2274be1e61bSAlexander Langer static ssize_t read_disk(off_t sector, void *buf);
2284be1e61bSAlexander Langer static ssize_t write_disk(off_t sector, void *buf);
2294be1e61bSAlexander Langer static int get_params();
2304be1e61bSAlexander Langer static int read_s0();
2314be1e61bSAlexander Langer static int write_s0();
2324be1e61bSAlexander Langer static int ok(char *str);
2334be1e61bSAlexander Langer static int decimal(char *str, int *num, int deflt);
2344be1e61bSAlexander Langer static char *get_type(int type);
235f46af505SJordan K. Hubbard static int read_config(char *config_file);
236f46af505SJordan K. Hubbard static void reset_boot(void);
237d98b1668SPhilippe Charnier static void usage(void);
2384be1e61bSAlexander Langer #if 0
2394be1e61bSAlexander Langer static int hex(char *str, int *num, int deflt);
2404be1e61bSAlexander Langer static int string(char *str, char **ans);
2414be1e61bSAlexander Langer #endif
2425b81b6b3SRodney W. Grimes 
2434be1e61bSAlexander Langer 
2444be1e61bSAlexander Langer int
2454be1e61bSAlexander Langer main(int argc, char *argv[])
2465b81b6b3SRodney W. Grimes {
2475b81b6b3SRodney W. Grimes 	int	i;
2485b81b6b3SRodney W. Grimes 
2495b81b6b3SRodney W. Grimes 	for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
2505b81b6b3SRodney W. Grimes 		if (*token++ != '-' || !*token)
2515b81b6b3SRodney W. Grimes 			break;
2525b81b6b3SRodney W. Grimes 		else { register int flag;
2534be1e61bSAlexander Langer 			for ( ; (flag = *token++) ; ) {
2545b81b6b3SRodney W. Grimes 				switch (flag) {
2555b81b6b3SRodney W. Grimes 				case '1':
2565b81b6b3SRodney W. Grimes 					partition = 1;
2575b81b6b3SRodney W. Grimes 					break;
2585b81b6b3SRodney W. Grimes 				case '2':
2595b81b6b3SRodney W. Grimes 					partition = 2;
2605b81b6b3SRodney W. Grimes 					break;
2615b81b6b3SRodney W. Grimes 				case '3':
2625b81b6b3SRodney W. Grimes 					partition = 3;
2635b81b6b3SRodney W. Grimes 					break;
2644ddd60b9SBrian Somers 				case '4':
2654ddd60b9SBrian Somers 					partition = 4;
2664ddd60b9SBrian Somers 					break;
2675b81b6b3SRodney W. Grimes 				case 'a':
2685b81b6b3SRodney W. Grimes 					a_flag = 1;
2695b81b6b3SRodney W. Grimes 					break;
270f46af505SJordan K. Hubbard 				case 'f':
271f46af505SJordan K. Hubbard 					if (*token)
272f46af505SJordan K. Hubbard 					{
273f46af505SJordan K. Hubbard 					    f_flag = token;
274f46af505SJordan K. Hubbard 					    token = "";
275f46af505SJordan K. Hubbard 					}
276f46af505SJordan K. Hubbard 					else
277f46af505SJordan K. Hubbard 					{
278f46af505SJordan K. Hubbard 					    if (argc == 1)
279d98b1668SPhilippe Charnier 						usage();
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:
300d98b1668SPhilippe Charnier 					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)
319d98b1668SPhilippe Charnier 			err(1, "cannot open disk %s", disk);
320e3038c6eSJoerg Wunsch 	}
321e3038c6eSJoerg Wunsch 	else
322e3038c6eSJoerg Wunsch 	{
3234be1e61bSAlexander Langer 		int i, rv = 0;
324e3038c6eSJoerg Wunsch 
325e3038c6eSJoerg Wunsch 		for(i = 0; disks[i]; i++)
326e3038c6eSJoerg Wunsch 		{
327e3038c6eSJoerg Wunsch 			disk = disks[i];
328e3038c6eSJoerg Wunsch 			rv = open_disk(u_flag);
329e3038c6eSJoerg Wunsch 			if(rv != -2) break;
330e3038c6eSJoerg Wunsch 		}
331e3038c6eSJoerg Wunsch 		if(rv < 0)
332d98b1668SPhilippe Charnier 			err(1, "cannot open any disk");
333e3038c6eSJoerg Wunsch 	}
3345b81b6b3SRodney W. Grimes 
3355b81b6b3SRodney W. Grimes 	printf("******* Working on device %s *******\n",disk);
336f46af505SJordan K. Hubbard 
337f46af505SJordan K. Hubbard 	if (f_flag)
338f46af505SJordan K. Hubbard 	{
339f46af505SJordan K. Hubbard 	    if (read_s0() || i_flag)
340f46af505SJordan K. Hubbard 	    {
341f46af505SJordan K. Hubbard 		reset_boot();
342f46af505SJordan K. Hubbard 	    }
343f46af505SJordan K. Hubbard 
344f46af505SJordan K. Hubbard 	    if (!read_config(f_flag))
345f46af505SJordan K. Hubbard 	    {
346f46af505SJordan K. Hubbard 		exit(1);
347f46af505SJordan K. Hubbard 	    }
348f46af505SJordan K. Hubbard 	    if (v_flag)
349f46af505SJordan K. Hubbard 	    {
350f46af505SJordan K. Hubbard 		print_s0(-1);
351f46af505SJordan K. Hubbard 	    }
352f46af505SJordan K. Hubbard 	    if (!t_flag)
353f46af505SJordan K. Hubbard 	    {
354f46af505SJordan K. Hubbard 		write_s0();
355f46af505SJordan K. Hubbard 	    }
356f46af505SJordan K. Hubbard 	}
357f46af505SJordan K. Hubbard 	else
358f46af505SJordan K. Hubbard 	{
3595b81b6b3SRodney W. Grimes 	    if(u_flag)
3605b81b6b3SRodney W. Grimes 	    {
3615b81b6b3SRodney W. Grimes 		get_params_to_use();
3625b81b6b3SRodney W. Grimes 	    }
3635b81b6b3SRodney W. Grimes 	    else
3645b81b6b3SRodney W. Grimes 	    {
3655b81b6b3SRodney W. Grimes 		print_params();
3665b81b6b3SRodney W. Grimes 	    }
3675b81b6b3SRodney W. Grimes 
3685b81b6b3SRodney W. Grimes 	    if (read_s0())
3695b81b6b3SRodney W. Grimes 		init_sector0(1);
3705b81b6b3SRodney W. Grimes 
3717cb29d33SSøren Schmidt 	    printf("Media sector size is %d\n", secsize);
3725b81b6b3SRodney W. Grimes 	    printf("Warning: BIOS sector numbering starts with sector 1\n");
3735b81b6b3SRodney W. Grimes 	    printf("Information from DOS bootblock is:\n");
3745b81b6b3SRodney W. Grimes 	    if (partition == -1)
3754ddd60b9SBrian Somers 		for (i = 1; i <= NDOSPART; i++)
3765b81b6b3SRodney W. Grimes 		    change_part(i);
3775b81b6b3SRodney W. Grimes 	    else
3785b81b6b3SRodney W. Grimes 		change_part(partition);
3795b81b6b3SRodney W. Grimes 
3805b81b6b3SRodney W. Grimes 	    if (u_flag || a_flag)
3815b81b6b3SRodney W. Grimes 		change_active(partition);
3825b81b6b3SRodney W. Grimes 
3835b81b6b3SRodney W. Grimes 	    if (u_flag || a_flag) {
384f46af505SJordan K. Hubbard 		if (!t_flag)
385f46af505SJordan K. Hubbard 		{
3865b81b6b3SRodney W. Grimes 		    printf("\nWe haven't changed the partition table yet.  ");
3875b81b6b3SRodney W. Grimes 		    printf("This is your last chance.\n");
388f46af505SJordan K. Hubbard 		}
3895b81b6b3SRodney W. Grimes 		print_s0(-1);
390f46af505SJordan K. Hubbard 		if (!t_flag)
391f46af505SJordan K. Hubbard 		{
3925b81b6b3SRodney W. Grimes 		    if (ok("Should we write new partition table?"))
3935b81b6b3SRodney W. Grimes 			write_s0();
3945b81b6b3SRodney W. Grimes 		}
395f46af505SJordan K. Hubbard 		else
396f46af505SJordan K. Hubbard 		{
397f46af505SJordan K. Hubbard 		    printf("\n-t flag specified -- partition table not written.\n");
398f46af505SJordan K. Hubbard 		}
399f46af505SJordan K. Hubbard 	    }
400f46af505SJordan K. Hubbard 	}
4015b81b6b3SRodney W. Grimes 
4025b81b6b3SRodney W. Grimes 	exit(0);
403d98b1668SPhilippe Charnier }
4045b81b6b3SRodney W. Grimes 
405d98b1668SPhilippe Charnier static void
406d98b1668SPhilippe Charnier usage()
407d98b1668SPhilippe Charnier {
408d98b1668SPhilippe Charnier 	fprintf(stderr,
409d98b1668SPhilippe Charnier  "usage: fdisk {-a|-i|-u} [-f <config file> [-t] [-v]] [-{1,2,3,4}] [disk]\n");
410d98b1668SPhilippe Charnier         exit(1);
4115b81b6b3SRodney W. Grimes }
4125b81b6b3SRodney W. Grimes 
4134be1e61bSAlexander Langer static void
4144be1e61bSAlexander Langer print_s0(int which)
4155b81b6b3SRodney W. Grimes {
4165b81b6b3SRodney W. Grimes int	i;
4175b81b6b3SRodney W. Grimes 
4185b81b6b3SRodney W. Grimes 	print_params();
4195b81b6b3SRodney W. Grimes 	printf("Information from DOS bootblock is:\n");
4205b81b6b3SRodney W. Grimes 	if (which == -1)
4214ddd60b9SBrian Somers 		for (i = 1; i <= NDOSPART; i++)
4225b81b6b3SRodney W. Grimes 			printf("%d: ", i), print_part(i);
4235b81b6b3SRodney W. Grimes 	else
4245b81b6b3SRodney W. Grimes 		print_part(which);
4255b81b6b3SRodney W. Grimes }
4265b81b6b3SRodney W. Grimes 
4275b81b6b3SRodney W. Grimes static struct dos_partition mtpart = { 0 };
4285b81b6b3SRodney W. Grimes 
4294be1e61bSAlexander Langer static void
4304be1e61bSAlexander Langer print_part(int i)
4315b81b6b3SRodney W. Grimes {
432637fe2f7SJustin T. Gibbs 	struct	  dos_partition *partp;
433637fe2f7SJustin T. Gibbs 	u_int64_t part_mb;
4345b81b6b3SRodney W. Grimes 
4354ddd60b9SBrian Somers 	partp = ((struct dos_partition *) &mboot.parts) + i - 1;
4365b81b6b3SRodney W. Grimes 
4375b81b6b3SRodney W. Grimes 	if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
4385b81b6b3SRodney W. Grimes 		printf("<UNUSED>\n");
4395b81b6b3SRodney W. Grimes 		return;
4405b81b6b3SRodney W. Grimes 	}
441637fe2f7SJustin T. Gibbs 	/*
442637fe2f7SJustin T. Gibbs 	 * Be careful not to overflow.
443637fe2f7SJustin T. Gibbs 	 */
444637fe2f7SJustin T. Gibbs 	part_mb = partp->dp_size;
445637fe2f7SJustin T. Gibbs 	part_mb *= secsize;
446637fe2f7SJustin T. Gibbs 	part_mb /= (1024 * 1024);
4475b81b6b3SRodney W. Grimes 	printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
448ba198492SBruce Evans 	printf("    start %lu, size %lu (%qd Meg), flag %x%s\n",
449ba198492SBruce Evans 		(u_long)partp->dp_start,
450ba198492SBruce Evans 		(u_long)partp->dp_size,
451637fe2f7SJustin T. Gibbs 		part_mb,
452680426beSDavid E. O'Brien 		partp->dp_flag,
453680426beSDavid E. O'Brien 		partp->dp_flag == ACTIVE ? " (active)" : "");
4545b81b6b3SRodney W. Grimes 	printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
4555b81b6b3SRodney W. Grimes 		,DPCYL(partp->dp_scyl, partp->dp_ssect)
4565b81b6b3SRodney W. Grimes 		,DPSECT(partp->dp_ssect)
4575b81b6b3SRodney W. Grimes 		,partp->dp_shd
4585b81b6b3SRodney W. Grimes 		,DPCYL(partp->dp_ecyl, partp->dp_esect)
4595b81b6b3SRodney W. Grimes 		,DPSECT(partp->dp_esect)
4605b81b6b3SRodney W. Grimes 		,partp->dp_ehd);
4615b81b6b3SRodney W. Grimes }
4625b81b6b3SRodney W. Grimes 
463f46af505SJordan K. Hubbard 
464f46af505SJordan K. Hubbard static void
465f46af505SJordan K. Hubbard init_boot(void)
466f46af505SJordan K. Hubbard {
467f46af505SJordan K. Hubbard 	memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
468f46af505SJordan K. Hubbard 	mboot.signature = BOOT_MAGIC;
469f46af505SJordan K. Hubbard }
470f46af505SJordan K. Hubbard 
471f46af505SJordan K. Hubbard 
4724be1e61bSAlexander Langer static void
4734be1e61bSAlexander Langer init_sector0(unsigned long start)
4745b81b6b3SRodney W. Grimes {
4755b81b6b3SRodney W. Grimes struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
4764be1e61bSAlexander Langer unsigned long size = disksecs - start;
4775b81b6b3SRodney W. Grimes 
478f46af505SJordan K. Hubbard 	init_boot();
4795b81b6b3SRodney W. Grimes 
4805b81b6b3SRodney W. Grimes 	partp->dp_typ = DOSPTYP_386BSD;
4815b81b6b3SRodney W. Grimes 	partp->dp_flag = ACTIVE;
4825b81b6b3SRodney W. Grimes 	partp->dp_start = start;
4835b81b6b3SRodney W. Grimes 	partp->dp_size = size;
4845b81b6b3SRodney W. Grimes 
485e2975440SBruce Evans 	dos(partp->dp_start, partp->dp_size,
486e2975440SBruce Evans 	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
487e2975440SBruce Evans 	dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
488e2975440SBruce Evans 	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
4895b81b6b3SRodney W. Grimes }
4905b81b6b3SRodney W. Grimes 
4914be1e61bSAlexander Langer static void
4924be1e61bSAlexander Langer change_part(int i)
4935b81b6b3SRodney W. Grimes {
4944ddd60b9SBrian Somers struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i - 1;
4955b81b6b3SRodney W. Grimes 
4965b81b6b3SRodney W. Grimes     printf("The data for partition %d is:\n", i);
4975b81b6b3SRodney W. Grimes     print_part(i);
4985b81b6b3SRodney W. Grimes 
4995b81b6b3SRodney W. Grimes     if (u_flag && ok("Do you want to change it?")) {
5005b81b6b3SRodney W. Grimes 	int tmp;
5015b81b6b3SRodney W. Grimes 
5025b81b6b3SRodney W. Grimes 	if (i_flag) {
5035b81b6b3SRodney W. Grimes 		bzero((char *)partp, sizeof (struct dos_partition));
5044ddd60b9SBrian Somers 		if (i == 4) {
5055b81b6b3SRodney W. Grimes 			init_sector0(1);
5064ddd60b9SBrian Somers 			printf("\nThe static data for the DOS partition 4 has been reinitialized to:\n");
5075b81b6b3SRodney W. Grimes 			print_part(i);
5085b81b6b3SRodney W. Grimes 		}
5095b81b6b3SRodney W. Grimes 	}
5105b81b6b3SRodney W. Grimes 
5115b81b6b3SRodney W. Grimes 	do {
512680426beSDavid E. O'Brien 		Decimal("sysid (165=FreeBSD)", partp->dp_typ, tmp);
5135b81b6b3SRodney W. Grimes 		Decimal("start", partp->dp_start, tmp);
5145b81b6b3SRodney W. Grimes 		Decimal("size", partp->dp_size, tmp);
5155b81b6b3SRodney W. Grimes 
5164b3b45a7SJames Raynard 		if (ok("Explicitly specify beg/end address ?"))
5175b81b6b3SRodney W. Grimes 		{
5185b81b6b3SRodney W. Grimes 			int	tsec,tcyl,thd;
5195b81b6b3SRodney W. Grimes 			tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
5205b81b6b3SRodney W. Grimes 			thd = partp->dp_shd;
5215b81b6b3SRodney W. Grimes 			tsec = DPSECT(partp->dp_ssect);
5225b81b6b3SRodney W. Grimes 			Decimal("beginning cylinder", tcyl, tmp);
5235b81b6b3SRodney W. Grimes 			Decimal("beginning head", thd, tmp);
5245b81b6b3SRodney W. Grimes 			Decimal("beginning sector", tsec, tmp);
5255b81b6b3SRodney W. Grimes 			partp->dp_scyl = DOSCYL(tcyl);
5265b81b6b3SRodney W. Grimes 			partp->dp_ssect = DOSSECT(tsec,tcyl);
5275b81b6b3SRodney W. Grimes 			partp->dp_shd = thd;
5285b81b6b3SRodney W. Grimes 
5295b81b6b3SRodney W. Grimes 			tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
5305b81b6b3SRodney W. Grimes 			thd = partp->dp_ehd;
5315b81b6b3SRodney W. Grimes 			tsec = DPSECT(partp->dp_esect);
5325b81b6b3SRodney W. Grimes 			Decimal("ending cylinder", tcyl, tmp);
5335b81b6b3SRodney W. Grimes 			Decimal("ending head", thd, tmp);
5345b81b6b3SRodney W. Grimes 			Decimal("ending sector", tsec, tmp);
5355b81b6b3SRodney W. Grimes 			partp->dp_ecyl = DOSCYL(tcyl);
5365b81b6b3SRodney W. Grimes 			partp->dp_esect = DOSSECT(tsec,tcyl);
5375b81b6b3SRodney W. Grimes 			partp->dp_ehd = thd;
5385b81b6b3SRodney W. Grimes 		} else {
539e2975440SBruce Evans 			dos(partp->dp_start, partp->dp_size,
5405b81b6b3SRodney W. Grimes 			    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
541e2975440SBruce Evans 			dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
5425b81b6b3SRodney W. Grimes 			    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
5435b81b6b3SRodney W. Grimes 		}
5445b81b6b3SRodney W. Grimes 
5455b81b6b3SRodney W. Grimes 		print_part(i);
5465b81b6b3SRodney W. Grimes 	} while (!ok("Are we happy with this entry?"));
5475b81b6b3SRodney W. Grimes     }
5485b81b6b3SRodney W. Grimes }
5495b81b6b3SRodney W. Grimes 
5504be1e61bSAlexander Langer static void
5515b81b6b3SRodney W. Grimes print_params()
5525b81b6b3SRodney W. Grimes {
5535b81b6b3SRodney W. Grimes 	printf("parameters extracted from in-core disklabel are:\n");
5545b81b6b3SRodney W. Grimes 	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
5555b81b6b3SRodney W. Grimes 			,cyls,heads,sectors,cylsecs);
5565b81b6b3SRodney W. Grimes 	if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
5575b81b6b3SRodney W. Grimes 		printf("Figures below won't work with BIOS for partitions not in cyl 1\n");
5585b81b6b3SRodney W. Grimes 	printf("parameters to be used for BIOS calculations are:\n");
5595b81b6b3SRodney W. Grimes 	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
5605b81b6b3SRodney W. Grimes 		,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
5615b81b6b3SRodney W. Grimes }
5625b81b6b3SRodney W. Grimes 
5634be1e61bSAlexander Langer static void
5644be1e61bSAlexander Langer change_active(int which)
5655b81b6b3SRodney W. Grimes {
5665b81b6b3SRodney W. Grimes int i;
5674ddd60b9SBrian Somers int active = 4, tmp;
5685b81b6b3SRodney W. Grimes struct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
5695b81b6b3SRodney W. Grimes 
5705b81b6b3SRodney W. Grimes 	if (a_flag && which != -1)
5715b81b6b3SRodney W. Grimes 		active = which;
5720b461cd7SBruce Evans 	if (!ok("Do you want to change the active partition?"))
5730b461cd7SBruce Evans 		return;
574680426beSDavid E. O'Brien setactive:
575680426beSDavid E. O'Brien 	active = 4;
576680426beSDavid E. O'Brien 	do {
5775b81b6b3SRodney W. Grimes 		Decimal("active partition", active, tmp);
578680426beSDavid E. O'Brien 		if (active < 1 || 4 < active) {
579680426beSDavid E. O'Brien 			printf("Active partition number must be in range 1-4."
580680426beSDavid E. O'Brien 					"  Try again.\n");
581680426beSDavid E. O'Brien 			goto setactive;
582680426beSDavid E. O'Brien 		}
583680426beSDavid E. O'Brien 	} while (!ok("Are you happy with this choice"));
5845b81b6b3SRodney W. Grimes 	for (i = 0; i < NDOSPART; i++)
5855b81b6b3SRodney W. Grimes 		partp[i].dp_flag = 0;
5864ddd60b9SBrian Somers 	if (active > 0 && active <= NDOSPART)
5874ddd60b9SBrian Somers 		partp[active-1].dp_flag = ACTIVE;
5885b81b6b3SRodney W. Grimes }
5895b81b6b3SRodney W. Grimes 
5904be1e61bSAlexander Langer void
5915b81b6b3SRodney W. Grimes get_params_to_use()
5925b81b6b3SRodney W. Grimes {
5935b81b6b3SRodney W. Grimes 	int	tmp;
5945b81b6b3SRodney W. Grimes 	print_params();
5955b81b6b3SRodney W. Grimes 	if (ok("Do you want to change our idea of what BIOS thinks ?"))
5965b81b6b3SRodney W. Grimes 	{
5975b81b6b3SRodney W. Grimes 		do
5985b81b6b3SRodney W. Grimes 		{
5995b81b6b3SRodney W. Grimes 			Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
6005b81b6b3SRodney W. Grimes 			Decimal("BIOS's idea of #heads", dos_heads, tmp);
6015b81b6b3SRodney W. Grimes 			Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
6025b81b6b3SRodney W. Grimes 			dos_cylsecs = dos_heads * dos_sectors;
6035b81b6b3SRodney W. Grimes 			print_params();
6045b81b6b3SRodney W. Grimes 		}
6055b81b6b3SRodney W. Grimes 		while(!ok("Are you happy with this choice"));
6065b81b6b3SRodney W. Grimes 	}
6075b81b6b3SRodney W. Grimes }
6085b81b6b3SRodney W. Grimes 
609f46af505SJordan K. Hubbard 
6105b81b6b3SRodney W. Grimes /***********************************************\
6115b81b6b3SRodney W. Grimes * Change real numbers into strange dos numbers	*
6125b81b6b3SRodney W. Grimes \***********************************************/
6134be1e61bSAlexander Langer static void
614e2975440SBruce Evans dos(sec, size, c, s, h)
615e2975440SBruce Evans int sec, size;
6165b81b6b3SRodney W. Grimes unsigned char *c, *s, *h;
6175b81b6b3SRodney W. Grimes {
6185b81b6b3SRodney W. Grimes int cy;
6195b81b6b3SRodney W. Grimes int hd;
6205b81b6b3SRodney W. Grimes 
621e2975440SBruce Evans 	if (sec == 0 && size == 0) {
6220b461cd7SBruce Evans 		*s = *c = *h = 0;
6230b461cd7SBruce Evans 		return;
6240b461cd7SBruce Evans 	}
6250b461cd7SBruce Evans 
6265b81b6b3SRodney W. Grimes 	cy = sec / ( dos_cylsecs );
6275b81b6b3SRodney W. Grimes 	sec = sec - cy * ( dos_cylsecs );
6285b81b6b3SRodney W. Grimes 
6295b81b6b3SRodney W. Grimes 	hd = sec / dos_sectors;
6305b81b6b3SRodney W. Grimes 	sec = (sec - hd * dos_sectors) + 1;
6315b81b6b3SRodney W. Grimes 
6325b81b6b3SRodney W. Grimes 	*h = hd;
6335b81b6b3SRodney W. Grimes 	*c = cy & 0xff;
6345b81b6b3SRodney W. Grimes 	*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
6355b81b6b3SRodney W. Grimes }
6365b81b6b3SRodney W. Grimes 
6375b81b6b3SRodney W. Grimes int fd;
6385b81b6b3SRodney W. Grimes 
6395b81b6b3SRodney W. Grimes 	/* Getting device status */
6405b81b6b3SRodney W. Grimes 
6414be1e61bSAlexander Langer static int
6424be1e61bSAlexander Langer open_disk(int u_flag)
6435b81b6b3SRodney W. Grimes {
6445b81b6b3SRodney W. Grimes struct stat 	st;
6455b81b6b3SRodney W. Grimes 
6465b81b6b3SRodney W. Grimes 	if (stat(disk, &st) == -1) {
647d98b1668SPhilippe Charnier 		warnx("can't get file status of %s", disk);
6485b81b6b3SRodney W. Grimes 		return -1;
649b60eb395SBruce Evans 	}
650b60eb395SBruce Evans 	if ( !(st.st_mode & S_IFCHR) )
651d98b1668SPhilippe Charnier 		warnx("device %s is not character special", disk);
6520b461cd7SBruce Evans 	if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) {
653e3038c6eSJoerg Wunsch 		if(errno == ENXIO)
654e3038c6eSJoerg Wunsch 			return -2;
655d98b1668SPhilippe Charnier 		warnx("can't open device %s", disk);
6565b81b6b3SRodney W. Grimes 		return -1;
6575b81b6b3SRodney W. Grimes 	}
6585b81b6b3SRodney W. Grimes 	if (get_params(0) == -1) {
659d98b1668SPhilippe Charnier 		warnx("can't get disk parameters on %s", disk);
6605b81b6b3SRodney W. Grimes 		return -1;
6615b81b6b3SRodney W. Grimes 	}
6625b81b6b3SRodney W. Grimes 	return fd;
6635b81b6b3SRodney W. Grimes }
6645b81b6b3SRodney W. Grimes 
6654be1e61bSAlexander Langer static ssize_t
6664be1e61bSAlexander Langer read_disk(off_t sector, void *buf)
6675b81b6b3SRodney W. Grimes {
6685b81b6b3SRodney W. Grimes 	lseek(fd,(sector * 512), 0);
6697cb29d33SSøren Schmidt 	if( secsize == 0 )
6707cb29d33SSøren Schmidt 		for( secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; secsize *= 2 )
6717cb29d33SSøren Schmidt 			{
6727cb29d33SSøren Schmidt 			/* try the read */
6737cb29d33SSøren Schmidt 			int size = read(fd, buf, secsize);
6747cb29d33SSøren Schmidt 			if( size == secsize )
6757cb29d33SSøren Schmidt 				/* it worked so return */
6767cb29d33SSøren Schmidt 				return secsize;
6777cb29d33SSøren Schmidt 			}
6787cb29d33SSøren Schmidt 	else
6797cb29d33SSøren Schmidt 		return read( fd, buf, secsize );
6807cb29d33SSøren Schmidt 
6817cb29d33SSøren Schmidt 	/* we failed to read at any of the sizes */
6827cb29d33SSøren Schmidt 	return -1;
6835b81b6b3SRodney W. Grimes }
6845b81b6b3SRodney W. Grimes 
6854be1e61bSAlexander Langer static ssize_t
6864be1e61bSAlexander Langer write_disk(off_t sector, void *buf)
6875b81b6b3SRodney W. Grimes {
6885b81b6b3SRodney W. Grimes 	lseek(fd,(sector * 512), 0);
6897cb29d33SSøren Schmidt 	/* write out in the size that the read_disk found worked */
6907cb29d33SSøren Schmidt 	return write(fd, buf, secsize);
6915b81b6b3SRodney W. Grimes }
6925b81b6b3SRodney W. Grimes 
6934be1e61bSAlexander Langer static int
6944be1e61bSAlexander Langer get_params()
6955b81b6b3SRodney W. Grimes {
6965b81b6b3SRodney W. Grimes 
6975b81b6b3SRodney W. Grimes     if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
698d98b1668SPhilippe Charnier 	warnx("can't get disk parameters on %s; supplying dummy ones", disk);
699b60eb395SBruce Evans 	dos_cyls = cyls = 1;
700b60eb395SBruce Evans 	dos_heads = heads = 1;
701b60eb395SBruce Evans 	dos_sectors = sectors = 1;
702b60eb395SBruce Evans 	dos_cylsecs = cylsecs = heads * sectors;
703b60eb395SBruce Evans 	disksecs = cyls * heads * sectors;
704b60eb395SBruce Evans 	return disksecs;
7055b81b6b3SRodney W. Grimes     }
7065b81b6b3SRodney W. Grimes 
7075b81b6b3SRodney W. Grimes     dos_cyls = cyls = disklabel.d_ncylinders;
7085b81b6b3SRodney W. Grimes     dos_heads = heads = disklabel.d_ntracks;
7095b81b6b3SRodney W. Grimes     dos_sectors = sectors = disklabel.d_nsectors;
7105b81b6b3SRodney W. Grimes     dos_cylsecs = cylsecs = heads * sectors;
7115b81b6b3SRodney W. Grimes     disksecs = cyls * heads * sectors;
7125b81b6b3SRodney W. Grimes 
7135b81b6b3SRodney W. Grimes     return (disksecs);
7145b81b6b3SRodney W. Grimes }
7155b81b6b3SRodney W. Grimes 
7165b81b6b3SRodney W. Grimes 
7174be1e61bSAlexander Langer static int
7185b81b6b3SRodney W. Grimes read_s0()
7195b81b6b3SRodney W. Grimes {
7205b81b6b3SRodney W. Grimes 	if (read_disk(0, (char *) mboot.bootinst) == -1) {
721d98b1668SPhilippe Charnier 		warnx("can't read fdisk partition table");
7225b81b6b3SRodney W. Grimes 		return -1;
7235b81b6b3SRodney W. Grimes 	}
7245b81b6b3SRodney W. Grimes 	if (mboot.signature != BOOT_MAGIC) {
725d98b1668SPhilippe Charnier 		warnx("invalid fdisk partition table found");
7265b81b6b3SRodney W. Grimes 		/* So should we initialize things */
7275b81b6b3SRodney W. Grimes 		return -1;
7285b81b6b3SRodney W. Grimes 	}
7295b81b6b3SRodney W. Grimes 	return 0;
7305b81b6b3SRodney W. Grimes }
7315b81b6b3SRodney W. Grimes 
7324be1e61bSAlexander Langer static int
7335b81b6b3SRodney W. Grimes write_s0()
7345b81b6b3SRodney W. Grimes {
7355b81b6b3SRodney W. Grimes 	int	flag;
7365b81b6b3SRodney W. Grimes 	if (iotest) {
7375b81b6b3SRodney W. Grimes 		print_s0(-1);
7385b81b6b3SRodney W. Grimes 		return 0;
7395b81b6b3SRodney W. Grimes 	}
7405b81b6b3SRodney W. Grimes 	/*
7415b81b6b3SRodney W. Grimes 	 * write enable label sector before write (if necessary),
7425b81b6b3SRodney W. Grimes 	 * disable after writing.
7435b81b6b3SRodney W. Grimes 	 * needed if the disklabel protected area also protects
7445b81b6b3SRodney W. Grimes 	 * sector 0. (e.g. empty disk)
7455b81b6b3SRodney W. Grimes 	 */
7465b81b6b3SRodney W. Grimes 	flag = 1;
747ba3551dfSJulian Elischer #ifdef NOT_NOW
7485b81b6b3SRodney W. Grimes 	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
749d98b1668SPhilippe Charnier 		warn("ioctl DIOCWLABEL");
750ba3551dfSJulian Elischer #endif
7515b81b6b3SRodney W. Grimes 	if (write_disk(0, (char *) mboot.bootinst) == -1) {
752d98b1668SPhilippe Charnier 		warnx("can't write fdisk partition table");
7535b81b6b3SRodney W. Grimes 		return -1;
7545b81b6b3SRodney W. Grimes 	flag = 0;
755ba3551dfSJulian Elischer #ifdef NOT_NOW
7565b81b6b3SRodney W. Grimes 	(void) ioctl(fd, DIOCWLABEL, &flag);
757ba3551dfSJulian Elischer #endif
7585b81b6b3SRodney W. Grimes 	}
7594be1e61bSAlexander Langer 	return(0);
7605b81b6b3SRodney W. Grimes }
7615b81b6b3SRodney W. Grimes 
7625b81b6b3SRodney W. Grimes 
7634be1e61bSAlexander Langer static int
7645b81b6b3SRodney W. Grimes ok(str)
7655b81b6b3SRodney W. Grimes char *str;
7665b81b6b3SRodney W. Grimes {
7675b81b6b3SRodney W. Grimes 	printf("%s [n] ", str);
7685b81b6b3SRodney W. Grimes 	fgets(lbuf, LBUF, stdin);
7695b81b6b3SRodney W. Grimes 	lbuf[strlen(lbuf)-1] = 0;
7705b81b6b3SRodney W. Grimes 
7715b81b6b3SRodney W. Grimes 	if (*lbuf &&
7725b81b6b3SRodney W. Grimes 		(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
7735b81b6b3SRodney W. Grimes 		 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
7745b81b6b3SRodney W. Grimes 		return 1;
7755b81b6b3SRodney W. Grimes 	else
7765b81b6b3SRodney W. Grimes 		return 0;
7775b81b6b3SRodney W. Grimes }
7785b81b6b3SRodney W. Grimes 
7794be1e61bSAlexander Langer static int
7804be1e61bSAlexander Langer decimal(char *str, int *num, int deflt)
7815b81b6b3SRodney W. Grimes {
7825b81b6b3SRodney W. Grimes int acc = 0, c;
7835b81b6b3SRodney W. Grimes char *cp;
7845b81b6b3SRodney W. Grimes 
7855b81b6b3SRodney W. Grimes 	while (1) {
7865b81b6b3SRodney W. Grimes 		printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
7875b81b6b3SRodney W. Grimes 		fgets(lbuf, LBUF, stdin);
7885b81b6b3SRodney W. Grimes 		lbuf[strlen(lbuf)-1] = 0;
7895b81b6b3SRodney W. Grimes 
7905b81b6b3SRodney W. Grimes 		if (!*lbuf)
7915b81b6b3SRodney W. Grimes 			return 0;
7925b81b6b3SRodney W. Grimes 
7935b81b6b3SRodney W. Grimes 		cp = lbuf;
7945b81b6b3SRodney W. Grimes 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
7955b81b6b3SRodney W. Grimes 		if (!c)
7965b81b6b3SRodney W. Grimes 			return 0;
7974be1e61bSAlexander Langer 		while ((c = *cp++)) {
7985b81b6b3SRodney W. Grimes 			if (c <= '9' && c >= '0')
7995b81b6b3SRodney W. Grimes 				acc = acc * 10 + c - '0';
8005b81b6b3SRodney W. Grimes 			else
8015b81b6b3SRodney W. Grimes 				break;
8025b81b6b3SRodney W. Grimes 		}
8035b81b6b3SRodney W. Grimes 		if (c == ' ' || c == '\t')
8045b81b6b3SRodney W. Grimes 			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8055b81b6b3SRodney W. Grimes 		if (!c) {
8065b81b6b3SRodney W. Grimes 			*num = acc;
8075b81b6b3SRodney W. Grimes 			return 1;
8085b81b6b3SRodney W. Grimes 		} else
809680426beSDavid E. O'Brien 			printf("%s is an invalid decimal number.  Try again.\n",
8105b81b6b3SRodney W. Grimes 				lbuf);
8115b81b6b3SRodney W. Grimes 	}
8125b81b6b3SRodney W. Grimes 
8135b81b6b3SRodney W. Grimes }
8145b81b6b3SRodney W. Grimes 
8154be1e61bSAlexander Langer #if 0
8164be1e61bSAlexander Langer static int
8174be1e61bSAlexander Langer hex(char *str, int *num, int deflt)
8185b81b6b3SRodney W. Grimes {
8195b81b6b3SRodney W. Grimes int acc = 0, c;
8205b81b6b3SRodney W. Grimes char *cp;
8215b81b6b3SRodney W. Grimes 
8225b81b6b3SRodney W. Grimes 	while (1) {
8235b81b6b3SRodney W. Grimes 		printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
8245b81b6b3SRodney W. Grimes 		fgets(lbuf, LBUF, stdin);
8255b81b6b3SRodney W. Grimes 		lbuf[strlen(lbuf)-1] = 0;
8265b81b6b3SRodney W. Grimes 
8275b81b6b3SRodney W. Grimes 		if (!*lbuf)
8285b81b6b3SRodney W. Grimes 			return 0;
8295b81b6b3SRodney W. Grimes 
8305b81b6b3SRodney W. Grimes 		cp = lbuf;
8315b81b6b3SRodney W. Grimes 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8325b81b6b3SRodney W. Grimes 		if (!c)
8335b81b6b3SRodney W. Grimes 			return 0;
8344be1e61bSAlexander Langer 		while ((c = *cp++)) {
8355b81b6b3SRodney W. Grimes 			if (c <= '9' && c >= '0')
8365b81b6b3SRodney W. Grimes 				acc = (acc << 4) + c - '0';
8375b81b6b3SRodney W. Grimes 			else if (c <= 'f' && c >= 'a')
8385b81b6b3SRodney W. Grimes 				acc = (acc << 4) + c - 'a' + 10;
8395b81b6b3SRodney W. Grimes 			else if (c <= 'F' && c >= 'A')
8405b81b6b3SRodney W. Grimes 				acc = (acc << 4) + c - 'A' + 10;
8415b81b6b3SRodney W. Grimes 			else
8425b81b6b3SRodney W. Grimes 				break;
8435b81b6b3SRodney W. Grimes 		}
8445b81b6b3SRodney W. Grimes 		if (c == ' ' || c == '\t')
8455b81b6b3SRodney W. Grimes 			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8465b81b6b3SRodney W. Grimes 		if (!c) {
8475b81b6b3SRodney W. Grimes 			*num = acc;
8485b81b6b3SRodney W. Grimes 			return 1;
8495b81b6b3SRodney W. Grimes 		} else
850680426beSDavid E. O'Brien 			printf("%s is an invalid hex number.  Try again.\n",
8515b81b6b3SRodney W. Grimes 				lbuf);
8525b81b6b3SRodney W. Grimes 	}
8535b81b6b3SRodney W. Grimes 
8545b81b6b3SRodney W. Grimes }
8555b81b6b3SRodney W. Grimes 
8564be1e61bSAlexander Langer static int
8574be1e61bSAlexander Langer string(char *str, char **ans)
8585b81b6b3SRodney W. Grimes {
8595b81b6b3SRodney W. Grimes int c;
8605b81b6b3SRodney W. Grimes char *cp = lbuf;
8615b81b6b3SRodney W. Grimes 
8625b81b6b3SRodney W. Grimes 	while (1) {
8635b81b6b3SRodney W. Grimes 		printf("Supply a string value for \"%s\" [%s] ", str, *ans);
8645b81b6b3SRodney W. Grimes 		fgets(lbuf, LBUF, stdin);
8655b81b6b3SRodney W. Grimes 		lbuf[strlen(lbuf)-1] = 0;
8665b81b6b3SRodney W. Grimes 
8675b81b6b3SRodney W. Grimes 		if (!*lbuf)
8685b81b6b3SRodney W. Grimes 			return 0;
8695b81b6b3SRodney W. Grimes 
8705b81b6b3SRodney W. Grimes 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
8715b81b6b3SRodney W. Grimes 		if (c == '"') {
8725b81b6b3SRodney W. Grimes 			c = *++cp;
8735b81b6b3SRodney W. Grimes 			*ans = cp;
8745b81b6b3SRodney W. Grimes 			while ((c = *cp) && c != '"') cp++;
8755b81b6b3SRodney W. Grimes 		} else {
8765b81b6b3SRodney W. Grimes 			*ans = cp;
8775b81b6b3SRodney W. Grimes 			while ((c = *cp) && c != ' ' && c != '\t') cp++;
8785b81b6b3SRodney W. Grimes 		}
8795b81b6b3SRodney W. Grimes 
8805b81b6b3SRodney W. Grimes 		if (c)
8815b81b6b3SRodney W. Grimes 			*cp = 0;
8825b81b6b3SRodney W. Grimes 		return 1;
8835b81b6b3SRodney W. Grimes 	}
8845b81b6b3SRodney W. Grimes }
8854be1e61bSAlexander Langer #endif
8865b81b6b3SRodney W. Grimes 
8874be1e61bSAlexander Langer static char *
8884be1e61bSAlexander Langer get_type(int type)
8895b81b6b3SRodney W. Grimes {
8905b81b6b3SRodney W. Grimes 	int	numentries = (sizeof(part_types)/sizeof(struct part_type));
8915b81b6b3SRodney W. Grimes 	int	counter = 0;
8925b81b6b3SRodney W. Grimes 	struct	part_type *ptr = part_types;
8935b81b6b3SRodney W. Grimes 
8945b81b6b3SRodney W. Grimes 
8955b81b6b3SRodney W. Grimes 	while(counter < numentries)
8965b81b6b3SRodney W. Grimes 	{
8975b81b6b3SRodney W. Grimes 		if(ptr->type == type)
8985b81b6b3SRodney W. Grimes 		{
8995b81b6b3SRodney W. Grimes 			return(ptr->name);
9005b81b6b3SRodney W. Grimes 		}
9015b81b6b3SRodney W. Grimes 		ptr++;
9025b81b6b3SRodney W. Grimes 		counter++;
9035b81b6b3SRodney W. Grimes 	}
9045b81b6b3SRodney W. Grimes 	return("unknown");
9055b81b6b3SRodney W. Grimes }
906f46af505SJordan K. Hubbard 
907f46af505SJordan K. Hubbard 
908f46af505SJordan K. Hubbard static void
909f46af505SJordan K. Hubbard parse_config_line(line, command)
910f46af505SJordan K. Hubbard     char	*line;
911f46af505SJordan K. Hubbard     CMD		*command;
912f46af505SJordan K. Hubbard {
913f46af505SJordan K. Hubbard     char	*cp, *end;
914f46af505SJordan K. Hubbard 
915f46af505SJordan K. Hubbard     cp = line;
916f46af505SJordan K. Hubbard     while (1)	/* dirty trick used to insure one exit point for this
917f46af505SJordan K. Hubbard 		   function */
918f46af505SJordan K. Hubbard     {
919f46af505SJordan K. Hubbard 	memset(command, 0, sizeof(*command));
920f46af505SJordan K. Hubbard 
921f46af505SJordan K. Hubbard 	while (isspace(*cp)) ++cp;
922f46af505SJordan K. Hubbard 	if (*cp == '\0' || *cp == '#')
923f46af505SJordan K. Hubbard 	{
924f46af505SJordan K. Hubbard 	    break;
925f46af505SJordan K. Hubbard 	}
926f46af505SJordan K. Hubbard 	command->cmd = *cp++;
927f46af505SJordan K. Hubbard 
928f46af505SJordan K. Hubbard 	/*
929f46af505SJordan K. Hubbard 	 * Parse args
930f46af505SJordan K. Hubbard 	 */
931f46af505SJordan K. Hubbard 	while (1)
932f46af505SJordan K. Hubbard 	{
933f46af505SJordan K. Hubbard 	    while (isspace(*cp)) ++cp;
934f46af505SJordan K. Hubbard 	    if (*cp == '#')
935f46af505SJordan K. Hubbard 	    {
936f46af505SJordan K. Hubbard 		break;		/* found comment */
937f46af505SJordan K. Hubbard 	    }
938f46af505SJordan K. Hubbard 	    if (isalpha(*cp))
939f46af505SJordan K. Hubbard 	    {
940f46af505SJordan K. Hubbard 		command->args[command->n_args].argtype = *cp++;
941f46af505SJordan K. Hubbard 	    }
942f46af505SJordan K. Hubbard 	    if (!isdigit(*cp))
943f46af505SJordan K. Hubbard 	    {
944f46af505SJordan K. Hubbard 		break;		/* assume end of line */
945f46af505SJordan K. Hubbard 	    }
946f46af505SJordan K. Hubbard 	    end = NULL;
947f46af505SJordan K. Hubbard 	    command->args[command->n_args].arg_val = strtol(cp, &end, 0);
948f46af505SJordan K. Hubbard 	    if (cp == end)
949f46af505SJordan K. Hubbard 	    {
950f46af505SJordan K. Hubbard 		break;		/* couldn't parse number */
951f46af505SJordan K. Hubbard 	    }
952f46af505SJordan K. Hubbard 	    cp = end;
953f46af505SJordan K. Hubbard 	    command->n_args++;
954f46af505SJordan K. Hubbard 	}
955f46af505SJordan K. Hubbard 	break;
956f46af505SJordan K. Hubbard     }
957f46af505SJordan K. Hubbard }
958f46af505SJordan K. Hubbard 
959f46af505SJordan K. Hubbard 
960f46af505SJordan K. Hubbard static int
961f46af505SJordan K. Hubbard process_geometry(command)
962f46af505SJordan K. Hubbard     CMD		*command;
963f46af505SJordan K. Hubbard {
964f46af505SJordan K. Hubbard     int		status = 1, i;
965f46af505SJordan K. Hubbard 
966f46af505SJordan K. Hubbard     while (1)
967f46af505SJordan K. Hubbard     {
968f46af505SJordan K. Hubbard 	geom_processed = 1;
969f46af505SJordan K. Hubbard 	if (part_processed)
970f46af505SJordan K. Hubbard 	{
971d98b1668SPhilippe Charnier 	    warnx(
972d98b1668SPhilippe Charnier 	"ERROR line %d: the geometry specification line must occur before\n\
973d98b1668SPhilippe Charnier     all partition specifications",
974d98b1668SPhilippe Charnier 		    current_line_number);
975f46af505SJordan K. Hubbard 	    status = 0;
976f46af505SJordan K. Hubbard 	    break;
977f46af505SJordan K. Hubbard 	}
978f46af505SJordan K. Hubbard 	if (command->n_args != 3)
979f46af505SJordan K. Hubbard 	{
980d98b1668SPhilippe Charnier 	    warnx("ERROR line %d: incorrect number of geometry args",
981d98b1668SPhilippe Charnier 		    current_line_number);
982f46af505SJordan K. Hubbard 	    status = 0;
983f46af505SJordan K. Hubbard 	    break;
984f46af505SJordan K. Hubbard 	}
985f46af505SJordan K. Hubbard 	dos_cyls = -1;
986f46af505SJordan K. Hubbard 	dos_heads = -1;
987f46af505SJordan K. Hubbard 	dos_sectors = -1;
988f46af505SJordan K. Hubbard 	for (i = 0; i < 3; ++i)
989f46af505SJordan K. Hubbard 	{
990f46af505SJordan K. Hubbard 	    switch (command->args[i].argtype)
991f46af505SJordan K. Hubbard 	    {
992f46af505SJordan K. Hubbard 	    case 'c':
993f46af505SJordan K. Hubbard 		dos_cyls = command->args[i].arg_val;
994f46af505SJordan K. Hubbard 		break;
995f46af505SJordan K. Hubbard 	    case 'h':
996f46af505SJordan K. Hubbard 		dos_heads = command->args[i].arg_val;
997f46af505SJordan K. Hubbard 		break;
998f46af505SJordan K. Hubbard 	    case 's':
999f46af505SJordan K. Hubbard 		dos_sectors = command->args[i].arg_val;
1000f46af505SJordan K. Hubbard 		break;
1001f46af505SJordan K. Hubbard 	    default:
1002d98b1668SPhilippe Charnier 		warnx(
1003d98b1668SPhilippe Charnier 		"ERROR line %d: unknown geometry arg type: '%c' (0x%02x)",
1004d98b1668SPhilippe Charnier 			current_line_number, command->args[i].argtype,
1005f46af505SJordan K. Hubbard 			command->args[i].argtype);
1006f46af505SJordan K. Hubbard 		status = 0;
1007f46af505SJordan K. Hubbard 		break;
1008f46af505SJordan K. Hubbard 	    }
1009f46af505SJordan K. Hubbard 	}
1010f46af505SJordan K. Hubbard 	if (status == 0)
1011f46af505SJordan K. Hubbard 	{
1012f46af505SJordan K. Hubbard 	    break;
1013f46af505SJordan K. Hubbard 	}
1014f46af505SJordan K. Hubbard 
1015f46af505SJordan K. Hubbard 	dos_cylsecs = dos_heads * dos_sectors;
1016f46af505SJordan K. Hubbard 
1017f46af505SJordan K. Hubbard 	/*
1018f46af505SJordan K. Hubbard 	 * Do sanity checks on parameter values
1019f46af505SJordan K. Hubbard 	 */
1020f46af505SJordan K. Hubbard 	if (dos_cyls < 0)
1021f46af505SJordan K. Hubbard 	{
1022d98b1668SPhilippe Charnier 	    warnx("ERROR line %d: number of cylinders not specified",
1023d98b1668SPhilippe Charnier 		    current_line_number);
1024f46af505SJordan K. Hubbard 	    status = 0;
1025f46af505SJordan K. Hubbard 	}
1026f46af505SJordan K. Hubbard 	if (dos_cyls == 0 || dos_cyls > 1024)
1027f46af505SJordan K. Hubbard 	{
1028d98b1668SPhilippe Charnier 	    warnx(
1029d98b1668SPhilippe Charnier 	"WARNING line %d: number of cylinders (%d) may be out-of-range\n\
1030f46af505SJordan K. Hubbard     (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\
1031d98b1668SPhilippe Charnier     is dedicated to FreeBSD)",
1032d98b1668SPhilippe Charnier 		    current_line_number, dos_cyls);
1033f46af505SJordan K. Hubbard 	}
1034f46af505SJordan K. Hubbard 
1035f46af505SJordan K. Hubbard 	if (dos_heads < 0)
1036f46af505SJordan K. Hubbard 	{
1037d98b1668SPhilippe Charnier 	    warnx("ERROR line %d: number of heads not specified",
1038d98b1668SPhilippe Charnier 		    current_line_number);
1039f46af505SJordan K. Hubbard 	    status = 0;
1040f46af505SJordan K. Hubbard 	}
1041f46af505SJordan K. Hubbard 	else if (dos_heads < 1 || dos_heads > 256)
1042f46af505SJordan K. Hubbard 	{
1043d98b1668SPhilippe Charnier 	    warnx("ERROR line %d: number of heads must be within (1-256)",
1044d98b1668SPhilippe Charnier 		    current_line_number);
1045f46af505SJordan K. Hubbard 	    status = 0;
1046f46af505SJordan K. Hubbard 	}
1047f46af505SJordan K. Hubbard 
1048f46af505SJordan K. Hubbard 	if (dos_sectors < 0)
1049f46af505SJordan K. Hubbard 	{
1050d98b1668SPhilippe Charnier 	    warnx("ERROR line %d: number of sectors not specified",
1051d98b1668SPhilippe Charnier 		    current_line_number);
1052f46af505SJordan K. Hubbard 	    status = 0;
1053f46af505SJordan K. Hubbard 	}
1054f46af505SJordan K. Hubbard 	else if (dos_sectors < 1 || dos_sectors > 63)
1055f46af505SJordan K. Hubbard 	{
1056d98b1668SPhilippe Charnier 	    warnx("ERROR line %d: number of sectors must be within (1-63)",
1057d98b1668SPhilippe Charnier 		    current_line_number);
1058f46af505SJordan K. Hubbard 	    status = 0;
1059f46af505SJordan K. Hubbard 	}
1060f46af505SJordan K. Hubbard 
1061f46af505SJordan K. Hubbard 	break;
1062f46af505SJordan K. Hubbard     }
1063f46af505SJordan K. Hubbard     return (status);
1064f46af505SJordan K. Hubbard }
1065f46af505SJordan K. Hubbard 
1066f46af505SJordan K. Hubbard 
1067f46af505SJordan K. Hubbard static int
1068f46af505SJordan K. Hubbard process_partition(command)
1069f46af505SJordan K. Hubbard     CMD		*command;
1070f46af505SJordan K. Hubbard {
1071f46af505SJordan K. Hubbard     int				status = 0, partition;
1072f46af505SJordan K. Hubbard     unsigned long		chunks, adj_size, max_end;
1073f46af505SJordan K. Hubbard     struct dos_partition	*partp;
1074f46af505SJordan K. Hubbard 
1075f46af505SJordan K. Hubbard     while (1)
1076f46af505SJordan K. Hubbard     {
1077f46af505SJordan K. Hubbard 	part_processed = 1;
1078f46af505SJordan K. Hubbard 	if (command->n_args != 4)
1079f46af505SJordan K. Hubbard 	{
1080d98b1668SPhilippe Charnier 	    warnx("ERROR line %d: incorrect number of partition args",
1081d98b1668SPhilippe Charnier 		    current_line_number);
1082f46af505SJordan K. Hubbard 	    break;
1083f46af505SJordan K. Hubbard 	}
1084f46af505SJordan K. Hubbard 	partition = command->args[0].arg_val;
10854ddd60b9SBrian Somers 	if (partition < 1 || partition > 4)
1086f46af505SJordan K. Hubbard 	{
1087d98b1668SPhilippe Charnier 	    warnx("ERROR line %d: invalid partition number %d",
1088d98b1668SPhilippe Charnier 		    current_line_number, partition);
1089f46af505SJordan K. Hubbard 	    break;
1090f46af505SJordan K. Hubbard 	}
10914ddd60b9SBrian Somers 	partp = ((struct dos_partition *) &mboot.parts) + partition - 1;
1092f46af505SJordan K. Hubbard 	bzero((char *)partp, sizeof (struct dos_partition));
1093f46af505SJordan K. Hubbard 	partp->dp_typ = command->args[1].arg_val;
1094f46af505SJordan K. Hubbard 	partp->dp_start = command->args[2].arg_val;
1095f46af505SJordan K. Hubbard 	partp->dp_size = command->args[3].arg_val;
1096f46af505SJordan K. Hubbard 	max_end = partp->dp_start + partp->dp_size;
1097f46af505SJordan K. Hubbard 
1098f46af505SJordan K. Hubbard 	if (partp->dp_typ == 0)
1099f46af505SJordan K. Hubbard 	{
1100f46af505SJordan K. Hubbard 	    /*
1101f46af505SJordan K. Hubbard 	     * Get out, the partition is marked as unused.
1102f46af505SJordan K. Hubbard 	     */
1103f46af505SJordan K. Hubbard 	    /*
1104f46af505SJordan K. Hubbard 	     * Insure that it's unused.
1105f46af505SJordan K. Hubbard 	     */
1106f46af505SJordan K. Hubbard 	    bzero((char *)partp, sizeof (struct dos_partition));
1107f46af505SJordan K. Hubbard 	    status = 1;
1108f46af505SJordan K. Hubbard 	    break;
1109f46af505SJordan K. Hubbard 	}
1110f46af505SJordan K. Hubbard 
1111f46af505SJordan K. Hubbard 	/*
1112f46af505SJordan K. Hubbard 	 * Adjust start upwards, if necessary, to fall on an head boundary.
1113f46af505SJordan K. Hubbard 	 */
1114f46af505SJordan K. Hubbard 	if (partp->dp_start % dos_sectors != 0)
1115f46af505SJordan K. Hubbard 	{
1116f46af505SJordan K. Hubbard 	    adj_size =
1117f46af505SJordan K. Hubbard 		(partp->dp_start / dos_sectors + 1) * dos_sectors;
1118f46af505SJordan K. Hubbard 	    if (adj_size > max_end)
1119f46af505SJordan K. Hubbard 	    {
1120f46af505SJordan K. Hubbard 		/*
1121f46af505SJordan K. Hubbard 		 * Can't go past end of partition
1122f46af505SJordan K. Hubbard 		 */
1123d98b1668SPhilippe Charnier 		warnx(
1124d98b1668SPhilippe Charnier 	"ERROR line %d: unable to adjust start of partition %d to fall on\n\
1125d98b1668SPhilippe Charnier     a cylinder boundary",
1126d98b1668SPhilippe Charnier 			current_line_number, partition);
1127f46af505SJordan K. Hubbard 		break;
1128f46af505SJordan K. Hubbard 	    }
1129d98b1668SPhilippe Charnier 	    warnx(
1130d98b1668SPhilippe Charnier 	"WARNING: adjusting start offset of partition '%d' from %lu\n\
1131d98b1668SPhilippe Charnier     to %lu, to round to an head boundary",
1132d98b1668SPhilippe Charnier 		    partition, (u_long)partp->dp_start, adj_size);
1133f46af505SJordan K. Hubbard 	    partp->dp_start = adj_size;
1134f46af505SJordan K. Hubbard 	}
1135f46af505SJordan K. Hubbard 
1136f46af505SJordan K. Hubbard 	/*
1137f46af505SJordan K. Hubbard 	 * Adjust size downwards, if necessary, to fall on a cylinder
1138f46af505SJordan K. Hubbard 	 * boundary.
1139f46af505SJordan K. Hubbard 	 */
1140f46af505SJordan K. Hubbard 	chunks =
1141f46af505SJordan K. Hubbard 	    ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs;
1142f46af505SJordan K. Hubbard 	adj_size = chunks - partp->dp_start;
1143f46af505SJordan K. Hubbard 	if (adj_size != partp->dp_size)
1144f46af505SJordan K. Hubbard 	{
1145d98b1668SPhilippe Charnier 	    warnx(
1146d98b1668SPhilippe Charnier 	"WARNING: adjusting size of partition '%d' from %lu to %lu,\n\
1147d98b1668SPhilippe Charnier     to round to a cylinder boundary",
1148d98b1668SPhilippe Charnier 		    partition, (u_long)partp->dp_size, adj_size);
1149f46af505SJordan K. Hubbard 	    if (chunks > 0)
1150f46af505SJordan K. Hubbard 	    {
1151f46af505SJordan K. Hubbard 		partp->dp_size = adj_size;
1152f46af505SJordan K. Hubbard 	    }
1153f46af505SJordan K. Hubbard 	    else
1154f46af505SJordan K. Hubbard 	    {
1155f46af505SJordan K. Hubbard 		partp->dp_size = 0;
1156f46af505SJordan K. Hubbard 	    }
1157f46af505SJordan K. Hubbard 	}
1158f46af505SJordan K. Hubbard 	if (partp->dp_size < 1)
1159f46af505SJordan K. Hubbard 	{
1160d98b1668SPhilippe Charnier 	    warnx("ERROR line %d: size for partition '%d' is zero",
1161d98b1668SPhilippe Charnier 		    current_line_number, partition);
1162f46af505SJordan K. Hubbard 	    break;
1163f46af505SJordan K. Hubbard 	}
1164f46af505SJordan K. Hubbard 
1165f46af505SJordan K. Hubbard 	dos(partp->dp_start, partp->dp_size,
1166f46af505SJordan K. Hubbard 	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
1167f46af505SJordan K. Hubbard 	dos(partp->dp_start+partp->dp_size - 1, partp->dp_size,
1168f46af505SJordan K. Hubbard 	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
1169f46af505SJordan K. Hubbard 	status = 1;
1170f46af505SJordan K. Hubbard 	break;
1171f46af505SJordan K. Hubbard     }
1172f46af505SJordan K. Hubbard     return (status);
1173f46af505SJordan K. Hubbard }
1174f46af505SJordan K. Hubbard 
1175f46af505SJordan K. Hubbard 
1176f46af505SJordan K. Hubbard static int
1177f46af505SJordan K. Hubbard process_active(command)
1178f46af505SJordan K. Hubbard     CMD		*command;
1179f46af505SJordan K. Hubbard {
1180f46af505SJordan K. Hubbard     int				status = 0, partition, i;
1181f46af505SJordan K. Hubbard     struct dos_partition	*partp;
1182f46af505SJordan K. Hubbard 
1183f46af505SJordan K. Hubbard     while (1)
1184f46af505SJordan K. Hubbard     {
1185f46af505SJordan K. Hubbard 	active_processed = 1;
1186f46af505SJordan K. Hubbard 	if (command->n_args != 1)
1187f46af505SJordan K. Hubbard 	{
1188d98b1668SPhilippe Charnier 	    warnx("ERROR line %d: incorrect number of active args",
1189d98b1668SPhilippe Charnier 		    current_line_number);
1190f46af505SJordan K. Hubbard 	    status = 0;
1191f46af505SJordan K. Hubbard 	    break;
1192f46af505SJordan K. Hubbard 	}
1193f46af505SJordan K. Hubbard 	partition = command->args[0].arg_val;
11944ddd60b9SBrian Somers 	if (partition < 1 || partition > 4)
1195f46af505SJordan K. Hubbard 	{
1196d98b1668SPhilippe Charnier 	    warnx("ERROR line %d: invalid partition number %d",
1197d98b1668SPhilippe Charnier 		    current_line_number, partition);
1198f46af505SJordan K. Hubbard 	    break;
1199f46af505SJordan K. Hubbard 	}
1200f46af505SJordan K. Hubbard 	/*
1201f46af505SJordan K. Hubbard 	 * Reset active partition
1202f46af505SJordan K. Hubbard 	 */
1203f46af505SJordan K. Hubbard 	partp = ((struct dos_partition *) &mboot.parts);
1204f46af505SJordan K. Hubbard 	for (i = 0; i < NDOSPART; i++)
1205f46af505SJordan K. Hubbard 	    partp[i].dp_flag = 0;
12064ddd60b9SBrian Somers 	partp[partition-1].dp_flag = ACTIVE;
1207f46af505SJordan K. Hubbard 
1208f46af505SJordan K. Hubbard 	status = 1;
1209f46af505SJordan K. Hubbard 	break;
1210f46af505SJordan K. Hubbard     }
1211f46af505SJordan K. Hubbard     return (status);
1212f46af505SJordan K. Hubbard }
1213f46af505SJordan K. Hubbard 
1214f46af505SJordan K. Hubbard 
1215f46af505SJordan K. Hubbard static int
1216f46af505SJordan K. Hubbard process_line(line)
1217f46af505SJordan K. Hubbard     char	*line;
1218f46af505SJordan K. Hubbard {
1219f46af505SJordan K. Hubbard     CMD		command;
1220f46af505SJordan K. Hubbard     int		status = 1;
1221f46af505SJordan K. Hubbard 
1222f46af505SJordan K. Hubbard     while (1)
1223f46af505SJordan K. Hubbard     {
1224f46af505SJordan K. Hubbard 	parse_config_line(line, &command);
1225f46af505SJordan K. Hubbard 	switch (command.cmd)
1226f46af505SJordan K. Hubbard 	{
1227f46af505SJordan K. Hubbard 	case 0:
1228f46af505SJordan K. Hubbard 	    /*
1229f46af505SJordan K. Hubbard 	     * Comment or blank line
1230f46af505SJordan K. Hubbard 	     */
1231f46af505SJordan K. Hubbard 	    break;
1232f46af505SJordan K. Hubbard 	case 'g':
1233f46af505SJordan K. Hubbard 	    /*
1234f46af505SJordan K. Hubbard 	     * Set geometry
1235f46af505SJordan K. Hubbard 	     */
1236f46af505SJordan K. Hubbard 	    status = process_geometry(&command);
1237f46af505SJordan K. Hubbard 	    break;
1238f46af505SJordan K. Hubbard 	case 'p':
1239f46af505SJordan K. Hubbard 	    status = process_partition(&command);
1240f46af505SJordan K. Hubbard 	    break;
1241f46af505SJordan K. Hubbard 	case 'a':
1242f46af505SJordan K. Hubbard 	    status = process_active(&command);
1243f46af505SJordan K. Hubbard 	    break;
1244f46af505SJordan K. Hubbard 	default:
1245f46af505SJordan K. Hubbard 	    status = 0;
1246f46af505SJordan K. Hubbard 	    break;
1247f46af505SJordan K. Hubbard 	}
1248f46af505SJordan K. Hubbard 	break;
1249f46af505SJordan K. Hubbard     }
1250f46af505SJordan K. Hubbard     return (status);
1251f46af505SJordan K. Hubbard }
1252f46af505SJordan K. Hubbard 
1253f46af505SJordan K. Hubbard 
1254f46af505SJordan K. Hubbard static int
1255f46af505SJordan K. Hubbard read_config(config_file)
1256f46af505SJordan K. Hubbard     char *config_file;
1257f46af505SJordan K. Hubbard {
1258f46af505SJordan K. Hubbard     FILE	*fp = NULL;
1259f46af505SJordan K. Hubbard     int		status = 1;
1260f46af505SJordan K. Hubbard     char	buf[1010];
1261f46af505SJordan K. Hubbard 
1262f46af505SJordan K. Hubbard     while (1)	/* dirty trick used to insure one exit point for this
1263f46af505SJordan K. Hubbard 		   function */
1264f46af505SJordan K. Hubbard     {
1265f46af505SJordan K. Hubbard 	if (strcmp(config_file, "-") != 0)
1266f46af505SJordan K. Hubbard 	{
1267f46af505SJordan K. Hubbard 	    /*
1268f46af505SJordan K. Hubbard 	     * We're not reading from stdin
1269f46af505SJordan K. Hubbard 	     */
1270f46af505SJordan K. Hubbard 	    if ((fp = fopen(config_file, "r")) == NULL)
1271f46af505SJordan K. Hubbard 	    {
1272f46af505SJordan K. Hubbard 		status = 0;
1273f46af505SJordan K. Hubbard 		break;
1274f46af505SJordan K. Hubbard 	    }
1275f46af505SJordan K. Hubbard 	}
1276f46af505SJordan K. Hubbard 	else
1277f46af505SJordan K. Hubbard 	{
1278f46af505SJordan K. Hubbard 	    fp = stdin;
1279f46af505SJordan K. Hubbard 	}
1280f46af505SJordan K. Hubbard 	current_line_number = 0;
1281f46af505SJordan K. Hubbard 	while (!feof(fp))
1282f46af505SJordan K. Hubbard 	{
1283f46af505SJordan K. Hubbard 	    if (fgets(buf, sizeof(buf), fp) == NULL)
1284f46af505SJordan K. Hubbard 	    {
1285f46af505SJordan K. Hubbard 		break;
1286f46af505SJordan K. Hubbard 	    }
1287f46af505SJordan K. Hubbard 	    ++current_line_number;
1288f46af505SJordan K. Hubbard 	    status = process_line(buf);
1289f46af505SJordan K. Hubbard 	    if (status == 0)
1290f46af505SJordan K. Hubbard 	    {
1291f46af505SJordan K. Hubbard 		break;
1292f46af505SJordan K. Hubbard 	    }
1293f46af505SJordan K. Hubbard 	}
1294f46af505SJordan K. Hubbard 	break;
1295f46af505SJordan K. Hubbard     }
1296f46af505SJordan K. Hubbard     if (fp)
1297f46af505SJordan K. Hubbard     {
1298f46af505SJordan K. Hubbard 	/*
1299f46af505SJordan K. Hubbard 	 * It doesn't matter if we're reading from stdin, as we've reached EOF
1300f46af505SJordan K. Hubbard 	 */
1301f46af505SJordan K. Hubbard 	fclose(fp);
1302f46af505SJordan K. Hubbard     }
1303f46af505SJordan K. Hubbard     return (status);
1304f46af505SJordan K. Hubbard }
1305f46af505SJordan K. Hubbard 
1306f46af505SJordan K. Hubbard 
1307f46af505SJordan K. Hubbard static void
1308f46af505SJordan K. Hubbard reset_boot(void)
1309f46af505SJordan K. Hubbard {
1310f46af505SJordan K. Hubbard     int				i;
1311f46af505SJordan K. Hubbard     struct dos_partition	*partp;
1312f46af505SJordan K. Hubbard 
1313f46af505SJordan K. Hubbard     init_boot();
1314f46af505SJordan K. Hubbard     for (i = 0; i < 4; ++i)
1315f46af505SJordan K. Hubbard     {
1316f46af505SJordan K. Hubbard 	partp = ((struct dos_partition *) &mboot.parts) + i;
1317f46af505SJordan K. Hubbard 	bzero((char *)partp, sizeof (struct dos_partition));
1318f46af505SJordan K. Hubbard     }
1319f46af505SJordan K. Hubbard }
1320