fdisk.c revision 3723
14Srgrimes/*
24Srgrimes * Mach Operating System
34Srgrimes * Copyright (c) 1992 Carnegie Mellon University
44Srgrimes * All Rights Reserved.
54Srgrimes *
64Srgrimes * Permission to use, copy, modify and distribute this software and its
74Srgrimes * documentation is hereby granted, provided that both the copyright
84Srgrimes * notice and this permission notice appear in all copies of the
94Srgrimes * software, derivative works or modified versions, and any portions
104Srgrimes * thereof, and that both notices appear in supporting documentation.
114Srgrimes *
124Srgrimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
134Srgrimes * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
144Srgrimes * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
154Srgrimes *
164Srgrimes * Carnegie Mellon requests users of this software to return to
174Srgrimes *
184Srgrimes *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
194Srgrimes *  School of Computer Science
204Srgrimes *  Carnegie Mellon University
214Srgrimes *  Pittsburgh PA 15213-3890
224Srgrimes *
234Srgrimes * any improvements or extensions that they make and grant Carnegie Mellon
244Srgrimes * the rights to redistribute these changes.
254Srgrimes */
264Srgrimes
274Srgrimes#include <sys/types.h>
284Srgrimes#include <sys/disklabel.h>
294Srgrimes#include <stdio.h>
304Srgrimes#include <sys/stat.h>
314Srgrimes#include <sys/ioctl.h>
324Srgrimes#include <fcntl.h>
334Srgrimes
344Srgrimesint iotest;
354Srgrimes
364Srgrimes#define LBUF 100
374Srgrimesstatic char lbuf[LBUF];
384Srgrimes
394Srgrimes/*
404Srgrimes *
414Srgrimes * Ported to 386bsd by Julian Elischer  Thu Oct 15 20:26:46 PDT 1992
424Srgrimes *
434Srgrimes * 14-Dec-89  Robert Baron (rvb) at Carnegie-Mellon University
444Srgrimes *	Copyright (c) 1989	Robert. V. Baron
454Srgrimes *	Created.
464Srgrimes */
474Srgrimes
484Srgrimes#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
494Srgrimes#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
504Srgrimes#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
514Srgrimes
524Srgrimes#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
534Srgrimes
544Srgrimes#define SECSIZE 512
554Srgrimes
564Srgrimeschar *disk = "/dev/rwd0d";
574Srgrimeschar *name;
584Srgrimes
594Srgrimesstruct disklabel disklabel;		/* disk parameters */
604Srgrimes
614Srgrimesint cyls, sectors, heads, cylsecs, disksecs;
624Srgrimes
634Srgrimesstruct mboot
644Srgrimes{
654Srgrimes	unsigned char padding[2]; /* force the longs to be long alligned */
664Srgrimes	unsigned char bootinst[DOSPARTOFF];
674Srgrimes	struct	dos_partition parts[4];
684Srgrimes	unsigned short int	signature;
694Srgrimes};
704Srgrimesstruct mboot mboot;
714Srgrimes
724Srgrimes#define ACTIVE 0x80
734Srgrimes#define BOOT_MAGIC 0xAA55
744Srgrimes
754Srgrimesint dos_cyls;
764Srgrimesint dos_heads;
774Srgrimesint dos_sectors;
784Srgrimesint dos_cylsecs;
794Srgrimes
804Srgrimes#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
814Srgrimes#define DOSCYL(c)	(c & 0xff)
824Srgrimesstatic int dos();
834Srgrimeschar *get_type();
844Srgrimesstatic int partition = -1;
854Srgrimes
864Srgrimes
874Srgrimesstatic int a_flag  = 0;		/* set active partition */
884Srgrimesstatic int i_flag  = 0;		/* replace partition data */
894Srgrimesstatic int u_flag  = 0;		/* update partition data */
904Srgrimes
914Srgrimesstatic unsigned char bootcode[] = {
924Srgrimes0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
934Srgrimes0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
944Srgrimes0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
954Srgrimes0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
964Srgrimes0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
974Srgrimes0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
984Srgrimes0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
994Srgrimes0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
1004Srgrimes0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
1014Srgrimes'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
1024Srgrimes	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
1034Srgrimes'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
1044Srgrimes	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
1054Srgrimes'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
1064Srgrimes	'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
1074Srgrimes'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
1084Srgrimes	'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
1094Srgrimes
1104Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1114Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1124Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1134Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1144Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1154Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1164Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1174Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1184Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1194Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1204Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1214Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
1224Srgrimes  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
1234Srgrimes};
1244Srgrimes
1254Srgrimesstruct part_type
1264Srgrimes{
1274Srgrimes unsigned char type;
1284Srgrimes char *name;
1294Srgrimes}part_types[] =
1304Srgrimes{
1314Srgrimes	 {0x00, "unused"}
1324Srgrimes	,{0x01, "Primary DOS with 12 bit FAT"}
1334Srgrimes	,{0x02, "XENIX / filesystem"}
1344Srgrimes	,{0x03, "XENIX /usr filesystem"}
1354Srgrimes	,{0x04, "Primary DOS with 16 bit FAT"}
1364Srgrimes	,{0x05, "Extended DOS"}
1374Srgrimes	,{0x06, "Primary 'big' DOS (> 32MB)"}
1384Srgrimes	,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"}
1394Srgrimes	,{0x08, "AIX filesystem"}
1404Srgrimes	,{0x09, "AIX boot partition or Coherent"}
1414Srgrimes	,{0x0A, "OS/2 Boot Manager or OPUS"}
1424Srgrimes	,{0x10, "OPUS"}
1434Srgrimes	,{0x40, "VENIX 286"}
1444Srgrimes	,{0x50, "DM"}
1454Srgrimes	,{0x51, "DM"}
1464Srgrimes	,{0x52, "CP/M or Microport SysV/AT"}
1474Srgrimes	,{0x56, "GB"}
1484Srgrimes	,{0x61, "Speed"}
1494Srgrimes	,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
1504Srgrimes	,{0x64, "Novell Netware 2.xx"}
1514Srgrimes	,{0x65, "Novell Netware 3.xx"}
1524Srgrimes	,{0x75, "PCIX"}
1534Srgrimes	,{0x80, "Minix 1.1 ... 1.4a"}
1544Srgrimes	,{0x81, "Minix 1.4b ... 1.5.10"}
1554Srgrimes	,{0x82, "Linux"}
1564Srgrimes	,{0x93, "Amoeba filesystem"}
1574Srgrimes	,{0x94, "Amoeba bad block table"}
1584Srgrimes	,{0xA5, "386BSD"}
1594Srgrimes	,{0xB7, "BSDI BSD/386 filesystem"}
1604Srgrimes	,{0xB8, "BSDI BSD/386 swap"}
1614Srgrimes	,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
1624Srgrimes	,{0xE1, "Speed"}
1634Srgrimes	,{0xE3, "Speed"}
1644Srgrimes	,{0xE4, "Speed"}
1654Srgrimes	,{0xF1, "Speed"}
1664Srgrimes	,{0xF2, "DOS 3.3+ Secondary"}
1674Srgrimes	,{0xF4, "Speed"}
1684Srgrimes	,{0xFF, "BBT (Bad Blocks Table)"}
1694Srgrimes};
1704Srgrimes
1714Srgrimes
1724Srgrimesmain(argc, argv)
1734Srgrimeschar **argv;
1744Srgrimes{
1754Srgrimesint	i;
1764Srgrimes
1774Srgrimes	name = *argv;
1784Srgrimes	{register char *cp = name;
1794Srgrimes		while (*cp) if (*cp++ == '/') name = cp;
1804Srgrimes	}
1814Srgrimes
1824Srgrimes	for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
1834Srgrimes		if (*token++ != '-' || !*token)
1844Srgrimes			break;
1854Srgrimes		else { register int flag;
1864Srgrimes			for ( ; flag = *token++ ; ) {
1874Srgrimes				switch (flag) {
1884Srgrimes				case '0':
1894Srgrimes					partition = 0;
1904Srgrimes					break;
1914Srgrimes				case '1':
1924Srgrimes					partition = 1;
1934Srgrimes					break;
1944Srgrimes				case '2':
1954Srgrimes					partition = 2;
1964Srgrimes					break;
1974Srgrimes				case '3':
1984Srgrimes					partition = 3;
1994Srgrimes					break;
2004Srgrimes				case 'a':
2014Srgrimes					a_flag = 1;
2024Srgrimes					break;
2034Srgrimes				case 'i':
2044Srgrimes					i_flag = 1;
2054Srgrimes				case 'u':
2064Srgrimes					u_flag = 1;
2074Srgrimes					break;
2084Srgrimes				default:
2094Srgrimes					goto usage;
2104Srgrimes				}
2114Srgrimes			}
2124Srgrimes		}
2134Srgrimes	}
2144Srgrimes
2154Srgrimes	if (argc > 0)
2164Srgrimes		disk = argv[0];
2174Srgrimes
2184Srgrimes	if (open_disk(u_flag) < 0)
2194Srgrimes		exit(1);
2204Srgrimes
2214Srgrimes	printf("******* Working on device %s *******\n",disk);
2224Srgrimes	if(u_flag)
2234Srgrimes	{
2244Srgrimes		get_params_to_use();
2254Srgrimes	}
2264Srgrimes	else
2274Srgrimes	{
2284Srgrimes		print_params();
2294Srgrimes	}
2304Srgrimes
2314Srgrimes	if (read_s0())
2324Srgrimes		init_sector0(1);
2334Srgrimes
2344Srgrimes	printf("Warning: BIOS sector numbering starts with sector 1\n");
2354Srgrimes	printf("Information from DOS bootblock is:\n");
2364Srgrimes	if (partition == -1)
2374Srgrimes		for (i = 0; i < NDOSPART; i++)
2384Srgrimes			change_part(i);
2394Srgrimes	else
2404Srgrimes		change_part(partition);
2414Srgrimes
2424Srgrimes	if (u_flag || a_flag)
2434Srgrimes		change_active(partition);
2444Srgrimes
2454Srgrimes	if (u_flag || a_flag) {
2464Srgrimes		printf("\nWe haven't changed the partition table yet.  ");
2474Srgrimes		printf("This is your last chance.\n");
2484Srgrimes		print_s0(-1);
2494Srgrimes		if (ok("Should we write new partition table?"))
2504Srgrimes			write_s0();
2514Srgrimes	}
2524Srgrimes
2534Srgrimes	exit(0);
2544Srgrimes
2554Srgrimesusage:
2564Srgrimes	printf("fdisk {-a|-i|-r} {disk}\n");
2574Srgrimes}
2584Srgrimes
2594Srgrimesprint_s0(which)
2604Srgrimes{
2614Srgrimesint	i;
2624Srgrimes
2634Srgrimes	print_params();
2644Srgrimes	printf("Information from DOS bootblock is:\n");
2654Srgrimes	if (which == -1)
2664Srgrimes		for (i = 0; i < NDOSPART; i++)
2674Srgrimes			printf("%d: ", i), print_part(i);
2684Srgrimes	else
2694Srgrimes		print_part(which);
2704Srgrimes}
2714Srgrimes
2724Srgrimesstatic struct dos_partition mtpart = { 0 };
2734Srgrimes
2744Srgrimesprint_part(i)
2754Srgrimes{
2764Srgrimesstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
2774Srgrimes
2784Srgrimes
2794Srgrimes	if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
2804Srgrimes		printf("<UNUSED>\n");
2814Srgrimes		return;
2824Srgrimes	}
2834Srgrimes	printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
2844Srgrimes	printf("    start %d, size %d (%d Meg), flag %x\n",
2854Srgrimes		partp->dp_start,
2864Srgrimes		partp->dp_size, partp->dp_size * 512 / (1024 * 1024),
2874Srgrimes		partp->dp_flag);
2884Srgrimes	printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
2894Srgrimes		,DPCYL(partp->dp_scyl, partp->dp_ssect)
2904Srgrimes		,DPSECT(partp->dp_ssect)
2914Srgrimes		,partp->dp_shd
2924Srgrimes		,DPCYL(partp->dp_ecyl, partp->dp_esect)
2934Srgrimes		,DPSECT(partp->dp_esect)
2944Srgrimes		,partp->dp_ehd);
2954Srgrimes}
2964Srgrimes
2974Srgrimesinit_sector0(start)
2984Srgrimes{
2994Srgrimesstruct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
3004Srgrimesint size = disksecs - start;
3014Srgrimesint rest;
3024Srgrimes
3034Srgrimes	memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
3044Srgrimes	mboot.signature = BOOT_MAGIC;
3054Srgrimes
3064Srgrimes	partp->dp_typ = DOSPTYP_386BSD;
3074Srgrimes	partp->dp_flag = ACTIVE;
3084Srgrimes	partp->dp_start = start;
3094Srgrimes	partp->dp_size = size;
3104Srgrimes
3114Srgrimes	dos(partp->dp_start, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
3124Srgrimes	dos(partp->dp_start+partp->dp_size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
3134Srgrimes}
3144Srgrimes
3154Srgrimeschange_part(i)
3164Srgrimes{
3174Srgrimesstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
3184Srgrimes
3194Srgrimes    printf("The data for partition %d is:\n", i);
3204Srgrimes    print_part(i);
3214Srgrimes
3224Srgrimes    if (u_flag && ok("Do you want to change it?")) {
3234Srgrimes	int tmp;
3244Srgrimes
3254Srgrimes	if (i_flag) {
3264Srgrimes		bzero((char *)partp, sizeof (struct dos_partition));
3274Srgrimes		if (i == 3) {
3284Srgrimes			init_sector0(1);
3294Srgrimes			printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
3304Srgrimes			print_part(i);
3314Srgrimes		}
3324Srgrimes	}
3334Srgrimes
3344Srgrimes	do {
3354Srgrimes		Decimal("sysid", partp->dp_typ, tmp);
3364Srgrimes		Decimal("start", partp->dp_start, tmp);
3374Srgrimes		Decimal("size", partp->dp_size, tmp);
3384Srgrimes
3394Srgrimes		if (ok("Explicitly specifiy beg/end address ?"))
3404Srgrimes		{
3414Srgrimes			int	tsec,tcyl,thd;
3424Srgrimes			tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
3434Srgrimes			thd = partp->dp_shd;
3444Srgrimes			tsec = DPSECT(partp->dp_ssect);
3454Srgrimes			Decimal("beginning cylinder", tcyl, tmp);
3464Srgrimes			Decimal("beginning head", thd, tmp);
3474Srgrimes			Decimal("beginning sector", tsec, tmp);
3484Srgrimes			partp->dp_scyl = DOSCYL(tcyl);
3494Srgrimes			partp->dp_ssect = DOSSECT(tsec,tcyl);
3504Srgrimes			partp->dp_shd = thd;
3514Srgrimes
3524Srgrimes			tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
3534Srgrimes			thd = partp->dp_ehd;
3544Srgrimes			tsec = DPSECT(partp->dp_esect);
3554Srgrimes			Decimal("ending cylinder", tcyl, tmp);
3564Srgrimes			Decimal("ending head", thd, tmp);
3574Srgrimes			Decimal("ending sector", tsec, tmp);
3584Srgrimes			partp->dp_ecyl = DOSCYL(tcyl);
3594Srgrimes			partp->dp_esect = DOSSECT(tsec,tcyl);
3604Srgrimes			partp->dp_ehd = thd;
3614Srgrimes		} else {
3624Srgrimes			dos(partp->dp_start,
3634Srgrimes				&partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
3644Srgrimes			dos(partp->dp_start+partp->dp_size - 1,
3654Srgrimes				&partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
3664Srgrimes		}
3674Srgrimes
3684Srgrimes		print_part(i);
3694Srgrimes	} while (!ok("Are we happy with this entry?"));
3704Srgrimes    }
3714Srgrimes}
3724Srgrimes
3734Srgrimesprint_params()
3744Srgrimes{
3754Srgrimes	printf("parameters extracted from in-core disklabel are:\n");
3764Srgrimes	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
3774Srgrimes			,cyls,heads,sectors,cylsecs);
3784Srgrimes	if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
3794Srgrimes		printf(" Figures below won't work with BIOS for partitions not in cyl 1\n");
3804Srgrimes	printf("parameters to be used for BIOS calculations are:\n");
3814Srgrimes	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
3824Srgrimes		,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
3834Srgrimes}
3844Srgrimes
3854Srgrimeschange_active(which)
3864Srgrimes{
3874Srgrimesint i;
3884Srgrimesint active = 3, tmp;
3894Srgrimesstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
3904Srgrimes
3914Srgrimes	if (a_flag && which != -1)
3924Srgrimes		active = which;
3933723Sbde	if (!ok("Do you want to change the active partition?"))
3943723Sbde		return;
3953723Sbde	do
3963723Sbde		Decimal("active partition", active, tmp);
3973723Sbde	while (!ok("Are you happy with this choice"));
3984Srgrimes	for (i = 0; i < NDOSPART; i++)
3994Srgrimes		partp[i].dp_flag = 0;
4004Srgrimes	partp[active].dp_flag = ACTIVE;
4014Srgrimes}
4024Srgrimes
4034Srgrimesget_params_to_use()
4044Srgrimes{
4054Srgrimes	int	tmp;
4064Srgrimes	print_params();
4074Srgrimes	if (ok("Do you want to change our idea of what BIOS thinks ?"))
4084Srgrimes	{
4094Srgrimes		do
4104Srgrimes		{
4114Srgrimes			Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
4124Srgrimes			Decimal("BIOS's idea of #heads", dos_heads, tmp);
4134Srgrimes			Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
4144Srgrimes			dos_cylsecs = dos_heads * dos_sectors;
4154Srgrimes			print_params();
4164Srgrimes		}
4174Srgrimes		while(!ok("Are you happy with this choice"));
4184Srgrimes	}
4194Srgrimes}
4204Srgrimes
4214Srgrimes/***********************************************\
4224Srgrimes* Change real numbers into strange dos numbers	*
4234Srgrimes\***********************************************/
4244Srgrimesstatic
4254Srgrimesdos(sec, c, s, h)
4264Srgrimesint sec;
4274Srgrimesunsigned char *c, *s, *h;
4284Srgrimes{
4294Srgrimesint cy;
4304Srgrimesint hd;
4314Srgrimes
4323723Sbde	if (sec == 0) {
4333723Sbde		*s = *c = *h = 0;
4343723Sbde		return;
4353723Sbde	}
4363723Sbde
4374Srgrimes	cy = sec / ( dos_cylsecs );
4384Srgrimes	sec = sec - cy * ( dos_cylsecs );
4394Srgrimes
4404Srgrimes	hd = sec / dos_sectors;
4414Srgrimes	sec = (sec - hd * dos_sectors) + 1;
4424Srgrimes
4434Srgrimes	*h = hd;
4444Srgrimes	*c = cy & 0xff;
4454Srgrimes	*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
4464Srgrimes}
4474Srgrimes
4484Srgrimesint fd;
4494Srgrimes
4504Srgrimes	/* Getting device status */
4514Srgrimes
4524Srgrimesopen_disk(u_flag)
4534Srgrimes{
4544Srgrimesstruct stat 	st;
4554Srgrimes
4564Srgrimes	if (stat(disk, &st) == -1) {
4574Srgrimes		fprintf(stderr, "%s: Can't get file status of %s\n",
4584Srgrimes			name, disk);
4594Srgrimes		return -1;
4602810Sbde	}
4612810Sbde	if ( !(st.st_mode & S_IFCHR) )
4624Srgrimes		fprintf(stderr,"%s: Device %s is not character special\n",
4634Srgrimes			name, disk);
4643723Sbde	if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) {
4654Srgrimes		fprintf(stderr,"%s: Can't open device %s\n", name, disk);
4664Srgrimes		return -1;
4674Srgrimes	}
4684Srgrimes	if (get_params(0) == -1) {
4694Srgrimes		fprintf(stderr, "%s: Can't get disk parameters on %s\n",
4704Srgrimes			name, disk);
4714Srgrimes		return -1;
4724Srgrimes	}
4734Srgrimes	return fd;
4744Srgrimes}
4754Srgrimes
4764Srgrimes
4774Srgrimesread_disk(sector, buf)
4784Srgrimes{
4794Srgrimes	lseek(fd,(sector * 512), 0);
4804Srgrimes	return read(fd, buf, 512);
4814Srgrimes}
4824Srgrimes
4834Srgrimeswrite_disk(sector, buf)
4844Srgrimes{
4854Srgrimes	lseek(fd,(sector * 512), 0);
4864Srgrimes	return write(fd, buf, 512);
4874Srgrimes}
4884Srgrimes
4894Srgrimesget_params(verbose)
4904Srgrimes{
4914Srgrimes
4924Srgrimes    if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
4932810Sbde	fprintf(stderr,
4942810Sbde		"%s: Can't get disk parameters on %s; supplying dummy ones\n",
4952810Sbde		name, disk);
4962810Sbde	dos_cyls = cyls = 1;
4972810Sbde	dos_heads = heads = 1;
4982810Sbde	dos_sectors = sectors = 1;
4992810Sbde	dos_cylsecs = cylsecs = heads * sectors;
5002810Sbde	disksecs = cyls * heads * sectors;
5012810Sbde	return disksecs;
5024Srgrimes    }
5034Srgrimes
5044Srgrimes    dos_cyls = cyls = disklabel.d_ncylinders;
5054Srgrimes    dos_heads = heads = disklabel.d_ntracks;
5064Srgrimes    dos_sectors = sectors = disklabel.d_nsectors;
5074Srgrimes    dos_cylsecs = cylsecs = heads * sectors;
5084Srgrimes    disksecs = cyls * heads * sectors;
5094Srgrimes
5104Srgrimes    return (disksecs);
5114Srgrimes}
5124Srgrimes
5134Srgrimes
5144Srgrimesread_s0()
5154Srgrimes{
5164Srgrimes	if (read_disk(0, (char *) mboot.bootinst) == -1) {
5174Srgrimes		fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
5184Srgrimes		return -1;
5194Srgrimes	}
5204Srgrimes	if (mboot.signature != BOOT_MAGIC) {
5214Srgrimes		fprintf(stderr, "%s: Invalid fdisk partition table found\n",
5224Srgrimes			name);
5234Srgrimes		/* So should we initialize things */
5244Srgrimes		return -1;
5254Srgrimes	}
5264Srgrimes	return 0;
5274Srgrimes}
5284Srgrimes
5294Srgrimeswrite_s0()
5304Srgrimes{
5314Srgrimes	int	flag;
5324Srgrimes	if (iotest) {
5334Srgrimes		print_s0(-1);
5344Srgrimes		return 0;
5354Srgrimes	}
5364Srgrimes	/*
5374Srgrimes	 * write enable label sector before write (if necessary),
5384Srgrimes	 * disable after writing.
5394Srgrimes	 * needed if the disklabel protected area also protects
5404Srgrimes	 * sector 0. (e.g. empty disk)
5414Srgrimes	 */
5424Srgrimes	flag = 1;
5434Srgrimes	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
5444Srgrimes		perror("ioctl DIOCWLABEL");
5454Srgrimes	if (write_disk(0, (char *) mboot.bootinst) == -1) {
5464Srgrimes		fprintf(stderr, "%s: Can't write fdisk partition table\n",
5474Srgrimes			name);
5484Srgrimes		return -1;
5494Srgrimes	flag = 0;
5504Srgrimes	(void) ioctl(fd, DIOCWLABEL, &flag);
5514Srgrimes	}
5524Srgrimes}
5534Srgrimes
5544Srgrimes
5554Srgrimes
5564Srgrimesok(str)
5574Srgrimeschar *str;
5584Srgrimes{
5594Srgrimes	printf("%s [n] ", str);
5604Srgrimes	fgets(lbuf, LBUF, stdin);
5614Srgrimes	lbuf[strlen(lbuf)-1] = 0;
5624Srgrimes
5634Srgrimes	if (*lbuf &&
5644Srgrimes		(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
5654Srgrimes		 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
5664Srgrimes		return 1;
5674Srgrimes	else
5684Srgrimes		return 0;
5694Srgrimes}
5704Srgrimes
5714Srgrimesdecimal(str, num, deflt)
5724Srgrimeschar *str;
5734Srgrimesint *num;
5744Srgrimes{
5754Srgrimesint acc = 0, c;
5764Srgrimeschar *cp;
5774Srgrimes
5784Srgrimes	while (1) {
5794Srgrimes		printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
5804Srgrimes		fgets(lbuf, LBUF, stdin);
5814Srgrimes		lbuf[strlen(lbuf)-1] = 0;
5824Srgrimes
5834Srgrimes		if (!*lbuf)
5844Srgrimes			return 0;
5854Srgrimes
5864Srgrimes		cp = lbuf;
5874Srgrimes		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
5884Srgrimes		if (!c)
5894Srgrimes			return 0;
5904Srgrimes		while (c = *cp++) {
5914Srgrimes			if (c <= '9' && c >= '0')
5924Srgrimes				acc = acc * 10 + c - '0';
5934Srgrimes			else
5944Srgrimes				break;
5954Srgrimes		}
5964Srgrimes		if (c == ' ' || c == '\t')
5974Srgrimes			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
5984Srgrimes		if (!c) {
5994Srgrimes			*num = acc;
6004Srgrimes			return 1;
6014Srgrimes		} else
6024Srgrimes			printf("%s is an invalid decimal number.  Try again\n",
6034Srgrimes				lbuf);
6044Srgrimes	}
6054Srgrimes
6064Srgrimes}
6074Srgrimes
6084Srgrimeshex(str, num, deflt)
6094Srgrimeschar *str;
6104Srgrimesint *num;
6114Srgrimes{
6124Srgrimesint acc = 0, c;
6134Srgrimeschar *cp;
6144Srgrimes
6154Srgrimes	while (1) {
6164Srgrimes		printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
6174Srgrimes		fgets(lbuf, LBUF, stdin);
6184Srgrimes		lbuf[strlen(lbuf)-1] = 0;
6194Srgrimes
6204Srgrimes		if (!*lbuf)
6214Srgrimes			return 0;
6224Srgrimes
6234Srgrimes		cp = lbuf;
6244Srgrimes		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
6254Srgrimes		if (!c)
6264Srgrimes			return 0;
6274Srgrimes		while (c = *cp++) {
6284Srgrimes			if (c <= '9' && c >= '0')
6294Srgrimes				acc = (acc << 4) + c - '0';
6304Srgrimes			else if (c <= 'f' && c >= 'a')
6314Srgrimes				acc = (acc << 4) + c - 'a' + 10;
6324Srgrimes			else if (c <= 'F' && c >= 'A')
6334Srgrimes				acc = (acc << 4) + c - 'A' + 10;
6344Srgrimes			else
6354Srgrimes				break;
6364Srgrimes		}
6374Srgrimes		if (c == ' ' || c == '\t')
6384Srgrimes			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
6394Srgrimes		if (!c) {
6404Srgrimes			*num = acc;
6414Srgrimes			return 1;
6424Srgrimes		} else
6434Srgrimes			printf("%s is an invalid hex number.  Try again\n",
6444Srgrimes				lbuf);
6454Srgrimes	}
6464Srgrimes
6474Srgrimes}
6484Srgrimes
6494Srgrimesstring(str, ans)
6504Srgrimeschar *str;
6514Srgrimeschar **ans;
6524Srgrimes{
6534Srgrimesint c;
6544Srgrimeschar *cp = lbuf;
6554Srgrimes
6564Srgrimes	while (1) {
6574Srgrimes		printf("Supply a string value for \"%s\" [%s] ", str, *ans);
6584Srgrimes		fgets(lbuf, LBUF, stdin);
6594Srgrimes		lbuf[strlen(lbuf)-1] = 0;
6604Srgrimes
6614Srgrimes		if (!*lbuf)
6624Srgrimes			return 0;
6634Srgrimes
6644Srgrimes		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
6654Srgrimes		if (c == '"') {
6664Srgrimes			c = *++cp;
6674Srgrimes			*ans = cp;
6684Srgrimes			while ((c = *cp) && c != '"') cp++;
6694Srgrimes		} else {
6704Srgrimes			*ans = cp;
6714Srgrimes			while ((c = *cp) && c != ' ' && c != '\t') cp++;
6724Srgrimes		}
6734Srgrimes
6744Srgrimes		if (c)
6754Srgrimes			*cp = 0;
6764Srgrimes		return 1;
6774Srgrimes	}
6784Srgrimes}
6794Srgrimes
6804Srgrimeschar *get_type(type)
6814Srgrimesint	type;
6824Srgrimes{
6834Srgrimes	int	numentries = (sizeof(part_types)/sizeof(struct part_type));
6844Srgrimes	int	counter = 0;
6854Srgrimes	struct	part_type *ptr = part_types;
6864Srgrimes
6874Srgrimes
6884Srgrimes	while(counter < numentries)
6894Srgrimes	{
6904Srgrimes		if(ptr->type == type)
6914Srgrimes		{
6924Srgrimes			return(ptr->name);
6934Srgrimes		}
6944Srgrimes		ptr++;
6954Srgrimes		counter++;
6964Srgrimes	}
6974Srgrimes	return("unknown");
6984Srgrimes}
699