xref: /onnv-gate/usr/src/cmd/fdisk/fdisk.c (revision 251:b12a6b02566e)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*251Slclee  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
280Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
290Sstevel@tonic-gate /*	  All Rights Reserved	*/
300Sstevel@tonic-gate 
310Sstevel@tonic-gate /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
320Sstevel@tonic-gate /*	  All Rights Reserved	*/
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
350Sstevel@tonic-gate 
360Sstevel@tonic-gate /*
370Sstevel@tonic-gate  * PROGRAM: fdisk(1M)
380Sstevel@tonic-gate  * This program reads the partition table on the specified device and
390Sstevel@tonic-gate  * also reads the drive parameters. The user can perform various
400Sstevel@tonic-gate  * operations from a supplied menu or from the command line. Diagnostic
410Sstevel@tonic-gate  * options are also available.
420Sstevel@tonic-gate  */
430Sstevel@tonic-gate 
440Sstevel@tonic-gate #include <stdio.h>
450Sstevel@tonic-gate #include <stdlib.h>
460Sstevel@tonic-gate #include <string.h>
470Sstevel@tonic-gate #include <unistd.h>
480Sstevel@tonic-gate #include <errno.h>
490Sstevel@tonic-gate #include <fcntl.h>
500Sstevel@tonic-gate #include <ctype.h>
510Sstevel@tonic-gate #include <sys/stat.h>
520Sstevel@tonic-gate #include <sys/types.h>
530Sstevel@tonic-gate #include <sys/param.h>
540Sstevel@tonic-gate #include <sys/systeminfo.h>
550Sstevel@tonic-gate #include <sys/efi_partition.h>
560Sstevel@tonic-gate #include <sys/byteorder.h>
570Sstevel@tonic-gate #include <sys/systeminfo.h>
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
600Sstevel@tonic-gate #include <sys/dkio.h>
610Sstevel@tonic-gate #include <sys/vtoc.h>
620Sstevel@tonic-gate 
630Sstevel@tonic-gate #define	CLR_SCR ""
640Sstevel@tonic-gate #define	CLR_LIN ""
650Sstevel@tonic-gate #define	HOME "" \
660Sstevel@tonic-gate 	""
670Sstevel@tonic-gate #define	Q_LINE ""
680Sstevel@tonic-gate #define	W_LINE ""
690Sstevel@tonic-gate #define	E_LINE ""
700Sstevel@tonic-gate #define	M_LINE "" \
710Sstevel@tonic-gate 	""
720Sstevel@tonic-gate #define	T_LINE ""
730Sstevel@tonic-gate 
740Sstevel@tonic-gate #define	DEFAULT_PATH	"/dev/rdsk/"
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /* XXX - should be in fdisk.h, used by sd as well */
770Sstevel@tonic-gate 
780Sstevel@tonic-gate /*
790Sstevel@tonic-gate  * the MAX values are the maximum usable values for BIOS chs values
800Sstevel@tonic-gate  * The MAX_CYL value of 1022 is the maximum usable value
810Sstevel@tonic-gate  *   the value of 1023 is a fence value,
820Sstevel@tonic-gate  *   indicating no CHS geometry exists for the corresponding LBA value.
830Sstevel@tonic-gate  * HEAD range [ 0 .. MAX_HEAD ], so number of heads is (MAX_HEAD + 1)
840Sstevel@tonic-gate  * SECT range [ 1 .. MAX_SECT ], so number of sectors is (MAX_SECT)
850Sstevel@tonic-gate  */
860Sstevel@tonic-gate #define	MAX_SECT	(63)
870Sstevel@tonic-gate #define	MAX_CYL		(1022)
880Sstevel@tonic-gate #define	MAX_HEAD	(254)
890Sstevel@tonic-gate 
900Sstevel@tonic-gate /* for clear_vtoc() */
910Sstevel@tonic-gate #define	OLD		0
920Sstevel@tonic-gate #define	NEW		1
930Sstevel@tonic-gate 
940Sstevel@tonic-gate /* readvtoc/writevtoc return codes */
950Sstevel@tonic-gate #define	VTOC_OK		0	/* Good VTOC */
960Sstevel@tonic-gate #define	VTOC_INVAL	1	/* invalid VTOC */
970Sstevel@tonic-gate #define	VTOC_NOTSUP	2	/* operation not supported - EFI label */
980Sstevel@tonic-gate #define	VTOC_RWERR	3	/* couldn't read or write VTOC */
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate /*
1010Sstevel@tonic-gate  * Support for fdisk(1M) on the SPARC platform
1020Sstevel@tonic-gate  *	In order to convert little endian values to big endian for SPARC,
1030Sstevel@tonic-gate  *	byte/short and long values must be swapped.
1040Sstevel@tonic-gate  *	These swapping macros will be used to access information in the
1050Sstevel@tonic-gate  *	mboot and ipart structures.
1060Sstevel@tonic-gate  */
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate #ifdef sparc
1090Sstevel@tonic-gate #define	les(val)	((((val)&0xFF)<<8)|(((val)>>8)&0xFF))
1100Sstevel@tonic-gate #define	lel(val)	(((unsigned)(les((val)&0x0000FFFF))<<16) | \
1110Sstevel@tonic-gate 			    (les((unsigned)((val)&0xffff0000)>>16)))
1120Sstevel@tonic-gate #else
1130Sstevel@tonic-gate #define	les(val)	(val)
1140Sstevel@tonic-gate #define	lel(val)	(val)
1150Sstevel@tonic-gate #endif
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
1180Sstevel@tonic-gate #define	VTOC_OFFSET	512
1190Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_8)
1200Sstevel@tonic-gate #define	VTOC_OFFSET	0
1210Sstevel@tonic-gate #else
1220Sstevel@tonic-gate #error No VTOC format defined.
1230Sstevel@tonic-gate #endif
1240Sstevel@tonic-gate 
125*251Slclee static char Usage[] = "Usage: fdisk\n"
1260Sstevel@tonic-gate "[ -A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n"
1270Sstevel@tonic-gate "[ -b masterboot ]\n"
1280Sstevel@tonic-gate "[ -D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n"
1290Sstevel@tonic-gate "[ -F fdisk_file ] [ -h ] [ -o offset ] [ -P fill_patt ] [ -s size ]\n"
1300Sstevel@tonic-gate "[ -S geom_file ] [ [ -v ] -W { creat_fdisk_file | - } ]\n"
1310Sstevel@tonic-gate "[ -w | r | d | n | I | B | E | g | G | R | t | T ] rdevice";
1320Sstevel@tonic-gate 
133*251Slclee static char Usage1[] = "    Partition options:\n"
1340Sstevel@tonic-gate "	-A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n"
1350Sstevel@tonic-gate "		Create a partition with specific attributes:\n"
1360Sstevel@tonic-gate "		id      = system id number (fdisk.h) for the partition type\n"
1370Sstevel@tonic-gate "		act     = active partition flag (0 is off and 128 is on)\n"
1380Sstevel@tonic-gate "		bhead   = beginning head for start of partition\n"
1390Sstevel@tonic-gate "		bsect   = beginning sector for start of partition\n"
1400Sstevel@tonic-gate "		bcyl    = beginning cylinder for start of partition\n"
1410Sstevel@tonic-gate "		ehead   = ending head for end of partition\n"
1420Sstevel@tonic-gate "		esect   = ending sector for end of partition\n"
1430Sstevel@tonic-gate "		ecyl    = ending cylinder for end of partition\n"
1440Sstevel@tonic-gate "		rsect   = sector number from start of disk for\n"
1450Sstevel@tonic-gate "			  start of partition\n"
1460Sstevel@tonic-gate "		numsect = partition size in sectors\n"
1470Sstevel@tonic-gate "	-b master_boot\n"
1480Sstevel@tonic-gate "		Use master_boot as the master boot file.\n"
1490Sstevel@tonic-gate "	-B	Create one Solaris partition that uses the entire disk.\n"
1500Sstevel@tonic-gate "	-E	Create one EFI partition that uses the entire disk.\n"
1510Sstevel@tonic-gate "	-D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n"
1520Sstevel@tonic-gate "		Delete a partition. See attribute definitions for -A.\n"
1530Sstevel@tonic-gate "	-F fdisk_file\n"
1540Sstevel@tonic-gate "		Use fdisk_file to initialize on-line fdisk table.\n"
1550Sstevel@tonic-gate "	-I	Forego device checks. Generate a file image of what would go\n"
1560Sstevel@tonic-gate "		on a disk using the geometry specified with the -S option.\n"
1570Sstevel@tonic-gate "	-n	Do not run in interactive mode.\n"
1580Sstevel@tonic-gate "	-R	Open the disk device as read-only.\n"
1590Sstevel@tonic-gate "	-t	Check and adjust VTOC to be consistent with fdisk table.\n"
1600Sstevel@tonic-gate "		VTOC slices exceeding the partition size will be truncated.\n"
1610Sstevel@tonic-gate "	-T	Check and adjust VTOC to be consistent with fdisk table.\n"
1620Sstevel@tonic-gate "		VTOC slices exceeding the partition size will be removed.\n"
1630Sstevel@tonic-gate "	-W fdisk_file\n"
1640Sstevel@tonic-gate "		Write on-disk table to fdisk_file.\n"
1650Sstevel@tonic-gate "	-W -	Write on-disk table to standard output.\n"
1660Sstevel@tonic-gate "	-v	Display virtual geometry. Must be used with the -W option.\n"
1670Sstevel@tonic-gate "    Diagnostic options:\n"
1680Sstevel@tonic-gate "	-d	Activate debug information about progress.\n"
1690Sstevel@tonic-gate "	-g	Write label geometry to standard output:\n"
1700Sstevel@tonic-gate "		PCYL		number of physical cylinders\n"
1710Sstevel@tonic-gate "		NCYL		number of usable cylinders\n"
1720Sstevel@tonic-gate "		ACYL		number of alternate cylinders\n"
1730Sstevel@tonic-gate "		BCYL		cylinder offset\n"
1740Sstevel@tonic-gate "		NHEADS		number of heads\n"
1750Sstevel@tonic-gate "		NSECTORS	number of sectors per track\n"
1760Sstevel@tonic-gate "		SECTSIZ		size of a sector in bytes\n"
1770Sstevel@tonic-gate "	-G	Write physical geometry to standard output (see -g).\n"
1780Sstevel@tonic-gate "	-h	Issue this verbose help message.\n"
1790Sstevel@tonic-gate "	-o offset\n"
1800Sstevel@tonic-gate "		Block offset from start of disk (default 0). Ignored if\n"
1810Sstevel@tonic-gate "		-P # specified.\n"
1820Sstevel@tonic-gate "	-P fill_patt\n"
1830Sstevel@tonic-gate "		Fill disk with pattern fill_patt. fill_patt can be decimal or\n"
1840Sstevel@tonic-gate "		hexadecimal and is used as number for constant long word\n"
1850Sstevel@tonic-gate "		pattern. If fill_patt is \"#\" then pattern of block #\n"
1860Sstevel@tonic-gate "		for each block. Pattern is put in each block as long words\n"
1870Sstevel@tonic-gate "		and fills each block (see -o and -s).\n"
1880Sstevel@tonic-gate "	-r	Read from a disk to stdout (see -o and -s).\n"
1890Sstevel@tonic-gate "	-s size	Number of blocks on which to perform operation (see -o).\n"
1900Sstevel@tonic-gate "	-S geom_file\n"
1910Sstevel@tonic-gate "		Use geom_file to set the label geometry (see -g).\n"
1920Sstevel@tonic-gate "	-w	Write to a disk from stdin (see -o and -s).";
1930Sstevel@tonic-gate 
194*251Slclee static char Ostr[] = "Other OS";
195*251Slclee static char Dstr[] = "DOS12";
196*251Slclee static char D16str[] = "DOS16";
197*251Slclee static char DDstr[] = "DOS-DATA";
198*251Slclee static char EDstr[] = "EXT-DOS";
199*251Slclee static char DBstr[] = "DOS-BIG";
200*251Slclee static char PCstr[] = "PCIX";
201*251Slclee static char Ustr[] = "UNIX System";
202*251Slclee static char SUstr[] = "Solaris";
203*251Slclee static char SU2str[] = "Solaris2";
204*251Slclee static char X86str[] = "x86 Boot";
205*251Slclee static char DIAGstr[] = "Diagnostic";
206*251Slclee static char IFSstr[] = "IFS: NTFS";
207*251Slclee static char AIXstr[] = "AIX Boot";
208*251Slclee static char AIXDstr[] = "AIX Data";
209*251Slclee static char OS2str[] = "OS/2 Boot";
210*251Slclee static char WINstr[] = "Win95 FAT32";
211*251Slclee static char EWINstr[] = "Ext Win95";
212*251Slclee static char FAT95str[] = "FAT16 LBA";
213*251Slclee static char EXTLstr[] = "EXT LBA";
214*251Slclee static char LINUXstr[] = "Linux";
215*251Slclee static char CPMstr[] = "CP/M";
216*251Slclee static char NOVstr[] = "Netware 3.x+";
217*251Slclee static char QNXstr[] = "QNX 4.x";
218*251Slclee static char QNX2str[] = "QNX part 2";
219*251Slclee static char QNX3str[] = "QNX part 3";
220*251Slclee static char LINNATstr[] = "Linux native";
221*251Slclee static char NTFSVOL1str[] = "NT volset 1";
222*251Slclee static char NTFSVOL2str[] = "NT volset 2";
223*251Slclee static char BSDstr[] = "BSD OS";
224*251Slclee static char NEXTSTEPstr[] = "NeXTSTEP";
225*251Slclee static char BSDIFSstr[] = "BSDI FS";
226*251Slclee static char BSDISWAPstr[] = "BSDI swap";
227*251Slclee static char Actvstr[] = "Active";
228*251Slclee static char EFIstr[] = "EFI";
229*251Slclee static char NAstr[] = "      ";
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate /* All the user options and flags */
232*251Slclee static char *Dfltdev;			/* name of fixed disk drive */
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate /* Diagnostic options */
235*251Slclee static int	io_wrt = 0;		/* write stdin to disk (-w) */
236*251Slclee static int	io_rd = 0;		/* read disk and write stdout (-r) */
237*251Slclee static char	*io_fatt;		/* user supplied pattern (-P pattern) */
238*251Slclee static int	io_patt = 0;		/* write pattern to disk (-P pattern) */
239*251Slclee static int	io_lgeom = 0;		/* get label geometry (-g) */
240*251Slclee static int	io_pgeom = 0;		/* get drive physical geometry (-G) */
241*251Slclee static char	*io_sgeom = 0;		/* set label geometry (-S geom_file) */
242*251Slclee static int	io_readonly = 0;	/* do not write to disk (-R) */
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate /* The -o offset and -s size options specify the area of the disk on */
2450Sstevel@tonic-gate /* which to perform the particular operation; i.e., -P, -r, or -w. */
246*251Slclee static int	io_offset = 0;		/* offset sector (-o offset) */
247*251Slclee static int	io_size = 0;		/* size in sectors (-s size) */
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate /* Partition table flags */
250*251Slclee static int	v_flag = 0;		/* virtual geometry-HBA flag (-v) */
251*251Slclee static int 	stdo_flag = 0;		/* stdout flag (-W -) */
252*251Slclee static int	io_fdisk = 0;		/* do fdisk operation */
253*251Slclee static int	io_ifdisk = 0;		/* interactive partition */
254*251Slclee static int	io_nifdisk = 0;		/* non-interactive partition (-n) */
255*251Slclee 
256*251Slclee static int	io_adjt = 0;		/* check/adjust VTOC (truncate (-t)) */
257*251Slclee static int	io_ADJT = 0;		/* check/adjust VTOC (delete (-T)) */
258*251Slclee static char	*io_ffdisk = 0;		/* input fdisk file name (-F file) */
259*251Slclee static char	*io_Wfdisk = 0;		/* output fdisk file name (-W file) */
260*251Slclee static char	*io_Afdisk = 0;		/* add entry to partition table (-A) */
261*251Slclee static char	*io_Dfdisk = 0;		/* delete entry from part. table (-D) */
262*251Slclee 
263*251Slclee static char	*io_mboot = 0;		/* master boot record (-b boot_file) */
264*251Slclee 
265*251Slclee static struct mboot BootCod;		/* buffer for master boot record */
266*251Slclee 
267*251Slclee static int	io_wholedisk = 0;	/* use whole disk for Solaris (-B) */
268*251Slclee static int	io_EFIdisk = 0;		/* use whole disk for EFI (-E) */
269*251Slclee static int	io_debug = 0;		/* activate verbose mode (-d) */
270*251Slclee static int	io_image = 0;		/* create image using geometry (-I) */
271*251Slclee 
272*251Slclee static struct mboot *Bootblk;		/* pointer to cut/paste sector zero */
273*251Slclee static char	*Bootsect;		/* pointer to sector zero buffer */
274*251Slclee static char	*Nullsect;
275*251Slclee static struct vtoc	disk_vtoc;	/* verify VTOC table */
276*251Slclee static int	vt_inval = 0;
277*251Slclee static int	no_virtgeom_ioctl = 0;	/* ioctl for virtual geometry failed */
278*251Slclee static int	no_physgeom_ioctl = 0;	/* ioctl for physical geometry failed */
279*251Slclee 
280*251Slclee static struct ipart	Table[FD_NUMPART];
281*251Slclee static struct ipart	Old_Table[FD_NUMPART];
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate /* Disk geometry information */
284*251Slclee static struct dk_geom	disk_geom;
285*251Slclee 
286*251Slclee static int Dev;			/* fd for open device */
2870Sstevel@tonic-gate /* Physical geometry for the drive */
288*251Slclee static int	Numcyl;			/* number of cylinders */
289*251Slclee static int	heads;			/* number of heads */
290*251Slclee static int	sectors;		/* number of sectors per track */
291*251Slclee static int	acyl;			/* number of alternate sectors */
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate /* HBA (virtual) geometry for the drive */
294*251Slclee static int	hba_Numcyl;		/* number of cylinders */
295*251Slclee static int	hba_heads;		/* number of heads */
296*251Slclee static int	hba_sectors;		/* number of sectors per track */
297*251Slclee 
298*251Slclee static int	sectsiz;		/* sector size */
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate /* Load functions for fdisk table modification */
3010Sstevel@tonic-gate #define	LOADFILE	0	/* load fdisk from file */
3020Sstevel@tonic-gate #define	LOADDEL		1	/* delete an fdisk entry */
3030Sstevel@tonic-gate #define	LOADADD		2	/* add an fdisk entry */
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate #define	CBUFLEN 80
306*251Slclee static char s[CBUFLEN];
307*251Slclee 
308*251Slclee static void update_disk_and_exit(boolean_t table_changed);
309*251Slclee int main(int argc, char *argv[]);
310*251Slclee static int read_geom(char *sgeom);
311*251Slclee static void dev_mboot_read(void);
312*251Slclee static void dev_mboot_write(int sect, char *buff, int bootsiz);
313*251Slclee static void mboot_read(void);
314*251Slclee static void fill_patt(void);
315*251Slclee static void abs_read(void);
316*251Slclee static void abs_write(void);
317*251Slclee static void load(int funct, char *file);
318*251Slclee static void Set_Table_CHS_Values(int ti);
319*251Slclee static int insert_tbl(int id, int act,
320*251Slclee     int bhead, int bsect, int bcyl,
321*251Slclee     int ehead, int esect, int ecyl,
322*251Slclee     int rsect, int numsect);
323*251Slclee static int verify_tbl(void);
324*251Slclee static int pars_fdisk(char *line,
325*251Slclee     int *id, int *act,
326*251Slclee     int *bhead, int *bsect, int *bcyl,
327*251Slclee     int *ehead, int *esect, int *ecyl,
328*251Slclee     int *rsect, int *numsect);
329*251Slclee static int validate_part(int id, int rsect, int numsect);
330*251Slclee static void stage0(void);
331*251Slclee static int pcreate(void);
332*251Slclee static int specify(uchar_t tsystid);
333*251Slclee static void dispmenu(void);
334*251Slclee static int pchange(void);
335*251Slclee static int ppartid(void);
336*251Slclee static char pdelete(void);
337*251Slclee static void rm_blanks(char *s);
338*251Slclee static int getcyl(void);
339*251Slclee static void disptbl(void);
340*251Slclee static void print_Table(void);
341*251Slclee static void copy_Table_to_Old_Table(void);
342*251Slclee static void nulltbl(void);
343*251Slclee static void copy_Bootblk_to_Table(void);
344*251Slclee static void fill_ipart(char *bootptr, struct ipart *partp);
345*251Slclee #ifdef sparc
346*251Slclee uchar_t getbyte(char **bp);
347*251Slclee uint32_t getlong(char **bp);
348*251Slclee #endif
349*251Slclee static void copy_Table_to_Bootblk(void);
350*251Slclee static int TableChanged(void);
351*251Slclee static void ffile_write(char *file);
352*251Slclee static void fix_slice(void);
353*251Slclee static int yesno(void);
354*251Slclee static int readvtoc(void);
355*251Slclee static int writevtoc(void);
356*251Slclee static int efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc);
357*251Slclee static int clear_efi(void);
358*251Slclee static void clear_vtoc(int table, int part);
359*251Slclee static int lecture_and_query(char *warning, char *devname);
360*251Slclee static void sanity_check_provided_device(char *devname, int fd);
361*251Slclee static char *get_node(char *devname);
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate static void
3640Sstevel@tonic-gate update_disk_and_exit(boolean_t table_changed)
3650Sstevel@tonic-gate {
3660Sstevel@tonic-gate 	if (table_changed) {
3670Sstevel@tonic-gate 		/*
3680Sstevel@tonic-gate 		 * Copy the new table back to the sector buffer
3690Sstevel@tonic-gate 		 * and write it to disk
3700Sstevel@tonic-gate 		 */
3710Sstevel@tonic-gate 		copy_Table_to_Bootblk();
3720Sstevel@tonic-gate 		dev_mboot_write(0, Bootsect, sectsiz);
3730Sstevel@tonic-gate 	}
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	/* If the VTOC table is wrong fix it (truncation only) */
3760Sstevel@tonic-gate 	if (io_adjt)
3770Sstevel@tonic-gate 		fix_slice();
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	exit(0);
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate /*
3850Sstevel@tonic-gate  * main
3860Sstevel@tonic-gate  * Process command-line options.
3870Sstevel@tonic-gate  */
388*251Slclee int
3890Sstevel@tonic-gate main(int argc, char *argv[])
3900Sstevel@tonic-gate {
391*251Slclee 	int c, i;
3920Sstevel@tonic-gate 	extern	int optind;
3930Sstevel@tonic-gate 	extern	char *optarg;
3940Sstevel@tonic-gate 	int	errflg = 0;
3950Sstevel@tonic-gate 	int	diag_cnt = 0;
3960Sstevel@tonic-gate 	int openmode;
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 	setbuf(stderr, 0);	/* so all output gets out on exit */
3990Sstevel@tonic-gate 	setbuf(stdout, 0);
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	/* Process the options. */
4020Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "o:s:P:F:b:A:D:W:S:tTIhwvrndgGRBE"))
4030Sstevel@tonic-gate 	    != EOF) {
4040Sstevel@tonic-gate 		switch (c) {
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 			case 'o':
4070Sstevel@tonic-gate 				io_offset = strtoul(optarg, 0, 0);
4080Sstevel@tonic-gate 				continue;
4090Sstevel@tonic-gate 			case 's':
4100Sstevel@tonic-gate 				io_size = strtoul(optarg, 0, 0);
4110Sstevel@tonic-gate 				continue;
4120Sstevel@tonic-gate 			case 'P':
4130Sstevel@tonic-gate 				diag_cnt++;
4140Sstevel@tonic-gate 				io_patt++;
4150Sstevel@tonic-gate 				io_fatt = optarg;
4160Sstevel@tonic-gate 				continue;
4170Sstevel@tonic-gate 			case 'w':
4180Sstevel@tonic-gate 				diag_cnt++;
4190Sstevel@tonic-gate 				io_wrt++;
4200Sstevel@tonic-gate 				continue;
4210Sstevel@tonic-gate 			case 'r':
4220Sstevel@tonic-gate 				diag_cnt++;
4230Sstevel@tonic-gate 				io_rd++;
4240Sstevel@tonic-gate 				continue;
4250Sstevel@tonic-gate 			case 'd':
4260Sstevel@tonic-gate 				io_debug++;
4270Sstevel@tonic-gate 				continue;
4280Sstevel@tonic-gate 			case 'I':
4290Sstevel@tonic-gate 				io_image++;
4300Sstevel@tonic-gate 				continue;
4310Sstevel@tonic-gate 			case 'R':
4320Sstevel@tonic-gate 				io_readonly++;
4330Sstevel@tonic-gate 				continue;
4340Sstevel@tonic-gate 			case 'S':
4350Sstevel@tonic-gate 				diag_cnt++;
4360Sstevel@tonic-gate 				io_sgeom = optarg;
4370Sstevel@tonic-gate 				continue;
4380Sstevel@tonic-gate 			case 'T':
4390Sstevel@tonic-gate 				io_ADJT++;
440*251Slclee 				/* FALLTHRU */
4410Sstevel@tonic-gate 			case 't':
4420Sstevel@tonic-gate 				io_adjt++;
4430Sstevel@tonic-gate 				continue;
4440Sstevel@tonic-gate 			case 'B':
4450Sstevel@tonic-gate 				io_wholedisk++;
4460Sstevel@tonic-gate 				io_fdisk++;
4470Sstevel@tonic-gate 				continue;
4480Sstevel@tonic-gate 			case 'E':
4490Sstevel@tonic-gate 				io_EFIdisk++;
4500Sstevel@tonic-gate 				io_fdisk++;
4510Sstevel@tonic-gate 				continue;
4520Sstevel@tonic-gate 			case 'g':
4530Sstevel@tonic-gate 				diag_cnt++;
4540Sstevel@tonic-gate 				io_lgeom++;
4550Sstevel@tonic-gate 				continue;
4560Sstevel@tonic-gate 			case 'G':
4570Sstevel@tonic-gate 				diag_cnt++;
4580Sstevel@tonic-gate 				io_pgeom++;
4590Sstevel@tonic-gate 				continue;
4600Sstevel@tonic-gate 			case 'n':
4610Sstevel@tonic-gate 				io_nifdisk++;
4620Sstevel@tonic-gate 				io_fdisk++;
4630Sstevel@tonic-gate 				continue;
4640Sstevel@tonic-gate 			case 'F':
4650Sstevel@tonic-gate 				io_fdisk++;
4660Sstevel@tonic-gate 				io_ffdisk = optarg;
4670Sstevel@tonic-gate 				continue;
4680Sstevel@tonic-gate 			case 'b':
4690Sstevel@tonic-gate 				io_mboot = optarg;
4700Sstevel@tonic-gate 				continue;
4710Sstevel@tonic-gate 			case 'W':
4720Sstevel@tonic-gate 				/*
4730Sstevel@tonic-gate 				 * If '-' is the -W argument, then write
4740Sstevel@tonic-gate 				 * to standard output, otherwise write
4750Sstevel@tonic-gate 				 * to the specified file.
4760Sstevel@tonic-gate 				 */
4770Sstevel@tonic-gate 				if (strncmp(optarg, "-", 1) == 0)
4780Sstevel@tonic-gate 					stdo_flag = 1;
4790Sstevel@tonic-gate 				else
4800Sstevel@tonic-gate 					io_Wfdisk = optarg;
4810Sstevel@tonic-gate 				io_fdisk++;
4820Sstevel@tonic-gate 				continue;
4830Sstevel@tonic-gate 			case 'A':
4840Sstevel@tonic-gate 				io_fdisk++;
4850Sstevel@tonic-gate 				io_Afdisk = optarg;
4860Sstevel@tonic-gate 				continue;
4870Sstevel@tonic-gate 			case 'D':
4880Sstevel@tonic-gate 				io_fdisk++;
4890Sstevel@tonic-gate 				io_Dfdisk = optarg;
4900Sstevel@tonic-gate 				continue;
4910Sstevel@tonic-gate 			case 'h':
492*251Slclee 				(void) fprintf(stderr, "%s\n", Usage);
493*251Slclee 				(void) fprintf(stderr, "%s\n", Usage1);
4940Sstevel@tonic-gate 				exit(0);
495*251Slclee 				/* FALLTHRU */
4960Sstevel@tonic-gate 			case 'v':
4970Sstevel@tonic-gate 				v_flag = 1;
4980Sstevel@tonic-gate 				continue;
4990Sstevel@tonic-gate 			case '?':
5000Sstevel@tonic-gate 				errflg++;
5010Sstevel@tonic-gate 				break;
5020Sstevel@tonic-gate 		}
5030Sstevel@tonic-gate 		break;
5040Sstevel@tonic-gate 	}
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 	if (io_image && io_sgeom && diag_cnt == 1) {
5070Sstevel@tonic-gate 		diag_cnt = 0;
5080Sstevel@tonic-gate 	}
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 	/* User option checking */
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 	/* By default, run in interactive mode */
5130Sstevel@tonic-gate 	if (!io_fdisk && !diag_cnt && !io_nifdisk) {
5140Sstevel@tonic-gate 		io_ifdisk++;
5150Sstevel@tonic-gate 		io_fdisk++;
5160Sstevel@tonic-gate 	}
5170Sstevel@tonic-gate 	if (((io_fdisk || io_adjt) && diag_cnt) || (diag_cnt > 1)) {
5180Sstevel@tonic-gate 		errflg++;
5190Sstevel@tonic-gate 	}
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 	/* Was any error detected? */
5220Sstevel@tonic-gate 	if (errflg || argc == optind) {
523*251Slclee 		(void) fprintf(stderr, "%s\n", Usage);
524*251Slclee 		(void) fprintf(stderr,
5250Sstevel@tonic-gate 		    "\nDetailed help is available with the -h option.\n");
5260Sstevel@tonic-gate 		exit(2);
5270Sstevel@tonic-gate 	}
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	/* Figure out the correct device node to open */
5310Sstevel@tonic-gate 	Dfltdev = get_node(argv[optind]);
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	if (io_readonly)
5340Sstevel@tonic-gate 		openmode = O_RDONLY;
5350Sstevel@tonic-gate 	else
5360Sstevel@tonic-gate 		openmode = O_RDWR|O_CREAT;
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate 	if ((Dev = open(Dfltdev, openmode, 0666)) == -1) {
539*251Slclee 		(void) fprintf(stderr,
540*251Slclee 		    "fdisk: Cannot open device %s.\n",
541*251Slclee 		    Dfltdev);
5420Sstevel@tonic-gate 		exit(1);
5430Sstevel@tonic-gate 	}
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate 	/* Get the disk geometry */
5460Sstevel@tonic-gate 	if (!io_image) {
5470Sstevel@tonic-gate 		/* Get disk's HBA (virtual) geometry */
5480Sstevel@tonic-gate 		errno = 0;
5490Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCG_VIRTGEOM, &disk_geom)) {
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 			/*
5520Sstevel@tonic-gate 			 * If ioctl isn't implemented on this platform, then
5530Sstevel@tonic-gate 			 * turn off flag to print out virtual geometry (-v),
5540Sstevel@tonic-gate 			 * otherwise use the virtual geometry.
5550Sstevel@tonic-gate 			 */
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate 			if (errno == ENOTTY) {
5580Sstevel@tonic-gate 				v_flag = 0;
5590Sstevel@tonic-gate 				no_virtgeom_ioctl = 1;
5600Sstevel@tonic-gate 			} else if (errno == EINVAL) {
5610Sstevel@tonic-gate 				/*
5620Sstevel@tonic-gate 				 * This means that the ioctl exists, but
5630Sstevel@tonic-gate 				 * is invalid for this disk, meaning the
5640Sstevel@tonic-gate 				 * disk doesn't have an HBA geometry
5650Sstevel@tonic-gate 				 * (like, say, it's larger than 8GB).
5660Sstevel@tonic-gate 				 */
5670Sstevel@tonic-gate 				v_flag = 0;
5680Sstevel@tonic-gate 				hba_Numcyl = hba_heads = hba_sectors = 0;
5690Sstevel@tonic-gate 			} else {
5700Sstevel@tonic-gate 				(void) fprintf(stderr,
5710Sstevel@tonic-gate 				    "%s: Cannot get virtual disk geometry.\n",
5720Sstevel@tonic-gate 				    argv[optind]);
5730Sstevel@tonic-gate 				exit(1);
5740Sstevel@tonic-gate 			}
5750Sstevel@tonic-gate 		} else {
5760Sstevel@tonic-gate 			/* save virtual geometry values obtained by ioctl */
5770Sstevel@tonic-gate 			hba_Numcyl = disk_geom.dkg_ncyl;
5780Sstevel@tonic-gate 			hba_heads = disk_geom.dkg_nhead;
5790Sstevel@tonic-gate 			hba_sectors = disk_geom.dkg_nsect;
5800Sstevel@tonic-gate 		}
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 		errno = 0;
5830Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCG_PHYGEOM, &disk_geom)) {
5840Sstevel@tonic-gate 			if (errno == ENOTTY) {
5850Sstevel@tonic-gate 				no_physgeom_ioctl = 1;
5860Sstevel@tonic-gate 			} else {
5870Sstevel@tonic-gate 				(void) fprintf(stderr,
5880Sstevel@tonic-gate 				    "%s: Cannot get physical disk geometry.\n",
5890Sstevel@tonic-gate 				    argv[optind]);
5900Sstevel@tonic-gate 				exit(1);
5910Sstevel@tonic-gate 			}
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 		}
5940Sstevel@tonic-gate 		/*
5950Sstevel@tonic-gate 		 * Call DKIOCGGEOM if the ioctls for physical and virtual
5960Sstevel@tonic-gate 		 * geometry fail. Get both from this generic call.
5970Sstevel@tonic-gate 		 */
5980Sstevel@tonic-gate 		if (no_virtgeom_ioctl && no_physgeom_ioctl) {
5990Sstevel@tonic-gate 			errno = 0;
6000Sstevel@tonic-gate 			if (ioctl(Dev, DKIOCGGEOM, &disk_geom)) {
6010Sstevel@tonic-gate 				(void) fprintf(stderr,
6020Sstevel@tonic-gate 				    "%s: Cannot get disk label geometry.\n",
6030Sstevel@tonic-gate 				    argv[optind]);
6040Sstevel@tonic-gate 				exit(1);
6050Sstevel@tonic-gate 			}
6060Sstevel@tonic-gate 		}
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate 		Numcyl = disk_geom.dkg_ncyl;
6090Sstevel@tonic-gate 		heads = disk_geom.dkg_nhead;
6100Sstevel@tonic-gate 		sectors = disk_geom.dkg_nsect;
6110Sstevel@tonic-gate 		sectsiz = 512;
6120Sstevel@tonic-gate 		acyl = disk_geom.dkg_acyl;
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate 		/*
6150Sstevel@tonic-gate 		 * if hba geometry was not set by DKIOC_VIRTGEOM
6160Sstevel@tonic-gate 		 * or we got an invalid hba geometry
6170Sstevel@tonic-gate 		 * then set hba geometry based on max values
6180Sstevel@tonic-gate 		 */
6190Sstevel@tonic-gate 		if (no_virtgeom_ioctl ||
620*251Slclee 		    disk_geom.dkg_ncyl == 0 ||
621*251Slclee 		    disk_geom.dkg_nhead == 0 ||
622*251Slclee 		    disk_geom.dkg_nsect == 0 ||
6230Sstevel@tonic-gate 		    disk_geom.dkg_ncyl > MAX_CYL ||
6240Sstevel@tonic-gate 		    disk_geom.dkg_nhead > MAX_HEAD ||
6250Sstevel@tonic-gate 		    disk_geom.dkg_nsect > MAX_SECT) {
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 			/*
6280Sstevel@tonic-gate 			 * turn off flag to print out virtual geometry (-v)
6290Sstevel@tonic-gate 			 */
6300Sstevel@tonic-gate 			v_flag = 0;
6310Sstevel@tonic-gate 			hba_sectors	= MAX_SECT;
6320Sstevel@tonic-gate 			hba_heads	= MAX_HEAD + 1;
6330Sstevel@tonic-gate 			hba_Numcyl	= (Numcyl * heads * sectors) /
6340Sstevel@tonic-gate 			    (hba_sectors * hba_heads);
6350Sstevel@tonic-gate 		}
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 		if (io_debug) {
638*251Slclee 			(void) fprintf(stderr, "Physical Geometry:\n");
639*251Slclee 			(void) fprintf(stderr,
6400Sstevel@tonic-gate 			    "  cylinders[%d] heads[%d] sectors[%d]\n"
6410Sstevel@tonic-gate 			    "  sector size[%d] blocks[%d] mbytes[%d]\n",
6420Sstevel@tonic-gate 			    Numcyl,
6430Sstevel@tonic-gate 			    heads,
6440Sstevel@tonic-gate 			    sectors,
6450Sstevel@tonic-gate 			    sectsiz,
646*251Slclee 			    Numcyl * heads * sectors,
647*251Slclee 			    (Numcyl * heads * sectors * sectsiz) / 1048576);
648*251Slclee 			(void) fprintf(stderr, "Virtual (HBA) Geometry:\n");
649*251Slclee 			(void) fprintf(stderr,
6500Sstevel@tonic-gate 			    "  cylinders[%d] heads[%d] sectors[%d]\n"
6510Sstevel@tonic-gate 			    "  sector size[%d] blocks[%d] mbytes[%d]\n",
6520Sstevel@tonic-gate 			    hba_Numcyl,
6530Sstevel@tonic-gate 			    hba_heads,
6540Sstevel@tonic-gate 			    hba_sectors,
6550Sstevel@tonic-gate 			    sectsiz,
656*251Slclee 			    hba_Numcyl * hba_heads * hba_sectors,
657*251Slclee 			    (hba_Numcyl * hba_heads * hba_sectors * sectsiz) /
658*251Slclee 			    1048576);
6590Sstevel@tonic-gate 		}
6600Sstevel@tonic-gate 	}
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate 	/* If user has requested a geometry report just do it and exit */
6630Sstevel@tonic-gate 	if (io_lgeom) {
6640Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCGGEOM, &disk_geom)) {
6650Sstevel@tonic-gate 			(void) fprintf(stderr,
6660Sstevel@tonic-gate 			    "%s: Cannot get disk label geometry.\n",
6670Sstevel@tonic-gate 			    argv[optind]);
6680Sstevel@tonic-gate 			exit(1);
6690Sstevel@tonic-gate 		}
6700Sstevel@tonic-gate 		Numcyl = disk_geom.dkg_ncyl;
6710Sstevel@tonic-gate 		heads = disk_geom.dkg_nhead;
6720Sstevel@tonic-gate 		sectors = disk_geom.dkg_nsect;
6730Sstevel@tonic-gate 		sectsiz = 512;
6740Sstevel@tonic-gate 		acyl = disk_geom.dkg_acyl;
675*251Slclee 		(void) printf("* Label geometry for device %s\n", Dfltdev);
676*251Slclee 		(void) printf(
677*251Slclee 		    "* PCYL     NCYL     ACYL     BCYL     NHEAD NSECT"
6780Sstevel@tonic-gate 		    " SECSIZ\n");
679*251Slclee 		(void) printf("  %-8d %-8d %-8d %-8d %-5d %-5d %-6d\n",
6800Sstevel@tonic-gate 		    Numcyl,
6810Sstevel@tonic-gate 		    disk_geom.dkg_ncyl,
6820Sstevel@tonic-gate 		    disk_geom.dkg_acyl,
6830Sstevel@tonic-gate 		    disk_geom.dkg_bcyl,
6840Sstevel@tonic-gate 		    heads,
6850Sstevel@tonic-gate 		    sectors,
6860Sstevel@tonic-gate 		    sectsiz);
6870Sstevel@tonic-gate 		exit(0);
6880Sstevel@tonic-gate 	} else if (io_pgeom) {
6890Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCG_PHYGEOM, &disk_geom)) {
6900Sstevel@tonic-gate 			(void) fprintf(stderr,
6910Sstevel@tonic-gate 			    "%s: Cannot get physical disk geometry.\n",
6920Sstevel@tonic-gate 			    argv[optind]);
6930Sstevel@tonic-gate 			exit(1);
6940Sstevel@tonic-gate 		}
695*251Slclee 		(void) printf("* Physical geometry for device %s\n", Dfltdev);
696*251Slclee 		(void) printf(
697*251Slclee 		    "* PCYL     NCYL     ACYL     BCYL     NHEAD NSECT"
6980Sstevel@tonic-gate 		    " SECSIZ\n");
699*251Slclee 		(void) printf("  %-8d %-8d %-8d %-8d %-5d %-5d %-6d\n",
7000Sstevel@tonic-gate 		    disk_geom.dkg_pcyl,
7010Sstevel@tonic-gate 		    disk_geom.dkg_ncyl,
7020Sstevel@tonic-gate 		    disk_geom.dkg_acyl,
7030Sstevel@tonic-gate 		    disk_geom.dkg_bcyl,
7040Sstevel@tonic-gate 		    disk_geom.dkg_nhead,
7050Sstevel@tonic-gate 		    disk_geom.dkg_nsect,
7060Sstevel@tonic-gate 		    sectsiz);
7070Sstevel@tonic-gate 		exit(0);
7080Sstevel@tonic-gate 	} else if (io_sgeom) {
7090Sstevel@tonic-gate 		if (read_geom(io_sgeom)) {
7100Sstevel@tonic-gate 			exit(1);
7110Sstevel@tonic-gate 		} else if (!io_image) {
7120Sstevel@tonic-gate 			exit(0);
7130Sstevel@tonic-gate 		}
7140Sstevel@tonic-gate 	}
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate 	/* Allocate memory to hold three complete sectors */
7170Sstevel@tonic-gate 	Bootsect = (char *)malloc(3 * sectsiz);
7180Sstevel@tonic-gate 	if (Bootsect == NULL) {
719*251Slclee 		(void) fprintf(stderr,
7200Sstevel@tonic-gate 		    "fdisk: Unable to obtain enough buffer memory"
7210Sstevel@tonic-gate 		    " (%d bytes).\n",
722*251Slclee 		    3 * sectsiz);
7230Sstevel@tonic-gate 		exit(1);
7240Sstevel@tonic-gate 	}
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 	Nullsect = Bootsect + sectsiz;
7270Sstevel@tonic-gate 	/* Zero out the "NULL" sector */
7280Sstevel@tonic-gate 	for (i = 0; i < sectsiz; i++) {
7290Sstevel@tonic-gate 		Nullsect[i] = 0;
7300Sstevel@tonic-gate 	}
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate 	/* Find out what the user wants done */
7330Sstevel@tonic-gate 	if (io_rd) {		/* abs disk read */
7340Sstevel@tonic-gate 		abs_read();	/* will not return */
7350Sstevel@tonic-gate 	} else if (io_wrt && !io_readonly) {
7360Sstevel@tonic-gate 		abs_write();	/* will not return */
7370Sstevel@tonic-gate 	} else if (io_patt && !io_readonly) {
7380Sstevel@tonic-gate 		fill_patt();	/* will not return */
7390Sstevel@tonic-gate 	}
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate 	/* This is the fdisk edit, the real reason for the program.	*/
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	sanity_check_provided_device(Dfltdev, Dev);
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 	/* Get the new BOOT program in case we write a new fdisk table */
7470Sstevel@tonic-gate 	mboot_read();
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate 	/* Read from disk master boot */
7500Sstevel@tonic-gate 	dev_mboot_read();
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 	/*
7530Sstevel@tonic-gate 	 * Verify and copy the device's fdisk table. This will be used
7540Sstevel@tonic-gate 	 * as the prototype mboot if the device's mboot looks invalid.
7550Sstevel@tonic-gate 	 */
7560Sstevel@tonic-gate 	Bootblk = (struct mboot *)Bootsect;
7570Sstevel@tonic-gate 	copy_Bootblk_to_Table();
7580Sstevel@tonic-gate 
7590Sstevel@tonic-gate 	/* save away a copy of Table in Old_Table for sensing changes */
7600Sstevel@tonic-gate 	copy_Table_to_Old_Table();
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate 	/* Load fdisk table from specified file (-F fdisk_file) */
7630Sstevel@tonic-gate 	if (io_ffdisk) {
7640Sstevel@tonic-gate 		/* Load and verify user-specified table parameters */
7650Sstevel@tonic-gate 		load(LOADFILE, io_ffdisk);
7660Sstevel@tonic-gate 	}
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 	/* Does user want to delete or add an entry? */
7690Sstevel@tonic-gate 	if (io_Dfdisk) {
7700Sstevel@tonic-gate 		load(LOADDEL, io_Dfdisk);
7710Sstevel@tonic-gate 	}
7720Sstevel@tonic-gate 	if (io_Afdisk) {
7730Sstevel@tonic-gate 		load(LOADADD, io_Afdisk);
7740Sstevel@tonic-gate 	}
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 	if (!io_ffdisk && !io_Afdisk && !io_Dfdisk) {
7770Sstevel@tonic-gate 		/* Check if there is no fdisk table */
7780Sstevel@tonic-gate 		if (Table[0].systid == UNUSED || io_wholedisk || io_EFIdisk) {
7790Sstevel@tonic-gate 			if (io_ifdisk && !io_wholedisk && !io_EFIdisk) {
780*251Slclee 				(void) printf(
781*251Slclee 				    "No fdisk table exists. The default"
782*251Slclee 				    " partition for the disk is:\n\n"
783*251Slclee 				    "  a 100%% \"SOLARIS System\" "
784*251Slclee 				    "partition\n\n"
785*251Slclee 				    "Type \"y\" to accept the default "
7860Sstevel@tonic-gate 				    "partition,  otherwise type \"n\" to "
7870Sstevel@tonic-gate 				    "edit the\n partition table.\n");
7880Sstevel@tonic-gate 			}
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 			/* Edit the partition table as directed */
7910Sstevel@tonic-gate 			if (io_wholedisk ||(io_ifdisk && yesno())) {
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 				/* Default scenario */
7940Sstevel@tonic-gate 				nulltbl();
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate 				/* now set up UNIX System partition */
7970Sstevel@tonic-gate 				Table[0].bootid = ACTIVE;
7980Sstevel@tonic-gate 				Table[0].relsect = lel(heads * sectors);
799*251Slclee 				Table[0].numsect = lel((long)((Numcyl - 1) *
8000Sstevel@tonic-gate 				    heads * sectors));
8010Sstevel@tonic-gate 				Table[0].systid = SUNIXOS2;   /* Solaris */
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 				/* calculate CHS values for table entry 0 */
8040Sstevel@tonic-gate 				Set_Table_CHS_Values(0);
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate 				update_disk_and_exit(B_TRUE);
8070Sstevel@tonic-gate 			} else if (io_EFIdisk) {
8080Sstevel@tonic-gate 				/* create an EFI partition for the whole disk */
8090Sstevel@tonic-gate 				nulltbl();
8100Sstevel@tonic-gate 				i = insert_tbl(EFI_PMBR, 0, 0, 0, 0, 0, 0, 0, 1,
8110Sstevel@tonic-gate 				    (Numcyl * heads * sectors) - 1);
8120Sstevel@tonic-gate 				if (i != 0) {
813*251Slclee 					(void) fprintf(stderr,
814*251Slclee 					    "Error creating EFI partition\n");
8150Sstevel@tonic-gate 					exit(1);
8160Sstevel@tonic-gate 				}
8170Sstevel@tonic-gate 				update_disk_and_exit(B_TRUE);
8180Sstevel@tonic-gate 			}
8190Sstevel@tonic-gate 		}
8200Sstevel@tonic-gate 	}
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate 	/* Display complete fdisk table entries for debugging purposes */
8230Sstevel@tonic-gate 	if (io_debug) {
824*251Slclee 		(void) fprintf(stderr, "Partition Table Entry Values:\n");
8250Sstevel@tonic-gate 		print_Table();
8260Sstevel@tonic-gate 		if (io_ifdisk) {
827*251Slclee 			(void) fprintf(stderr, "\n");
828*251Slclee 			(void) fprintf(stderr, "Press Enter to continue.\n");
829*251Slclee 			(void) gets(s);
8300Sstevel@tonic-gate 		}
8310Sstevel@tonic-gate 	}
8320Sstevel@tonic-gate 
8330Sstevel@tonic-gate 	/* Interactive fdisk mode */
8340Sstevel@tonic-gate 	if (io_ifdisk) {
835*251Slclee 		(void) printf(CLR_SCR);
8360Sstevel@tonic-gate 		disptbl();
837*251Slclee 		for (;;) {
838*251Slclee 			stage0();
8390Sstevel@tonic-gate 			copy_Bootblk_to_Table();
8400Sstevel@tonic-gate 			disptbl();
8410Sstevel@tonic-gate 		}
8420Sstevel@tonic-gate 	}
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate 	/* If user wants to write the table to a file, do it */
8450Sstevel@tonic-gate 	if (io_Wfdisk)
8460Sstevel@tonic-gate 		ffile_write(io_Wfdisk);
8470Sstevel@tonic-gate 	else if (stdo_flag)
8480Sstevel@tonic-gate 		ffile_write((char *)stdout);
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 	update_disk_and_exit(TableChanged() == 1);
851*251Slclee 	return (0);
8520Sstevel@tonic-gate }
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate /*
8550Sstevel@tonic-gate  * read_geom
8560Sstevel@tonic-gate  * Read geometry from specified file (-S).
8570Sstevel@tonic-gate  */
8580Sstevel@tonic-gate 
859*251Slclee static int
860*251Slclee read_geom(char *sgeom)
8610Sstevel@tonic-gate {
8620Sstevel@tonic-gate 	char	line[256];
8630Sstevel@tonic-gate 	FILE *fp;
8640Sstevel@tonic-gate 
8650Sstevel@tonic-gate 	/* open the prototype file */
8660Sstevel@tonic-gate 	if ((fp = fopen(sgeom, "r")) == NULL) {
8670Sstevel@tonic-gate 		(void) fprintf(stderr, "fdisk: Cannot open file %s.\n",
8680Sstevel@tonic-gate 		    io_sgeom);
8690Sstevel@tonic-gate 		return (1);
8700Sstevel@tonic-gate 	}
8710Sstevel@tonic-gate 
8720Sstevel@tonic-gate 	/* Read a line from the file */
8730Sstevel@tonic-gate 	while (fgets(line, sizeof (line) - 1, fp)) {
8740Sstevel@tonic-gate 		if (line[0] == '\0' || line[0] == '\n' || line[0] == '*')
8750Sstevel@tonic-gate 			continue;
8760Sstevel@tonic-gate 		else {
8770Sstevel@tonic-gate 			line[strlen(line)] = '\0';
878*251Slclee 			if (sscanf(line, "%hu %hu %hu %hu %hu %hu %d",
8790Sstevel@tonic-gate 			    &disk_geom.dkg_pcyl,
8800Sstevel@tonic-gate 			    &disk_geom.dkg_ncyl,
8810Sstevel@tonic-gate 			    &disk_geom.dkg_acyl,
8820Sstevel@tonic-gate 			    &disk_geom.dkg_bcyl,
8830Sstevel@tonic-gate 			    &disk_geom.dkg_nhead,
8840Sstevel@tonic-gate 			    &disk_geom.dkg_nsect,
8850Sstevel@tonic-gate 			    &sectsiz) != 7) {
8860Sstevel@tonic-gate 				(void) fprintf(stderr,
8870Sstevel@tonic-gate 				    "Syntax error:\n	\"%s\".\n",
8880Sstevel@tonic-gate 				    line);
8890Sstevel@tonic-gate 				return (1);
8900Sstevel@tonic-gate 			}
8910Sstevel@tonic-gate 			break;
8920Sstevel@tonic-gate 		} /* else */
8930Sstevel@tonic-gate 	} /* while (fgets(line, sizeof (line) - 1, fp)) */
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 	if (!io_image) {
8960Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCSGEOM, &disk_geom)) {
8970Sstevel@tonic-gate 			(void) fprintf(stderr,
8980Sstevel@tonic-gate 			    "fdisk: Cannot set label geometry.\n");
8990Sstevel@tonic-gate 			return (1);
9000Sstevel@tonic-gate 		}
9010Sstevel@tonic-gate 	} else {
9020Sstevel@tonic-gate 		Numcyl = hba_Numcyl = disk_geom.dkg_ncyl;
9030Sstevel@tonic-gate 		heads = hba_heads = disk_geom.dkg_nhead;
9040Sstevel@tonic-gate 		sectors = hba_sectors = disk_geom.dkg_nsect;
9050Sstevel@tonic-gate 		acyl = disk_geom.dkg_acyl;
9060Sstevel@tonic-gate 	}
9070Sstevel@tonic-gate 
908*251Slclee 	(void) fclose(fp);
9090Sstevel@tonic-gate 	return (0);
9100Sstevel@tonic-gate }
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate /*
9130Sstevel@tonic-gate  * dev_mboot_read
9140Sstevel@tonic-gate  * Read the master boot sector from the device.
9150Sstevel@tonic-gate  */
916*251Slclee static void
917*251Slclee dev_mboot_read(void)
9180Sstevel@tonic-gate {
9190Sstevel@tonic-gate 	if ((ioctl(Dev, DKIOCGMBOOT, Bootsect) < 0) && (errno != ENOTTY)) {
9200Sstevel@tonic-gate 		perror("Error in ioctl DKIOCGMBOOT");
9210Sstevel@tonic-gate 	}
9220Sstevel@tonic-gate 	if (errno == 0)
9230Sstevel@tonic-gate 		return;
9240Sstevel@tonic-gate 	if (lseek(Dev, 0, SEEK_SET) == -1) {
925*251Slclee 		(void) fprintf(stderr,
9260Sstevel@tonic-gate 		    "fdisk: Error seeking to partition table on %s.\n",
9270Sstevel@tonic-gate 		    Dfltdev);
9280Sstevel@tonic-gate 		if (!io_image)
9290Sstevel@tonic-gate 			exit(1);
9300Sstevel@tonic-gate 	}
9310Sstevel@tonic-gate 	if (read(Dev, Bootsect, sectsiz) != sectsiz) {
932*251Slclee 		(void) fprintf(stderr,
9330Sstevel@tonic-gate 		    "fdisk: Error reading partition table from %s.\n",
9340Sstevel@tonic-gate 		    Dfltdev);
9350Sstevel@tonic-gate 		if (!io_image)
9360Sstevel@tonic-gate 			exit(1);
9370Sstevel@tonic-gate 	}
9380Sstevel@tonic-gate }
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate /*
9410Sstevel@tonic-gate  * dev_mboot_write
9420Sstevel@tonic-gate  * Write the master boot sector to the device.
9430Sstevel@tonic-gate  */
944*251Slclee static void
9450Sstevel@tonic-gate dev_mboot_write(int sect, char *buff, int bootsiz)
9460Sstevel@tonic-gate {
9470Sstevel@tonic-gate 	int 	new_pt, old_pt, error;
9480Sstevel@tonic-gate 	int	clr_efi = -1, old_solaris = -1, new_solaris = -1;
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	if (io_readonly)
951*251Slclee 		return;
9520Sstevel@tonic-gate 
9530Sstevel@tonic-gate 	if (io_debug) {
954*251Slclee 		(void) fprintf(stderr, "About to write fdisk table:\n");
9550Sstevel@tonic-gate 		print_Table();
9560Sstevel@tonic-gate 		if (io_ifdisk) {
957*251Slclee 			(void) fprintf(stderr, "Press Enter to continue.\n");
958*251Slclee 			(void) gets(s);
9590Sstevel@tonic-gate 		}
9600Sstevel@tonic-gate 	}
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate 	/* see if the old table had EFI or Solaris partitions */
9630Sstevel@tonic-gate 	for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) {
9640Sstevel@tonic-gate 		if (Old_Table[old_pt].systid == SUNIXOS ||
9650Sstevel@tonic-gate 		    Old_Table[old_pt].systid == SUNIXOS2) {
9660Sstevel@tonic-gate 			old_solaris = old_pt;
9670Sstevel@tonic-gate 		} else if (Old_Table[old_pt].systid == EFI_PMBR) {
9680Sstevel@tonic-gate 			clr_efi = old_pt;
9690Sstevel@tonic-gate 		}
9700Sstevel@tonic-gate 	}
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate 	/* look to see if Solaris partition changed in relsect/numsect */
9730Sstevel@tonic-gate 	for (new_pt = 0; new_pt < FD_NUMPART; new_pt++) {
9740Sstevel@tonic-gate 
9750Sstevel@tonic-gate 		/*
9760Sstevel@tonic-gate 		 * if this is not a Solaris partition, ignore it
9770Sstevel@tonic-gate 		 */
9780Sstevel@tonic-gate 		if (Table[new_pt].systid != SUNIXOS &&
9790Sstevel@tonic-gate 		    Table[new_pt].systid != SUNIXOS2)
9800Sstevel@tonic-gate 			continue;
9810Sstevel@tonic-gate 
9820Sstevel@tonic-gate 		/*
9830Sstevel@tonic-gate 		 * if there was no previous Solaris partition
9840Sstevel@tonic-gate 		 * or if the old partition was in a different place
9850Sstevel@tonic-gate 		 * or if the old partition was a different size
9860Sstevel@tonic-gate 		 * then this must be a new Solaris partition
9870Sstevel@tonic-gate 		 */
9880Sstevel@tonic-gate 		if (old_solaris == -1 ||
9890Sstevel@tonic-gate 		    Old_Table[old_solaris].relsect != Table[new_pt].relsect ||
9900Sstevel@tonic-gate 		    Old_Table[old_solaris].numsect != Table[new_pt].numsect) {
9910Sstevel@tonic-gate 			new_solaris = new_pt;
9920Sstevel@tonic-gate 			break;
9930Sstevel@tonic-gate 		}
9940Sstevel@tonic-gate 	}
9950Sstevel@tonic-gate 
9960Sstevel@tonic-gate 	/* look to see if a EFI partition changed in relsect/numsect */
9970Sstevel@tonic-gate 	for (new_pt = 0; new_pt < FD_NUMPART; new_pt++) {
9980Sstevel@tonic-gate 		if (Table[new_pt].systid != EFI_PMBR)
9990Sstevel@tonic-gate 			continue;
10000Sstevel@tonic-gate 		for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) {
10010Sstevel@tonic-gate 		    if ((Old_Table[old_pt].systid == Table[new_pt].systid) &&
10020Sstevel@tonic-gate 			(Old_Table[old_pt].relsect == Table[new_pt].relsect) &&
10030Sstevel@tonic-gate 			(Old_Table[old_pt].numsect == Table[new_pt].numsect))
10040Sstevel@tonic-gate 			    break;
10050Sstevel@tonic-gate 		}
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate 		/*
10080Sstevel@tonic-gate 		 * if EFI partition changed, set the flag to clear
10090Sstevel@tonic-gate 		 * the EFI GPT
10100Sstevel@tonic-gate 		 */
10110Sstevel@tonic-gate 		if (old_pt == FD_NUMPART && Table[new_pt].begcyl != 0) {
10120Sstevel@tonic-gate 			clr_efi = 0;
10130Sstevel@tonic-gate 		}
10140Sstevel@tonic-gate 		break;
10150Sstevel@tonic-gate 	}
10160Sstevel@tonic-gate 
10170Sstevel@tonic-gate 	/* clear labels if necessary */
10180Sstevel@tonic-gate 	if (clr_efi >= 0) {
10190Sstevel@tonic-gate 		if (io_debug) {
1020*251Slclee 			(void) fprintf(stderr, "Clearing EFI labels\n");
10210Sstevel@tonic-gate 		}
10220Sstevel@tonic-gate 		if ((error = clear_efi()) != 0) {
10230Sstevel@tonic-gate 			if (io_debug) {
1024*251Slclee 				(void) fprintf(stderr,
1025*251Slclee 				    "\tError %d clearing EFI labels"
10260Sstevel@tonic-gate 				    " (probably no EFI labels exist)\n",
10270Sstevel@tonic-gate 				    error);
10280Sstevel@tonic-gate 			}
10290Sstevel@tonic-gate 		}
10300Sstevel@tonic-gate 	}
10310Sstevel@tonic-gate 
10320Sstevel@tonic-gate 	if (new_solaris >= 0) {
10330Sstevel@tonic-gate 		if (io_debug) {
1034*251Slclee 			(void) fprintf(stderr, "Clearing VTOC labels from NEW"
10350Sstevel@tonic-gate 			    " table\n");
10360Sstevel@tonic-gate 		}
10370Sstevel@tonic-gate 		clear_vtoc(NEW, new_solaris);
10380Sstevel@tonic-gate 	}
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 	if ((ioctl(Dev, DKIOCSMBOOT, buff) == -1) && (errno != ENOTTY)) {
1041*251Slclee 		(void) fprintf(stderr,
10420Sstevel@tonic-gate 		    "fdisk: Error in ioctl DKIOCSMBOOT on %s.\n",
10430Sstevel@tonic-gate 		    Dfltdev);
10440Sstevel@tonic-gate 	}
10450Sstevel@tonic-gate 	if (errno == 0)
10460Sstevel@tonic-gate 		return;
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate 	/* write to disk drive */
10490Sstevel@tonic-gate 	if (lseek(Dev, sect, SEEK_SET) == -1) {
1050*251Slclee 		(void) fprintf(stderr,
10510Sstevel@tonic-gate 		    "fdisk: Error seeking to master boot record on %s.\n",
10520Sstevel@tonic-gate 		    Dfltdev);
10530Sstevel@tonic-gate 		exit(1);
10540Sstevel@tonic-gate 	}
10550Sstevel@tonic-gate 	if (write(Dev, buff, bootsiz) != bootsiz) {
1056*251Slclee 		(void) fprintf(stderr,
10570Sstevel@tonic-gate 		    "fdisk: Error writing master boot record to %s.\n",
10580Sstevel@tonic-gate 		    Dfltdev);
10590Sstevel@tonic-gate 		exit(1);
10600Sstevel@tonic-gate 	}
10610Sstevel@tonic-gate }
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate /*
10640Sstevel@tonic-gate  * mboot_read
10650Sstevel@tonic-gate  * Read the prototype boot records from the files.
10660Sstevel@tonic-gate  */
1067*251Slclee static void
1068*251Slclee mboot_read(void)
10690Sstevel@tonic-gate {
10700Sstevel@tonic-gate 	int mDev, i;
10710Sstevel@tonic-gate 	struct ipart *part;
10720Sstevel@tonic-gate 
10730Sstevel@tonic-gate #if defined(i386) || defined(sparc)
10740Sstevel@tonic-gate 	/*
10750Sstevel@tonic-gate 	 * If the master boot file hasn't been specified, use the
10760Sstevel@tonic-gate 	 * implementation architecture name to generate the default one.
10770Sstevel@tonic-gate 	 */
10780Sstevel@tonic-gate 	if (io_mboot == (char *)0) {
10790Sstevel@tonic-gate 		/*
10800Sstevel@tonic-gate 		 * Bug ID 1249035:
10810Sstevel@tonic-gate 		 *	The mboot file must be delivered on all platforms
10820Sstevel@tonic-gate 		 *	and installed in a non-platform-dependent
10830Sstevel@tonic-gate 		 *	directory; i.e., /usr/lib/fs/ufs.
10840Sstevel@tonic-gate 		 */
10850Sstevel@tonic-gate 		io_mboot = "/usr/lib/fs/ufs/mboot";
10860Sstevel@tonic-gate 	}
10870Sstevel@tonic-gate 
10880Sstevel@tonic-gate 	/* First read in the master boot record */
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 	/* Open the master boot proto file */
10910Sstevel@tonic-gate 	if ((mDev = open(io_mboot, O_RDONLY, 0666)) == -1) {
1092*251Slclee 		(void) fprintf(stderr,
10930Sstevel@tonic-gate 		    "fdisk: Cannot open master boot file %s.\n",
10940Sstevel@tonic-gate 		    io_mboot);
10950Sstevel@tonic-gate 		exit(1);
10960Sstevel@tonic-gate 	}
10970Sstevel@tonic-gate 
10980Sstevel@tonic-gate 	/* Read the master boot program */
10990Sstevel@tonic-gate 	if (read(mDev, &BootCod, sizeof (struct mboot)) != sizeof
11000Sstevel@tonic-gate 	    (struct mboot)) {
1101*251Slclee 		(void) fprintf(stderr,
11020Sstevel@tonic-gate 		    "fdisk: Cannot read master boot file %s.\n",
11030Sstevel@tonic-gate 		    io_mboot);
11040Sstevel@tonic-gate 		exit(1);
11050Sstevel@tonic-gate 	}
11060Sstevel@tonic-gate 
11070Sstevel@tonic-gate 	/* Is this really a master boot record? */
11080Sstevel@tonic-gate 	if (les(BootCod.signature) != MBB_MAGIC) {
1109*251Slclee 		(void) fprintf(stderr,
11100Sstevel@tonic-gate 		    "fdisk: Invalid master boot file %s.\n", io_mboot);
1111*251Slclee 		(void) fprintf(stderr,
1112*251Slclee 		    "Bad magic number: is %x, but should be %x.\n",
11130Sstevel@tonic-gate 		    les(BootCod.signature), MBB_MAGIC);
11140Sstevel@tonic-gate 		exit(1);
11150Sstevel@tonic-gate 	}
11160Sstevel@tonic-gate 
1117*251Slclee 	(void) close(mDev);
11180Sstevel@tonic-gate #else
11190Sstevel@tonic-gate #error	fdisk needs to be ported to new architecture
11200Sstevel@tonic-gate #endif
11210Sstevel@tonic-gate 
11220Sstevel@tonic-gate 	/* Zero out the partitions part of this record */
11230Sstevel@tonic-gate 	part = (struct ipart *)BootCod.parts;
11240Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++, part++) {
1125*251Slclee 		(void) memset(part, 0, sizeof (struct ipart));
11260Sstevel@tonic-gate 	}
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate }
11290Sstevel@tonic-gate 
11300Sstevel@tonic-gate /*
11310Sstevel@tonic-gate  * fill_patt
11320Sstevel@tonic-gate  * Fill the disk with user/sector number pattern.
11330Sstevel@tonic-gate  */
1134*251Slclee static void
1135*251Slclee fill_patt(void)
11360Sstevel@tonic-gate {
1137*251Slclee 	int	*buff_ptr, i;
11380Sstevel@tonic-gate 	int	io_fpatt = 0;
11390Sstevel@tonic-gate 	int	io_ipatt = 0;
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 	if (strncmp(io_fatt, "#", 1) != 0) {
11420Sstevel@tonic-gate 		io_fpatt++;
11430Sstevel@tonic-gate 		io_ipatt = strtoul(io_fatt, 0, 0);
11440Sstevel@tonic-gate 		buff_ptr = (int *)Bootsect;
11450Sstevel@tonic-gate 		for (i = 0; i < sectsiz; i += 4, buff_ptr++)
11460Sstevel@tonic-gate 		    *buff_ptr = io_ipatt;
11470Sstevel@tonic-gate 	}
11480Sstevel@tonic-gate 
11490Sstevel@tonic-gate 	/*
11500Sstevel@tonic-gate 	 * Fill disk with pattern based on block number.
11510Sstevel@tonic-gate 	 * Write to the disk at absolute relative block io_offset
11520Sstevel@tonic-gate 	 * for io_size blocks.
11530Sstevel@tonic-gate 	 */
11540Sstevel@tonic-gate 	while (io_size--) {
11550Sstevel@tonic-gate 		buff_ptr = (int *)Bootsect;
11560Sstevel@tonic-gate 		if (!io_fpatt) {
11570Sstevel@tonic-gate 			for (i = 0; i < sectsiz; i += 4, buff_ptr++)
11580Sstevel@tonic-gate 				*buff_ptr = io_offset;
11590Sstevel@tonic-gate 		}
11600Sstevel@tonic-gate 		/* Write the data to disk */
11610Sstevel@tonic-gate 		if (lseek(Dev, sectsiz * io_offset++, SEEK_SET) == -1) {
1162*251Slclee 			(void) fprintf(stderr, "fdisk: Error seeking on %s.\n",
11630Sstevel@tonic-gate 				Dfltdev);
11640Sstevel@tonic-gate 			exit(1);
11650Sstevel@tonic-gate 		}
11660Sstevel@tonic-gate 		if (write(Dev, Bootsect, sectsiz) != sectsiz) {
1167*251Slclee 			(void) fprintf(stderr, "fdisk: Error writing %s.\n",
11680Sstevel@tonic-gate 				Dfltdev);
11690Sstevel@tonic-gate 			exit(1);
11700Sstevel@tonic-gate 		}
11710Sstevel@tonic-gate 	} /* while (--io_size); */
11720Sstevel@tonic-gate }
11730Sstevel@tonic-gate 
11740Sstevel@tonic-gate /*
11750Sstevel@tonic-gate  * abs_read
11760Sstevel@tonic-gate  * Read from the disk at absolute relative block io_offset for
11770Sstevel@tonic-gate  * io_size blocks. Write the data to standard ouput (-r).
11780Sstevel@tonic-gate  */
1179*251Slclee static void
1180*251Slclee abs_read(void)
1181*251Slclee {
11820Sstevel@tonic-gate 	int c;
11830Sstevel@tonic-gate 
11840Sstevel@tonic-gate 	while (io_size--) {
11850Sstevel@tonic-gate 		if (lseek(Dev, sectsiz * io_offset++, SEEK_SET) == -1) {
1186*251Slclee 			(void) fprintf(stderr, "fdisk: Error seeking on %s.\n",
11870Sstevel@tonic-gate 			    Dfltdev);
11880Sstevel@tonic-gate 			exit(1);
11890Sstevel@tonic-gate 		}
11900Sstevel@tonic-gate 		if (read(Dev, Bootsect, sectsiz) != sectsiz) {
1191*251Slclee 			(void) fprintf(stderr, "fdisk: Error reading %s.\n",
11920Sstevel@tonic-gate 			    Dfltdev);
11930Sstevel@tonic-gate 			exit(1);
11940Sstevel@tonic-gate 		}
11950Sstevel@tonic-gate 
11960Sstevel@tonic-gate 		/* Write to standard ouptut */
1197*251Slclee 		if ((c = write(1, Bootsect, (unsigned)sectsiz)) != sectsiz) {
11980Sstevel@tonic-gate 			if (c >= 0) {
11990Sstevel@tonic-gate 				if (io_debug)
1200*251Slclee 					(void) fprintf(stderr,
1201*251Slclee 					    "fdisk: Output warning: %d of %d"
1202*251Slclee 					    " characters written.\n",
1203*251Slclee 					    c, sectsiz);
12040Sstevel@tonic-gate 				exit(2);
12050Sstevel@tonic-gate 			} else {
12060Sstevel@tonic-gate 				perror("write error on output file.");
12070Sstevel@tonic-gate 				exit(2);
12080Sstevel@tonic-gate 			}
12090Sstevel@tonic-gate 		} /* if ((c = write(1, Bootsect, (unsigned)sectsiz)) */
12100Sstevel@tonic-gate 			/* != sectsiz) */
12110Sstevel@tonic-gate 	} /* while (--io_size); */
12120Sstevel@tonic-gate 	exit(0);
12130Sstevel@tonic-gate }
12140Sstevel@tonic-gate 
12150Sstevel@tonic-gate /*
12160Sstevel@tonic-gate  * abs_write
12170Sstevel@tonic-gate  * Read the data from standard input. Write to the disk at
12180Sstevel@tonic-gate  * absolute relative block io_offset for io_size blocks (-w).
12190Sstevel@tonic-gate  */
1220*251Slclee static void
1221*251Slclee abs_write(void)
12220Sstevel@tonic-gate {
12230Sstevel@tonic-gate 	int c, i;
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 	while (io_size--) {
12260Sstevel@tonic-gate 		int part_exit = 0;
12270Sstevel@tonic-gate 		/* Read from standard input */
12280Sstevel@tonic-gate 		if ((c = read(0, Bootsect, (unsigned)sectsiz)) != sectsiz) {
12290Sstevel@tonic-gate 			if (c >= 0) {
12300Sstevel@tonic-gate 				if (io_debug)
1231*251Slclee 				(void) fprintf(stderr,
12320Sstevel@tonic-gate 				    "fdisk: WARNING: Incomplete read (%d of"
12330Sstevel@tonic-gate 				    " %d characters read) on input file.\n",
12340Sstevel@tonic-gate 					c, sectsiz);
12350Sstevel@tonic-gate 				/* Fill pattern to mark partial sector in buf */
12360Sstevel@tonic-gate 				for (i = c; i < sectsiz; ) {
12370Sstevel@tonic-gate 					Bootsect[i++] = 0x41;
12380Sstevel@tonic-gate 					Bootsect[i++] = 0x62;
12390Sstevel@tonic-gate 					Bootsect[i++] = 0x65;
12400Sstevel@tonic-gate 					Bootsect[i++] = 0;
12410Sstevel@tonic-gate 				}
12420Sstevel@tonic-gate 				part_exit++;
12430Sstevel@tonic-gate 			} else {
12440Sstevel@tonic-gate 				perror("read error on input file.");
12450Sstevel@tonic-gate 				exit(2);
12460Sstevel@tonic-gate 			}
12470Sstevel@tonic-gate 
12480Sstevel@tonic-gate 		}
12490Sstevel@tonic-gate 		/* Write to disk drive */
12500Sstevel@tonic-gate 		if (lseek(Dev, sectsiz * io_offset++, SEEK_SET) == -1) {
1251*251Slclee 			(void) fprintf(stderr, "fdisk: Error seeking on %s.\n",
12520Sstevel@tonic-gate 			    Dfltdev);
12530Sstevel@tonic-gate 			exit(1);
12540Sstevel@tonic-gate 		}
12550Sstevel@tonic-gate 		if (write(Dev, Bootsect, sectsiz) != sectsiz) {
1256*251Slclee 			(void) fprintf(stderr, "fdisk: Error writing %s.\n",
12570Sstevel@tonic-gate 			    Dfltdev);
12580Sstevel@tonic-gate 			exit(1);
12590Sstevel@tonic-gate 		}
12600Sstevel@tonic-gate 		if (part_exit)
12610Sstevel@tonic-gate 		exit(0);
12620Sstevel@tonic-gate 	} /* while (--io_size); */
12630Sstevel@tonic-gate 	exit(1);
12640Sstevel@tonic-gate }
12650Sstevel@tonic-gate 
1266*251Slclee 
12670Sstevel@tonic-gate /*
12680Sstevel@tonic-gate  * load
12690Sstevel@tonic-gate  * Load will either read the fdisk table from a file or add or
12700Sstevel@tonic-gate  * delete an entry (-A, -D, -F).
12710Sstevel@tonic-gate  */
12720Sstevel@tonic-gate 
1273*251Slclee static void
1274*251Slclee load(int funct, char *file)
12750Sstevel@tonic-gate {
12760Sstevel@tonic-gate 	int	id;
12770Sstevel@tonic-gate 	int	act;
12780Sstevel@tonic-gate 	int	bhead;
12790Sstevel@tonic-gate 	int	bsect;
12800Sstevel@tonic-gate 	int	bcyl;
12810Sstevel@tonic-gate 	int	ehead;
12820Sstevel@tonic-gate 	int	esect;
12830Sstevel@tonic-gate 	int	ecyl;
12840Sstevel@tonic-gate 	int	rsect;
12850Sstevel@tonic-gate 	int	numsect;
12860Sstevel@tonic-gate 	char	line[256];
12870Sstevel@tonic-gate 	int	i = 0;
12880Sstevel@tonic-gate 	int	j;
12890Sstevel@tonic-gate 	FILE *fp;
12900Sstevel@tonic-gate 
12910Sstevel@tonic-gate 	switch (funct) {
12920Sstevel@tonic-gate 
12930Sstevel@tonic-gate 	    case LOADFILE:
12940Sstevel@tonic-gate 
12950Sstevel@tonic-gate 		/*
12960Sstevel@tonic-gate 		 * Zero out the table before loading it, which will
12970Sstevel@tonic-gate 		 * force it to be updated on disk later (-F
12980Sstevel@tonic-gate 		 * fdisk_file).
12990Sstevel@tonic-gate 		 */
13000Sstevel@tonic-gate 		nulltbl();
13010Sstevel@tonic-gate 
13020Sstevel@tonic-gate 		/* Open the prototype file */
13030Sstevel@tonic-gate 		if ((fp = fopen(file, "r")) == NULL) {
13040Sstevel@tonic-gate 			(void) fprintf(stderr,
13050Sstevel@tonic-gate 			    "fdisk: Cannot open prototype partition file %s.\n",
13060Sstevel@tonic-gate 			    file);
13070Sstevel@tonic-gate 			exit(1);
13080Sstevel@tonic-gate 		}
13090Sstevel@tonic-gate 
13100Sstevel@tonic-gate 		/* Read a line from the file */
13110Sstevel@tonic-gate 		while (fgets(line, sizeof (line) - 1, fp)) {
13120Sstevel@tonic-gate 			if (pars_fdisk(line, &id, &act, &bhead, &bsect,
13130Sstevel@tonic-gate 			    &bcyl, &ehead, &esect, &ecyl, &rsect, &numsect)) {
13140Sstevel@tonic-gate 				continue;
13150Sstevel@tonic-gate 			}
13160Sstevel@tonic-gate 
13170Sstevel@tonic-gate 			/*
13180Sstevel@tonic-gate 			 * Validate the partition. It cannot start at sector
13190Sstevel@tonic-gate 			 * 0 unless it is UNUSED or already exists
13200Sstevel@tonic-gate 			 */
13210Sstevel@tonic-gate 			if (validate_part(id, rsect, numsect) < 0) {
13220Sstevel@tonic-gate 				(void) fprintf(stderr,
13230Sstevel@tonic-gate 				    "fdisk: Error on entry \"%s\".\n",
13240Sstevel@tonic-gate 				    line);
13250Sstevel@tonic-gate 				exit(1);
13260Sstevel@tonic-gate 			}
13270Sstevel@tonic-gate 			/*
13280Sstevel@tonic-gate 			 * Find an unused entry to use and put the entry
13290Sstevel@tonic-gate 			 * in table
13300Sstevel@tonic-gate 			 */
13310Sstevel@tonic-gate 			if (insert_tbl(id, act, bhead, bsect, bcyl, ehead,
13320Sstevel@tonic-gate 			    esect, ecyl, rsect, numsect) < 0) {
13330Sstevel@tonic-gate 				(void) fprintf(stderr,
13340Sstevel@tonic-gate 				    "fdisk: Error on entry \"%s\".\n",
13350Sstevel@tonic-gate 				    line);
13360Sstevel@tonic-gate 				exit(1);
13370Sstevel@tonic-gate 			}
13380Sstevel@tonic-gate 		} /* while (fgets(line, sizeof (line) - 1, fp)) */
13390Sstevel@tonic-gate 
13400Sstevel@tonic-gate 		if (verify_tbl() < 0) {
1341*251Slclee 			(void) fprintf(stderr,
13420Sstevel@tonic-gate 			    "fdisk: Cannot create partition table\n");
13430Sstevel@tonic-gate 			exit(1);
13440Sstevel@tonic-gate 		}
13450Sstevel@tonic-gate 
1346*251Slclee 		(void) fclose(fp);
13470Sstevel@tonic-gate 		return;
13480Sstevel@tonic-gate 
13490Sstevel@tonic-gate 	    case LOADDEL:
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate 		/* Parse the user-supplied deletion line (-D) */
1352*251Slclee 		if (pars_fdisk(file, &id, &act, &bhead, &bsect, &bcyl,
1353*251Slclee 		    &ehead, &esect, &ecyl, &rsect, &numsect)) {
1354*251Slclee 			(void) fprintf(stderr,
1355*251Slclee 			    "fdisk: Syntax error \"%s\"\n", file);
1356*251Slclee 			exit(1);
1357*251Slclee 		}
13580Sstevel@tonic-gate 
13590Sstevel@tonic-gate 		/* Find the exact entry in the table */
13600Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
13610Sstevel@tonic-gate 			if (Table[i].systid == id &&
13620Sstevel@tonic-gate 			    Table[i].bootid == act &&
13630Sstevel@tonic-gate 			    Table[i].beghead == bhead &&
13640Sstevel@tonic-gate 			    Table[i].begsect == ((bsect & 0x3f) |
1365*251Slclee 				(uchar_t)((bcyl>>2) & 0xc0)) &&
1366*251Slclee 			    Table[i].begcyl == (uchar_t)(bcyl & 0xff) &&
13670Sstevel@tonic-gate 			    Table[i].endhead == ehead &&
13680Sstevel@tonic-gate 			    Table[i].endsect == ((esect & 0x3f) |
1369*251Slclee 				(uchar_t)((ecyl>>2) & 0xc0)) &&
1370*251Slclee 			    Table[i].endcyl == (uchar_t)(ecyl & 0xff) &&
13710Sstevel@tonic-gate 			    Table[i].relsect == lel(rsect) &&
13720Sstevel@tonic-gate 			    Table[i].numsect == lel(numsect)) {
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate 				/*
13750Sstevel@tonic-gate 				 * Found the entry. Now move rest of
13760Sstevel@tonic-gate 				 * entries up toward the top of the
13770Sstevel@tonic-gate 				 * table, leaving available entries at
13780Sstevel@tonic-gate 				 * the end of the fdisk table.
13790Sstevel@tonic-gate 				 */
1380*251Slclee 				for (j = i; j < FD_NUMPART - 1; j++) {
1381*251Slclee 					Table[j].systid = Table[j + 1].systid;
1382*251Slclee 					Table[j].bootid = Table[j + 1].bootid;
1383*251Slclee 					Table[j].beghead = Table[j + 1].beghead;
1384*251Slclee 					Table[j].begsect = Table[j + 1].begsect;
1385*251Slclee 					Table[j].begcyl = Table[j + 1].begcyl;
1386*251Slclee 					Table[j].endhead = Table[j + 1].endhead;
1387*251Slclee 					Table[j].endsect = Table[j + 1].endsect;
1388*251Slclee 					Table[j].endcyl = Table[j + 1].endcyl;
1389*251Slclee 					Table[j].relsect = Table[j + 1].relsect;
1390*251Slclee 					Table[j].numsect = Table[j + 1].numsect;
13910Sstevel@tonic-gate 				}
13920Sstevel@tonic-gate 
13930Sstevel@tonic-gate 				/*
13940Sstevel@tonic-gate 				 * Mark the last entry as unused in case
13950Sstevel@tonic-gate 				 * all table entries were in use prior
13960Sstevel@tonic-gate 				 * to the deletion.
13970Sstevel@tonic-gate 				 */
13980Sstevel@tonic-gate 
1399*251Slclee 				Table[FD_NUMPART - 1].systid = UNUSED;
1400*251Slclee 				Table[FD_NUMPART - 1].bootid = 0;
14010Sstevel@tonic-gate 				return;
14020Sstevel@tonic-gate 			}
14030Sstevel@tonic-gate 		}
1404*251Slclee 		(void) fprintf(stderr,
14050Sstevel@tonic-gate 		    "fdisk: Entry does not match any existing partition:\n"
14060Sstevel@tonic-gate 		    "	\"%s\"\n",
14070Sstevel@tonic-gate 		    file);
14080Sstevel@tonic-gate 		exit(1);
1409*251Slclee 		/* FALLTHRU */
14100Sstevel@tonic-gate 
14110Sstevel@tonic-gate 	    case LOADADD:
14120Sstevel@tonic-gate 
14130Sstevel@tonic-gate 		/* Parse the user-supplied addition line (-A) */
1414*251Slclee 		if (pars_fdisk(file, &id, &act, &bhead, &bsect, &bcyl, &ehead,
1415*251Slclee 		    &esect, &ecyl, &rsect, &numsect)) {
1416*251Slclee 			(void) fprintf(stderr,
1417*251Slclee 			    "fdisk: Syntax error \"%s\"\n", file);
1418*251Slclee 			exit(1);
1419*251Slclee 		}
14200Sstevel@tonic-gate 
14210Sstevel@tonic-gate 		/* Validate the partition. It cannot start at sector 0 */
14220Sstevel@tonic-gate 		if (rsect == 0) {
14230Sstevel@tonic-gate 			(void) fprintf(stderr,
14240Sstevel@tonic-gate 			    "fdisk: New partition cannot start at sector 0:\n"
14250Sstevel@tonic-gate 			    "   \"%s\".\n",
14260Sstevel@tonic-gate 			    file);
14270Sstevel@tonic-gate 			exit(1);
14280Sstevel@tonic-gate 		}
14290Sstevel@tonic-gate 
14300Sstevel@tonic-gate 		/*
14310Sstevel@tonic-gate 		 * if the user wishes to add an EFI partition, we need
14320Sstevel@tonic-gate 		 * more extensive validation.  rsect should be 1, and
14330Sstevel@tonic-gate 		 * numsect should equal the entire disk capacity - 1
14340Sstevel@tonic-gate 		 */
14350Sstevel@tonic-gate 
14360Sstevel@tonic-gate 		if (id == EFI_PMBR) {
14370Sstevel@tonic-gate 			if (rsect != 1) {
14380Sstevel@tonic-gate 				(void) fprintf(stderr,
14390Sstevel@tonic-gate 				    "fdisk: EFI partitions must start at sector"
14400Sstevel@tonic-gate 				    " 1 (input rsect = %d)\n", rsect);
14410Sstevel@tonic-gate 				exit(1);
14420Sstevel@tonic-gate 			}
14430Sstevel@tonic-gate 
14440Sstevel@tonic-gate 			if (numsect != ((Numcyl * heads * sectors) -1)) {
14450Sstevel@tonic-gate 				(void) fprintf(stderr,
14460Sstevel@tonic-gate 				    "fdisk: EFI partitions must encompass the "
1447*251Slclee 				    "entire disk\n"
1448*251Slclee 				    "(input numsect: %d - avail: %d)\n",
1449*251Slclee 				    numsect,
14500Sstevel@tonic-gate 				    ((Numcyl * heads * sectors) -1));
14510Sstevel@tonic-gate 				exit(1);
14520Sstevel@tonic-gate 			}
14530Sstevel@tonic-gate 		}
14540Sstevel@tonic-gate 
14550Sstevel@tonic-gate 		/* Find unused entry for use and put entry in table */
14560Sstevel@tonic-gate 		if (insert_tbl(id, act, bhead, bsect, bcyl, ehead, esect,
14570Sstevel@tonic-gate 		    ecyl, rsect, numsect) < 0) {
14580Sstevel@tonic-gate 			(void) fprintf(stderr,
14590Sstevel@tonic-gate 			    "fdisk: Invalid entry could not be inserted:\n"
14600Sstevel@tonic-gate 			    "	\"%s\"\n",
14610Sstevel@tonic-gate 			    file);
14620Sstevel@tonic-gate 			exit(1);
14630Sstevel@tonic-gate 		}
14640Sstevel@tonic-gate 
14650Sstevel@tonic-gate 		/* Make sure new entry does not overlap existing entry */
14660Sstevel@tonic-gate 		if (verify_tbl() < 0) {
1467*251Slclee 			(void) fprintf(stderr,
1468*251Slclee 			    "fdisk: Cannot create partition \"%s\"\n", file);
14690Sstevel@tonic-gate 			exit(1);
14700Sstevel@tonic-gate 		}
14710Sstevel@tonic-gate 	} /* switch funct */
14720Sstevel@tonic-gate }
14730Sstevel@tonic-gate 
14740Sstevel@tonic-gate /*
14750Sstevel@tonic-gate  * Set_Table_CHS_Values
14760Sstevel@tonic-gate  *
14770Sstevel@tonic-gate  * This will calculate the CHS values for beginning and ending CHS
14780Sstevel@tonic-gate  * for a single partition table entry (ti) based on the relsect
14790Sstevel@tonic-gate  * and numsect values contained in the partion table entry.
14800Sstevel@tonic-gate  *
14810Sstevel@tonic-gate  * hba_heads and hba_sectors contain the number of heads and sectors.
14820Sstevel@tonic-gate  *
14830Sstevel@tonic-gate  * If the number of cylinders exceeds the MAX_CYL,
14840Sstevel@tonic-gate  * then maximum values will be placed in the corresponding chs entry.
14850Sstevel@tonic-gate  */
14860Sstevel@tonic-gate static void
14870Sstevel@tonic-gate Set_Table_CHS_Values(int ti)
14880Sstevel@tonic-gate {
14890Sstevel@tonic-gate 	uint32_t	lba, cy, hd, sc;
14900Sstevel@tonic-gate 
14910Sstevel@tonic-gate 	lba = (uint32_t)Table[ti].relsect;
14920Sstevel@tonic-gate 	if (lba >= hba_heads * hba_sectors * MAX_CYL) {
14930Sstevel@tonic-gate 		/*
14940Sstevel@tonic-gate 		 * the lba address cannot be expressed in CHS value
14950Sstevel@tonic-gate 		 * so store the maximum CHS field values in the CHS fields.
14960Sstevel@tonic-gate 		 */
14970Sstevel@tonic-gate 		cy = MAX_CYL + 1;
14980Sstevel@tonic-gate 		hd = MAX_HEAD;
14990Sstevel@tonic-gate 		sc = MAX_SECT;
15000Sstevel@tonic-gate 	} else {
15010Sstevel@tonic-gate 		cy = lba / hba_sectors / hba_heads;
15020Sstevel@tonic-gate 		hd = lba / hba_sectors % hba_heads;
15030Sstevel@tonic-gate 		sc = lba % hba_sectors + 1;
15040Sstevel@tonic-gate 	}
15050Sstevel@tonic-gate 	Table[ti].begcyl = cy & 0xff;
1506*251Slclee 	Table[ti].beghead = (uchar_t)hd;
1507*251Slclee 	Table[ti].begsect = (uchar_t)(((cy >> 2) & 0xc0) | sc);
15080Sstevel@tonic-gate 
15090Sstevel@tonic-gate 	/*
15100Sstevel@tonic-gate 	 * This code is identical to the code above
15110Sstevel@tonic-gate 	 * except that it works on ending CHS values
15120Sstevel@tonic-gate 	 */
15130Sstevel@tonic-gate 	lba = (uint32_t)(Table[ti].relsect + Table[ti].numsect - 1);
15140Sstevel@tonic-gate 	if (lba >= hba_heads * hba_sectors * MAX_CYL) {
15150Sstevel@tonic-gate 		cy = MAX_CYL + 1;
15160Sstevel@tonic-gate 		hd = MAX_HEAD;
15170Sstevel@tonic-gate 		sc = MAX_SECT;
15180Sstevel@tonic-gate 	} else {
15190Sstevel@tonic-gate 		cy = lba / hba_sectors / hba_heads;
15200Sstevel@tonic-gate 		hd = lba / hba_sectors % hba_heads;
15210Sstevel@tonic-gate 		sc = lba % hba_sectors + 1;
15220Sstevel@tonic-gate 	}
15230Sstevel@tonic-gate 	Table[ti].endcyl = cy & 0xff;
1524*251Slclee 	Table[ti].endhead = (uchar_t)hd;
1525*251Slclee 	Table[ti].endsect = (uchar_t)(((cy >> 2) & 0xc0) | sc);
15260Sstevel@tonic-gate }
15270Sstevel@tonic-gate 
15280Sstevel@tonic-gate /*
15290Sstevel@tonic-gate  * insert_tbl
15300Sstevel@tonic-gate  * 	Insert entry into fdisk table. Check all user-supplied values
15310Sstevel@tonic-gate  *	for the entry, but not the validity relative to other table
15320Sstevel@tonic-gate  *	entries!
15330Sstevel@tonic-gate  */
1534*251Slclee static int
1535*251Slclee insert_tbl(
1536*251Slclee     int id, int act,
1537*251Slclee     int bhead, int bsect, int bcyl,
1538*251Slclee     int ehead, int esect, int ecyl,
1539*251Slclee     int rsect, int numsect)
15400Sstevel@tonic-gate {
15410Sstevel@tonic-gate 	int	i;
15420Sstevel@tonic-gate 
15430Sstevel@tonic-gate 	/* validate partition size */
1544*251Slclee 	if (rsect + numsect > (Numcyl * heads * sectors)) {
1545*251Slclee 		(void) fprintf(stderr,
15460Sstevel@tonic-gate 		    "fdisk: Partition table exceeds the size of the disk.\n");
15470Sstevel@tonic-gate 		return (-1);
15480Sstevel@tonic-gate 	}
15490Sstevel@tonic-gate 
15500Sstevel@tonic-gate 	/* find UNUSED partition table entry */
15510Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
15520Sstevel@tonic-gate 		if (Table[i].systid == UNUSED) {
15530Sstevel@tonic-gate 			break;
15540Sstevel@tonic-gate 		}
15550Sstevel@tonic-gate 	}
15560Sstevel@tonic-gate 	if (i >= FD_NUMPART) {
1557*251Slclee 		(void) fprintf(stderr, "fdisk: Partition table is full.\n");
15580Sstevel@tonic-gate 		return (-1);
15590Sstevel@tonic-gate 	}
15600Sstevel@tonic-gate 
15610Sstevel@tonic-gate 
1562*251Slclee 	Table[i].systid = (uchar_t)id;
1563*251Slclee 	Table[i].bootid = (uchar_t)act;
15640Sstevel@tonic-gate 	Table[i].numsect = lel(numsect);
15650Sstevel@tonic-gate 	Table[i].relsect = lel(rsect);
15660Sstevel@tonic-gate 
15670Sstevel@tonic-gate 	/*
15680Sstevel@tonic-gate 	 * If we have been called with a valid geometry, use it
15690Sstevel@tonic-gate 	 * valid means non-zero values that fit in the BIOS fields
15700Sstevel@tonic-gate 	 */
15710Sstevel@tonic-gate 	if (0 < bsect && bsect <= MAX_SECT &&
15720Sstevel@tonic-gate 	    0 <= bhead && bhead <= MAX_HEAD &&
15730Sstevel@tonic-gate 	    0 < esect && esect <= MAX_SECT &&
15740Sstevel@tonic-gate 	    0 <= ehead && ehead <= MAX_HEAD) {
15750Sstevel@tonic-gate 		if (bcyl > MAX_CYL)
15760Sstevel@tonic-gate 			bcyl = MAX_CYL + 1;
15770Sstevel@tonic-gate 		if (ecyl > MAX_CYL)
15780Sstevel@tonic-gate 			ecyl = MAX_CYL + 1;
15790Sstevel@tonic-gate 		Table[i].begcyl = bcyl & 0xff;
15800Sstevel@tonic-gate 		Table[i].endcyl = ecyl & 0xff;
1581*251Slclee 		Table[i].beghead = (uchar_t)bhead;
1582*251Slclee 		Table[i].endhead = (uchar_t)ehead;
1583*251Slclee 		Table[i].begsect = (uchar_t)(((bcyl >> 2) & 0xc0) | bsect);
15840Sstevel@tonic-gate 		Table[i].endsect = ((ecyl >> 2) & 0xc0) | esect;
15850Sstevel@tonic-gate 	} else {
15860Sstevel@tonic-gate 
15870Sstevel@tonic-gate 		/*
15880Sstevel@tonic-gate 		 * The specified values are invalid,
15890Sstevel@tonic-gate 		 * so calculate the values based on hba_heads, hba_sectors
15900Sstevel@tonic-gate 		 */
15910Sstevel@tonic-gate 		Set_Table_CHS_Values(i);
15920Sstevel@tonic-gate 	}
15930Sstevel@tonic-gate 
15940Sstevel@tonic-gate 	/*
15950Sstevel@tonic-gate 	 * return partition index
15960Sstevel@tonic-gate 	 */
15970Sstevel@tonic-gate 	return (i);
15980Sstevel@tonic-gate }
15990Sstevel@tonic-gate 
16000Sstevel@tonic-gate /*
16010Sstevel@tonic-gate  * verify_tbl
16020Sstevel@tonic-gate  * Verify that no partition entries overlap or exceed the size of
16030Sstevel@tonic-gate  * the disk.
16040Sstevel@tonic-gate  */
1605*251Slclee static int
1606*251Slclee verify_tbl(void)
16070Sstevel@tonic-gate {
16080Sstevel@tonic-gate 	int	i, j, rsect, numsect;
16090Sstevel@tonic-gate 	int	noMoreParts = 0;
16100Sstevel@tonic-gate 	int	numParts = 0;
16110Sstevel@tonic-gate 
16120Sstevel@tonic-gate 	/* Make sure new entry does not overlap an existing entry */
1613*251Slclee 	for (i = 0; i < FD_NUMPART - 1; i++) {
16140Sstevel@tonic-gate 		if (Table[i].systid != UNUSED) {
16150Sstevel@tonic-gate 			numParts++;
16160Sstevel@tonic-gate 			/*
16170Sstevel@tonic-gate 			 * No valid partitions allowed after an UNUSED  or
16180Sstevel@tonic-gate 			 * EFI_PMBR part
16190Sstevel@tonic-gate 			 */
16200Sstevel@tonic-gate 			if (noMoreParts) {
16210Sstevel@tonic-gate 				return (-1);
16220Sstevel@tonic-gate 			}
16230Sstevel@tonic-gate 
16240Sstevel@tonic-gate 			/*
16250Sstevel@tonic-gate 			 * EFI_PMBR partitions must be the only partition
16260Sstevel@tonic-gate 			 * and must be Table entry 0
16270Sstevel@tonic-gate 			 */
16280Sstevel@tonic-gate 			if (Table[i].systid == EFI_PMBR) {
16290Sstevel@tonic-gate 				if (i == 0) {
16300Sstevel@tonic-gate 					noMoreParts = 1;
16310Sstevel@tonic-gate 				} else {
16320Sstevel@tonic-gate 					return (-1);
16330Sstevel@tonic-gate 				}
16340Sstevel@tonic-gate 
16350Sstevel@tonic-gate 				if (Table[i].relsect != 1) {
1636*251Slclee 					(void) fprintf(stderr, "ERROR: "
16370Sstevel@tonic-gate 					    "Invalid starting sector "
16380Sstevel@tonic-gate 					    "for EFI_PMBR partition:\n"
16390Sstevel@tonic-gate 					    "relsect %d "
16400Sstevel@tonic-gate 					    "(should be 1)\n",
16410Sstevel@tonic-gate 					    Table[i].relsect);
16420Sstevel@tonic-gate 
16430Sstevel@tonic-gate 					return (-1);
16440Sstevel@tonic-gate 				}
16450Sstevel@tonic-gate 
16460Sstevel@tonic-gate 				if (Table[i].numsect !=
16470Sstevel@tonic-gate 				    ((Numcyl * heads * sectors) - 1)) {
1648*251Slclee 					(void) fprintf(stderr, "ERROR: "
16490Sstevel@tonic-gate 					    "EFI_PMBR partition must "
16500Sstevel@tonic-gate 					    "encompass the entire "
1651*251Slclee 					    "disk.\n numsect %d - "
1652*251Slclee 					    "actual %d\n",
16530Sstevel@tonic-gate 					    Table[i].numsect,
16540Sstevel@tonic-gate 					    ((Numcyl * heads * sectors) - 1));
16550Sstevel@tonic-gate 
16560Sstevel@tonic-gate 					return (-1);
16570Sstevel@tonic-gate 				}
16580Sstevel@tonic-gate 			}
16590Sstevel@tonic-gate 
16600Sstevel@tonic-gate 			/* make sure the partition isn't larger than the disk */
16610Sstevel@tonic-gate 			rsect = lel(Table[i].relsect);
16620Sstevel@tonic-gate 			numsect = lel(Table[i].numsect);
16630Sstevel@tonic-gate 			if ((rsect + numsect) > (Numcyl * heads * sectors)) {
16640Sstevel@tonic-gate 				return (-1);
16650Sstevel@tonic-gate 			}
16660Sstevel@tonic-gate 
1667*251Slclee 			for (j = i + 1; j < FD_NUMPART; j++) {
16680Sstevel@tonic-gate 				if (Table[j].systid != UNUSED) {
16690Sstevel@tonic-gate 					int t_relsect = lel(Table[j].relsect);
16700Sstevel@tonic-gate 					int t_numsect = lel(Table[j].numsect);
16710Sstevel@tonic-gate 
16720Sstevel@tonic-gate 					if (noMoreParts) {
1673*251Slclee 						(void) fprintf(stderr,
16740Sstevel@tonic-gate 						    "Cannot add partition to "
16750Sstevel@tonic-gate 						    "table; no more partitions "
16760Sstevel@tonic-gate 						    "allowed\n");
16770Sstevel@tonic-gate 
16780Sstevel@tonic-gate 						if (io_debug) {
1679*251Slclee 							(void) fprintf(stderr,
16800Sstevel@tonic-gate 							    "DEBUG: Current "
16810Sstevel@tonic-gate 							    "partition:\t"
16820Sstevel@tonic-gate 							    "%d:%d:%d:%d:%d:"
1683*251Slclee 							    "%d:%d:%d:%d:%d\n"
16840Sstevel@tonic-gate 							    "       Next "
16850Sstevel@tonic-gate 							    "partition:\t\t"
16860Sstevel@tonic-gate 							    "%d:%d:%d:%d:%d:"
1687*251Slclee 							    "%d:%d:%d:%d:%d\n",
16880Sstevel@tonic-gate 							    Table[i].systid,
16890Sstevel@tonic-gate 							    Table[i].bootid,
16900Sstevel@tonic-gate 							    Table[i].begcyl,
16910Sstevel@tonic-gate 							    Table[i].beghead,
16920Sstevel@tonic-gate 							    Table[i].begsect,
16930Sstevel@tonic-gate 							    Table[i].endcyl,
16940Sstevel@tonic-gate 							    Table[i].endhead,
16950Sstevel@tonic-gate 							    Table[i].endsect,
16960Sstevel@tonic-gate 							    Table[i].relsect,
16970Sstevel@tonic-gate 							    Table[i].numsect,
16980Sstevel@tonic-gate 							    Table[j].systid,
16990Sstevel@tonic-gate 							    Table[j].bootid,
17000Sstevel@tonic-gate 							    Table[j].begcyl,
17010Sstevel@tonic-gate 							    Table[j].beghead,
17020Sstevel@tonic-gate 							    Table[j].begsect,
17030Sstevel@tonic-gate 							    Table[j].endcyl,
17040Sstevel@tonic-gate 							    Table[j].endhead,
17050Sstevel@tonic-gate 							    Table[j].endsect,
17060Sstevel@tonic-gate 							    Table[j].relsect,
17070Sstevel@tonic-gate 							    Table[j].numsect);
17080Sstevel@tonic-gate 						}
17090Sstevel@tonic-gate 
17100Sstevel@tonic-gate 						return (-1);
17110Sstevel@tonic-gate 					}
17120Sstevel@tonic-gate 
17130Sstevel@tonic-gate 					if ((rsect >=
17140Sstevel@tonic-gate 					    (t_relsect + t_numsect)) ||
1715*251Slclee 					    ((rsect + numsect) <= t_relsect)) {
17160Sstevel@tonic-gate 						continue;
17170Sstevel@tonic-gate 					} else {
1718*251Slclee 						(void) fprintf(stderr, "ERROR: "
17190Sstevel@tonic-gate 						    "current partition overlaps"
17200Sstevel@tonic-gate 						    " following partition\n");
17210Sstevel@tonic-gate 
17220Sstevel@tonic-gate 						return (-1);
17230Sstevel@tonic-gate 					}
17240Sstevel@tonic-gate 				}
17250Sstevel@tonic-gate 			}
17260Sstevel@tonic-gate 		} else {
17270Sstevel@tonic-gate 			noMoreParts = 1;
17280Sstevel@tonic-gate 		}
17290Sstevel@tonic-gate 	}
17300Sstevel@tonic-gate 	if (Table[i].systid != UNUSED) {
17310Sstevel@tonic-gate 		if (noMoreParts ||
17320Sstevel@tonic-gate 		    ((lel(Table[i].relsect) + lel(Table[i].numsect)) >
17330Sstevel@tonic-gate 		    (Numcyl * heads * sectors))) {
17340Sstevel@tonic-gate 			return (-1);
17350Sstevel@tonic-gate 		}
17360Sstevel@tonic-gate 	}
17370Sstevel@tonic-gate 
17380Sstevel@tonic-gate 	return (numParts);
17390Sstevel@tonic-gate }
17400Sstevel@tonic-gate 
17410Sstevel@tonic-gate /*
17420Sstevel@tonic-gate  * pars_fdisk
17430Sstevel@tonic-gate  * Parse user-supplied data to set up fdisk partitions
17440Sstevel@tonic-gate  * (-A, -D, -F).
17450Sstevel@tonic-gate  */
1746*251Slclee static int
1747*251Slclee pars_fdisk(
1748*251Slclee     char *line,
1749*251Slclee     int *id, int *act,
1750*251Slclee     int *bhead, int *bsect, int *bcyl,
1751*251Slclee     int *ehead, int *esect, int *ecyl,
1752*251Slclee     int *rsect, int *numsect)
17530Sstevel@tonic-gate {
17540Sstevel@tonic-gate 	int	i;
17550Sstevel@tonic-gate 	if (line[0] == '\0' || line[0] == '\n' || line[0] == '*')
17560Sstevel@tonic-gate 	    return (1);
17570Sstevel@tonic-gate 	line[strlen(line)] = '\0';
17580Sstevel@tonic-gate 	for (i = 0; i < strlen(line); i++) {
17590Sstevel@tonic-gate 		if (line[i] == '\0') {
17600Sstevel@tonic-gate 			break;
17610Sstevel@tonic-gate 		} else if (line[i] == ':') {
17620Sstevel@tonic-gate 			line[i] = ' ';
17630Sstevel@tonic-gate 		}
17640Sstevel@tonic-gate 	}
1765*251Slclee 	if (sscanf(line, "%d %d %d %d %d %d %d %d %d %d",
17660Sstevel@tonic-gate 	    id, act, bhead, bsect, bcyl, ehead, esect, ecyl,
17670Sstevel@tonic-gate 	    rsect, numsect) != 10) {
17680Sstevel@tonic-gate 		(void) fprintf(stderr, "Syntax error:\n	\"%s\".\n", line);
17690Sstevel@tonic-gate 		exit(1);
17700Sstevel@tonic-gate 	}
17710Sstevel@tonic-gate 	return (0);
17720Sstevel@tonic-gate }
17730Sstevel@tonic-gate 
17740Sstevel@tonic-gate /*
17750Sstevel@tonic-gate  * validate_part
17760Sstevel@tonic-gate  * Validate that a new partition does not start at sector 0. Only UNUSED
17770Sstevel@tonic-gate  * partitions and previously existing partitions are allowed to start at 0.
17780Sstevel@tonic-gate  */
1779*251Slclee static int
1780*251Slclee validate_part(int id, int rsect, int numsect)
17810Sstevel@tonic-gate {
17820Sstevel@tonic-gate 	int i;
17830Sstevel@tonic-gate 	if ((id != UNUSED) && (rsect == 0)) {
17840Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
17850Sstevel@tonic-gate 			if ((Old_Table[i].systid == id) &&
17860Sstevel@tonic-gate 			    (Old_Table[i].relsect == lel(rsect)) &&
17870Sstevel@tonic-gate 			    (Old_Table[i].numsect == lel(numsect))) return (0);
17880Sstevel@tonic-gate 		}
1789*251Slclee 		(void) fprintf(stderr,
1790*251Slclee 		    "New partition cannot start at sector 0\n");
17910Sstevel@tonic-gate 		return (-1);
17920Sstevel@tonic-gate 	}
17930Sstevel@tonic-gate 	return (0);
17940Sstevel@tonic-gate }
17950Sstevel@tonic-gate 
17960Sstevel@tonic-gate /*
17970Sstevel@tonic-gate  * stage0
17980Sstevel@tonic-gate  * Print out interactive menu and process user input.
17990Sstevel@tonic-gate  */
1800*251Slclee static void
1801*251Slclee stage0(void)
18020Sstevel@tonic-gate {
1803*251Slclee 	dispmenu();
1804*251Slclee 	for (;;) {
1805*251Slclee 		(void) printf(Q_LINE);
1806*251Slclee 		(void) printf("Enter Selection: ");
1807*251Slclee 		(void) gets(s);
18080Sstevel@tonic-gate 		rm_blanks(s);
18090Sstevel@tonic-gate 		while (!((s[0] > '0') && (s[0] < '7') && (s[1] == 0))) {
1810*251Slclee 			(void) printf(E_LINE); /* Clear any previous error */
1811*251Slclee 			(void) printf(
1812*251Slclee 			    "Enter a one-digit number between 1 and 6.");
1813*251Slclee 			(void) printf(Q_LINE);
1814*251Slclee 			(void) printf("Enter Selection: ");
1815*251Slclee 			(void) gets(s);
18160Sstevel@tonic-gate 			rm_blanks(s);
18170Sstevel@tonic-gate 		}
1818*251Slclee 		(void) printf(E_LINE);
18190Sstevel@tonic-gate 		switch (s[0]) {
18200Sstevel@tonic-gate 			case '1':
18210Sstevel@tonic-gate 				if (pcreate() == -1)
18220Sstevel@tonic-gate 					return;
18230Sstevel@tonic-gate 				break;
18240Sstevel@tonic-gate 			case '2':
18250Sstevel@tonic-gate 				if (pchange() == -1)
18260Sstevel@tonic-gate 					return;
18270Sstevel@tonic-gate 				break;
18280Sstevel@tonic-gate 			case '3':
18290Sstevel@tonic-gate 				if (pdelete() == -1)
18300Sstevel@tonic-gate 					return;
18310Sstevel@tonic-gate 				break;
18320Sstevel@tonic-gate 			case '4':
18330Sstevel@tonic-gate 				if (ppartid() == -1)
18340Sstevel@tonic-gate 					return;
18350Sstevel@tonic-gate 				break;
18360Sstevel@tonic-gate 			case '5':
18370Sstevel@tonic-gate 				/* update disk partition table, if changed */
18380Sstevel@tonic-gate 				if (TableChanged() == 1) {
18390Sstevel@tonic-gate 					copy_Table_to_Bootblk();
18400Sstevel@tonic-gate 					dev_mboot_write(0, Bootsect, sectsiz);
18410Sstevel@tonic-gate 				}
18420Sstevel@tonic-gate 				/*
18430Sstevel@tonic-gate 				 * If the VTOC table is wrong fix it
18440Sstevel@tonic-gate 				 * (truncate only)
18450Sstevel@tonic-gate 				 */
18460Sstevel@tonic-gate 				if (io_adjt) {
18470Sstevel@tonic-gate 					fix_slice();
18480Sstevel@tonic-gate 				}
1849*251Slclee 				(void) close(Dev);
18500Sstevel@tonic-gate 				exit(0);
1851*251Slclee 				/* FALLTHRU */
18520Sstevel@tonic-gate 			case '6':
18530Sstevel@tonic-gate 				/*
18540Sstevel@tonic-gate 				 * If the VTOC table is wrong fix it
18550Sstevel@tonic-gate 				 * (truncate only)
18560Sstevel@tonic-gate 				 */
18570Sstevel@tonic-gate 				if (io_adjt) {
18580Sstevel@tonic-gate 					fix_slice();
18590Sstevel@tonic-gate 				}
1860*251Slclee 				(void) close(Dev);
18610Sstevel@tonic-gate 				exit(0);
1862*251Slclee 				/* FALLTHRU */
18630Sstevel@tonic-gate 			default:
18640Sstevel@tonic-gate 				break;
18650Sstevel@tonic-gate 		}
18660Sstevel@tonic-gate 		copy_Table_to_Bootblk();
18670Sstevel@tonic-gate 		disptbl();
1868*251Slclee 		dispmenu();
18690Sstevel@tonic-gate 	}
18700Sstevel@tonic-gate }
18710Sstevel@tonic-gate 
18720Sstevel@tonic-gate /*
18730Sstevel@tonic-gate  * pcreate
18740Sstevel@tonic-gate  * Create partition entry in the table (interactive mode).
18750Sstevel@tonic-gate  */
1876*251Slclee static int
1877*251Slclee pcreate(void)
18780Sstevel@tonic-gate {
1879*251Slclee 	uchar_t tsystid = 'z';
18800Sstevel@tonic-gate 	int i, j;
18810Sstevel@tonic-gate 	int rsect = 1;
18820Sstevel@tonic-gate 	int retCode = 0;
18830Sstevel@tonic-gate 
18840Sstevel@tonic-gate 	i = 0;
1885*251Slclee 	for (;;) {
18860Sstevel@tonic-gate 		if (i == FD_NUMPART) {
1887*251Slclee 			(void) printf(E_LINE);
1888*251Slclee 			(void) printf(
1889*251Slclee 			    "The partition table is full!\n"
1890*251Slclee 			    "You must delete a partition before creating"
18910Sstevel@tonic-gate 			    " a new one.\n");
18920Sstevel@tonic-gate 			return (-1);
18930Sstevel@tonic-gate 		}
18940Sstevel@tonic-gate 		if (Table[i].systid == UNUSED) {
18950Sstevel@tonic-gate 			break;
18960Sstevel@tonic-gate 		}
18970Sstevel@tonic-gate 		i++;
18980Sstevel@tonic-gate 	}
18990Sstevel@tonic-gate 
19000Sstevel@tonic-gate 	j = 0;
19010Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
19020Sstevel@tonic-gate 		if (Table[i].systid != UNUSED) {
19030Sstevel@tonic-gate 			j += lel(Table[i].numsect);
19040Sstevel@tonic-gate 		}
19050Sstevel@tonic-gate 		if (j >= Numcyl * heads * sectors) {
1906*251Slclee 			(void) printf(E_LINE);
1907*251Slclee 			(void) printf("There is no more room on the disk for"
19080Sstevel@tonic-gate 			    " another partition.\n");
1909*251Slclee 			(void) printf(
1910*251Slclee 			    "You must delete a partition before creating"
19110Sstevel@tonic-gate 			    " a new one.\n");
19120Sstevel@tonic-gate 			return (-1);
19130Sstevel@tonic-gate 		}
19140Sstevel@tonic-gate 	}
19150Sstevel@tonic-gate 	while (tsystid == 'z') {
1916*251Slclee 		(void) printf(Q_LINE);
1917*251Slclee 		(void) printf(
1918*251Slclee 		    "Select the partition type to create:\n"
1919*251Slclee 		    "   1=SOLARIS2  2=UNIX        3=PCIXOS     4=Other\n"
1920*251Slclee 		    "   5=DOS12     6=DOS16       7=DOSEXT     8=DOSBIG\n"
1921*251Slclee 		    "   9=DOS16LBA  A=x86 Boot    B=Diagnostic C=FAT32\n"
1922*251Slclee 		    "   D=FAT32LBA  E=DOSEXTLBA   F=EFI        0=Exit? ");
1923*251Slclee 		(void) gets(s);
19240Sstevel@tonic-gate 		rm_blanks(s);
19250Sstevel@tonic-gate 		if (s[1] != 0) {
1926*251Slclee 			(void) printf(E_LINE);
1927*251Slclee 			(void) printf("Invalid selection, try again.");
19280Sstevel@tonic-gate 			continue;
19290Sstevel@tonic-gate 		}
19300Sstevel@tonic-gate 		switch (s[0]) {
19310Sstevel@tonic-gate 		case '0':		/* exit */
1932*251Slclee 		    (void) printf(E_LINE);
19330Sstevel@tonic-gate 		    return (-1);
19340Sstevel@tonic-gate 		case '1':		/* Solaris partition */
19350Sstevel@tonic-gate 		    tsystid = SUNIXOS2;
19360Sstevel@tonic-gate 		    break;
19370Sstevel@tonic-gate 		case '2':		/* UNIX partition */
19380Sstevel@tonic-gate 		    tsystid = UNIXOS;
19390Sstevel@tonic-gate 		    break;
19400Sstevel@tonic-gate 		case '3':		/* PCIXOS partition */
19410Sstevel@tonic-gate 		    tsystid = PCIXOS;
19420Sstevel@tonic-gate 		    break;
19430Sstevel@tonic-gate 		case '4':		/* OTHEROS System partition */
19440Sstevel@tonic-gate 		    tsystid = OTHEROS;
19450Sstevel@tonic-gate 		    break;
19460Sstevel@tonic-gate 		case '5':
19470Sstevel@tonic-gate 		    tsystid = DOSOS12; /* DOS 12 bit fat */
19480Sstevel@tonic-gate 		    break;
19490Sstevel@tonic-gate 		case '6':
19500Sstevel@tonic-gate 		    tsystid = DOSOS16; /* DOS 16 bit fat */
19510Sstevel@tonic-gate 		    break;
19520Sstevel@tonic-gate 		case '7':
19530Sstevel@tonic-gate 		    tsystid = EXTDOS;
19540Sstevel@tonic-gate 		    break;
19550Sstevel@tonic-gate 		case '8':
19560Sstevel@tonic-gate 		    tsystid = DOSHUGE;
19570Sstevel@tonic-gate 		    break;
19580Sstevel@tonic-gate 		case '9':
19590Sstevel@tonic-gate 		    tsystid = FDISK_FAT95;  /* FAT16, need extended int13 */
19600Sstevel@tonic-gate 		    break;
19610Sstevel@tonic-gate 		case 'a':		/* x86 Boot partition */
19620Sstevel@tonic-gate 		case 'A':
19630Sstevel@tonic-gate 		    tsystid = X86BOOT;
19640Sstevel@tonic-gate 		    break;
19650Sstevel@tonic-gate 		case 'b':		/* Diagnostic boot partition */
19660Sstevel@tonic-gate 		case 'B':
19670Sstevel@tonic-gate 		    tsystid = DIAGPART;
19680Sstevel@tonic-gate 		    break;
19690Sstevel@tonic-gate 		case 'c':		/* FAT32 */
19700Sstevel@tonic-gate 		case 'C':
19710Sstevel@tonic-gate 		    tsystid = FDISK_WINDOWS;
19720Sstevel@tonic-gate 		    break;
19730Sstevel@tonic-gate 		case 'd':		/* FAT32 and need extended int13 */
19740Sstevel@tonic-gate 		case 'D':
19750Sstevel@tonic-gate 		    tsystid = FDISK_EXT_WIN;
19760Sstevel@tonic-gate 		    break;
19770Sstevel@tonic-gate 		case 'e':	/* Extended partition, need extended int13 */
19780Sstevel@tonic-gate 		case 'E':
19790Sstevel@tonic-gate 		    tsystid = FDISK_EXTLBA;
19800Sstevel@tonic-gate 		    break;
19810Sstevel@tonic-gate 		case 'f':
19820Sstevel@tonic-gate 		case 'F':
19830Sstevel@tonic-gate 		    tsystid = EFI_PMBR;
19840Sstevel@tonic-gate 		    break;
19850Sstevel@tonic-gate 		default:
1986*251Slclee 		    (void) printf(E_LINE);
1987*251Slclee 		    (void) printf("Invalid selection, try again.");
19880Sstevel@tonic-gate 		    continue;
19890Sstevel@tonic-gate 		}
19900Sstevel@tonic-gate 	}
19910Sstevel@tonic-gate 
1992*251Slclee 	(void) printf(E_LINE);
19930Sstevel@tonic-gate 
19940Sstevel@tonic-gate 	if (tsystid != EFI_PMBR) {
19950Sstevel@tonic-gate 		/* create the new partition */
19960Sstevel@tonic-gate 		i = specify(tsystid);
19970Sstevel@tonic-gate 
19980Sstevel@tonic-gate 		if (i != -1) {
19990Sstevel@tonic-gate 			/* see if it should be the active partition */
2000*251Slclee 			(void) printf(E_LINE);
2001*251Slclee 			(void) printf(Q_LINE);
2002*251Slclee 
2003*251Slclee 			(void) printf(
2004*251Slclee 			    "Should this become the active partition? If "
2005*251Slclee 			    "yes, it  will be activated\n"
2006*251Slclee 			    "each time the computer is reset or turned on.\n"
2007*251Slclee 			    "Please type \"y\" or \"n\". ");
20080Sstevel@tonic-gate 
20090Sstevel@tonic-gate 			if (yesno()) {
2010*251Slclee 				(void) printf(E_LINE);
20110Sstevel@tonic-gate 				for (j = 0; j < FD_NUMPART; j++) {
20120Sstevel@tonic-gate 					if (j == i) {
20130Sstevel@tonic-gate 						Table[j].bootid = ACTIVE;
2014*251Slclee 						(void) printf(E_LINE);
2015*251Slclee 						(void) printf(
2016*251Slclee 						    "Partition %d is now "
20170Sstevel@tonic-gate 						    "the active partition.",
2018*251Slclee 						    j + 1);
20190Sstevel@tonic-gate 					} else {
20200Sstevel@tonic-gate 						Table[j].bootid = 0;
20210Sstevel@tonic-gate 					}
20220Sstevel@tonic-gate 				}
20230Sstevel@tonic-gate 			} else {
20240Sstevel@tonic-gate 				Table[i].bootid = 0;
20250Sstevel@tonic-gate 			}
20260Sstevel@tonic-gate 
20270Sstevel@tonic-gate 			/* set up the return code */
20280Sstevel@tonic-gate 			i = 1;
20290Sstevel@tonic-gate 		}
20300Sstevel@tonic-gate 	} else {
20310Sstevel@tonic-gate 		/*
20320Sstevel@tonic-gate 		 * partitions of type EFI_PMBR must be the only partitions in
20330Sstevel@tonic-gate 		 * the table
20340Sstevel@tonic-gate 		 *
20350Sstevel@tonic-gate 		 * First, make sure there were no errors the table is
20360Sstevel@tonic-gate 		 * empty
20370Sstevel@tonic-gate 		 */
20380Sstevel@tonic-gate 		retCode = verify_tbl();
20390Sstevel@tonic-gate 
20400Sstevel@tonic-gate 		if (retCode < 0) {
2041*251Slclee 			(void) fprintf(stderr,
20420Sstevel@tonic-gate 			    "fdisk: Cannot create EFI partition table; \n"
20430Sstevel@tonic-gate 			    "current partition table is invalid.\n");
20440Sstevel@tonic-gate 			return (-1);
20450Sstevel@tonic-gate 		} else if (retCode > 0) {
2046*251Slclee 			(void) printf(
2047*251Slclee 			    "An EFI partition must be the only partition on "
2048*251Slclee 			    "disk.  You may manually delete existing\n"
2049*251Slclee 			    "partitions, or fdisk can do it.\n"
2050*251Slclee 			    "Do you want fdisk to destroy existing "
2051*251Slclee 			    "partitions?\n"
2052*251Slclee 			    "Please type \"y\" or \"n\". ");
20530Sstevel@tonic-gate 
20540Sstevel@tonic-gate 			if (yesno()) {
20550Sstevel@tonic-gate 				nulltbl();
20560Sstevel@tonic-gate 			} else {
20570Sstevel@tonic-gate 				return (-1);
20580Sstevel@tonic-gate 			}
20590Sstevel@tonic-gate 		}
20600Sstevel@tonic-gate 
20610Sstevel@tonic-gate 		/* create the table entry - i should be 0 */
20620Sstevel@tonic-gate 		i = insert_tbl(tsystid, 0, 0, 0, 0, 0, 0, 0, rsect,
20630Sstevel@tonic-gate 			(Numcyl * heads * sectors) - rsect);
20640Sstevel@tonic-gate 
20650Sstevel@tonic-gate 		if (i != 0) {
2066*251Slclee 			(void) printf("Error creating EFI partition!!!\n");
20670Sstevel@tonic-gate 			i = -1;
20680Sstevel@tonic-gate 		} else {
20690Sstevel@tonic-gate 
20700Sstevel@tonic-gate 			/* EFI partitions are currently never active */
20710Sstevel@tonic-gate 			Table[i].bootid = 0;
20720Sstevel@tonic-gate 
20730Sstevel@tonic-gate 			/* set up the return code */
20740Sstevel@tonic-gate 			i = 1;
20750Sstevel@tonic-gate 		}
20760Sstevel@tonic-gate 	}
20770Sstevel@tonic-gate 
20780Sstevel@tonic-gate 	return (i);
20790Sstevel@tonic-gate }
20800Sstevel@tonic-gate 
20810Sstevel@tonic-gate /*
20820Sstevel@tonic-gate  * specify
20830Sstevel@tonic-gate  * Query the user to specify the size of the new partition in
20840Sstevel@tonic-gate  * terms of percentage of the disk or by specifying the starting
20850Sstevel@tonic-gate  * cylinder and length in cylinders.
20860Sstevel@tonic-gate  */
2087*251Slclee static int
2088*251Slclee specify(uchar_t tsystid)
20890Sstevel@tonic-gate {
20900Sstevel@tonic-gate 	int	i, j,
20910Sstevel@tonic-gate 		percent = -1;
20920Sstevel@tonic-gate 	int	cyl, cylen, first_free, size_free;
20930Sstevel@tonic-gate 	struct ipart *partition[FD_NUMPART];
20940Sstevel@tonic-gate 
2095*251Slclee 	(void) printf(Q_LINE);
2096*251Slclee 	(void) printf(
2097*251Slclee 	    "Specify the percentage of disk to use for this partition\n"
2098*251Slclee 	    "(or type \"c\" to specify the size in cylinders). ");
2099*251Slclee 	(void) gets(s);
21000Sstevel@tonic-gate 	rm_blanks(s);
21010Sstevel@tonic-gate 	if (s[0] != 'c') {	/* Specify size in percentage of disk */
21020Sstevel@tonic-gate 	    i = 0;
21030Sstevel@tonic-gate 	    while (s[i] != '\0') {
21040Sstevel@tonic-gate 		if (s[i] < '0' || s[i] > '9') {
2105*251Slclee 		    (void) printf(E_LINE);
2106*251Slclee 		    (void) printf("Invalid percentage value specified; retry"
21070Sstevel@tonic-gate 			" the operation.");
21080Sstevel@tonic-gate 		    return (-1);
21090Sstevel@tonic-gate 		}
21100Sstevel@tonic-gate 		i++;
21110Sstevel@tonic-gate 		if (i > 3) {
2112*251Slclee 		    (void) printf(E_LINE);
2113*251Slclee 		    (void) printf("Invalid percentage value specified; retry"
21140Sstevel@tonic-gate 			" the operation.");
21150Sstevel@tonic-gate 		    return (-1);
21160Sstevel@tonic-gate 		}
21170Sstevel@tonic-gate 	    }
21180Sstevel@tonic-gate 	    if ((percent = atoi(s)) > 100) {
2119*251Slclee 		(void) printf(E_LINE);
2120*251Slclee 		(void) printf(
2121*251Slclee 		    "Percentage value is too large. The value must be"
21220Sstevel@tonic-gate 		    " between 1 and 100;\nretry the operation.\n");
21230Sstevel@tonic-gate 		return (-1);
21240Sstevel@tonic-gate 	    }
21250Sstevel@tonic-gate 	    if (percent < 1) {
2126*251Slclee 		(void) printf(E_LINE);
2127*251Slclee 		(void) printf(
2128*251Slclee 		    "Percentage value is too small. The value must be"
21290Sstevel@tonic-gate 		    " between 1 and 100;\nretry the operation.\n");
21300Sstevel@tonic-gate 		return (-1);
21310Sstevel@tonic-gate 	    }
21320Sstevel@tonic-gate 
21330Sstevel@tonic-gate 	    cylen = (Numcyl * percent) / 100;
21340Sstevel@tonic-gate 	    if ((percent < 100) && (((Numcyl * percent) % 10) > 5))
21350Sstevel@tonic-gate 		cylen++;
21360Sstevel@tonic-gate 
21370Sstevel@tonic-gate 	    /* Verify that the DOS12 partition does not exceed the maximum */
21380Sstevel@tonic-gate 	    /* size of 32MB. */
2139*251Slclee 	    if ((tsystid == DOSOS12) && ((long)((long)cylen * heads * sectors) >
21400Sstevel@tonic-gate 		MAXDOS)) {
21410Sstevel@tonic-gate 		int n;
2142*251Slclee 		n = (int)(MAXDOS * 100 / (int)(heads * sectors) / Numcyl);
2143*251Slclee 		(void) printf(E_LINE);
2144*251Slclee 		(void) printf("Maximum size for a DOS partition is %d%%;"
21450Sstevel@tonic-gate 		    " retry the operation.",
21460Sstevel@tonic-gate 		    n <= 100 ? n : 100);
21470Sstevel@tonic-gate 		return (-1);
21480Sstevel@tonic-gate 	    }
21490Sstevel@tonic-gate 
21500Sstevel@tonic-gate 	    /* Before searching the partitions, sort them into sector order */
21510Sstevel@tonic-gate 	    /* in the partition array, note that we only need to sort */
21520Sstevel@tonic-gate 	    /* NUMPART-1 entries as at least the last one must be empty */
21530Sstevel@tonic-gate 	    for (i = 0; i < FD_NUMPART; i++) partition[i] = &Table[i];
21540Sstevel@tonic-gate 
2155*251Slclee 	    for (i = 0; i < FD_NUMPART - 2; i++) {
21560Sstevel@tonic-gate 		if (partition[i]->systid == UNUSED) break;
2157*251Slclee 		for (j = i + 1; j < FD_NUMPART - 1; j++) {
21580Sstevel@tonic-gate 		    if (partition[j]->systid == UNUSED) break;
21590Sstevel@tonic-gate 		    if (lel(partition[j]->relsect) <
21600Sstevel@tonic-gate 				lel(partition[i]->relsect)) {
21610Sstevel@tonic-gate 			struct ipart *temp = partition[i];
21620Sstevel@tonic-gate 			partition[i] = partition[j];
21630Sstevel@tonic-gate 			partition[j] = temp;
21640Sstevel@tonic-gate 		    }
21650Sstevel@tonic-gate 		}
21660Sstevel@tonic-gate 	    }
21670Sstevel@tonic-gate 
21680Sstevel@tonic-gate 	    for (i = 0; i < FD_NUMPART; i++) {
21690Sstevel@tonic-gate 		    int last_ent = 0;
21700Sstevel@tonic-gate 
21710Sstevel@tonic-gate 		    /* Find start of current check area */
21720Sstevel@tonic-gate 		    if (i) { /* Not an empty table */
2173*251Slclee 			    first_free = lel(partition[i - 1]->relsect) +
2174*251Slclee 				lel(partition[i - 1]->numsect);
21750Sstevel@tonic-gate 		    } else {
21760Sstevel@tonic-gate 			    first_free = heads * sectors;
21770Sstevel@tonic-gate 		    }
21780Sstevel@tonic-gate 
21790Sstevel@tonic-gate 		    /* Determine size of current check area */
21800Sstevel@tonic-gate 		    if (partition[i]->systid == UNUSED) {
21810Sstevel@tonic-gate 			    /* Special case hack for whole unused disk */
21820Sstevel@tonic-gate 			    if (percent == 100 && i == 0)
21830Sstevel@tonic-gate 				cylen--;
2184*251Slclee 			    size_free = (Numcyl * heads * sectors) - first_free;
21850Sstevel@tonic-gate 			    last_ent++;
21860Sstevel@tonic-gate 		    } else {
2187*251Slclee 			    if (i && ((lel(partition[i - 1]->relsect) +
2188*251Slclee 				lel(partition[i - 1]->numsect)) !=
21890Sstevel@tonic-gate 				lel(partition[i]->relsect))) {
21900Sstevel@tonic-gate 				    /* There is a hole in table */
21910Sstevel@tonic-gate 				    size_free = lel(partition[i]->relsect) -
2192*251Slclee 					(lel(partition[i - 1]->relsect) +
2193*251Slclee 					lel(partition[i - 1]->numsect));
21940Sstevel@tonic-gate 			    } else if (i == 0) {
21950Sstevel@tonic-gate 				    size_free = lel(partition[i]->relsect) -
2196*251Slclee 					heads * sectors;
21970Sstevel@tonic-gate 			    } else {
21980Sstevel@tonic-gate 				    size_free = 0;
21990Sstevel@tonic-gate 			    }
22000Sstevel@tonic-gate 		    }
22010Sstevel@tonic-gate 
2202*251Slclee 		    if ((cylen * heads * sectors) <= size_free) {
22030Sstevel@tonic-gate 			    /* We found a place to use */
22040Sstevel@tonic-gate 			    break;
22050Sstevel@tonic-gate 		    } else if (last_ent) {
22060Sstevel@tonic-gate 			    size_free = 0;
22070Sstevel@tonic-gate 			    break;
22080Sstevel@tonic-gate 		    }
22090Sstevel@tonic-gate 	    }
22100Sstevel@tonic-gate 	    if (i < FD_NUMPART && size_free) {
2211*251Slclee 		    (void) printf(E_LINE);
22120Sstevel@tonic-gate 		    if ((i = insert_tbl(tsystid, 0, 0, 0, 0, 0, 0, 0,
2213*251Slclee 			first_free, cylen * heads * sectors)) < 0)  {
2214*251Slclee 			    (void) fprintf(stderr,
22150Sstevel@tonic-gate 				"fdisk: Partition entry too big.\n");
22160Sstevel@tonic-gate 			    return (-1);
22170Sstevel@tonic-gate 		    }
22180Sstevel@tonic-gate 	    } else {
2219*251Slclee 		    (void) printf(E_LINE);
2220*251Slclee 		    (void) fprintf(stderr, "fdisk: Partition entry too big.\n");
22210Sstevel@tonic-gate 		    i = -1;
22220Sstevel@tonic-gate 	    }
22230Sstevel@tonic-gate 	    return (i);
22240Sstevel@tonic-gate 	} else {	/* Specifying size in cylinders */
22250Sstevel@tonic-gate 
2226*251Slclee 	    (void) printf(E_LINE);
2227*251Slclee 	    (void) printf(Q_LINE);
2228*251Slclee 	    (void) printf("Enter starting cylinder number: ");
22290Sstevel@tonic-gate 	    if ((cyl = getcyl()) == -1) {
2230*251Slclee 		(void) printf(E_LINE);
2231*251Slclee 		(void) printf("Invalid number; retry the operation.");
22320Sstevel@tonic-gate 		return (-1);
22330Sstevel@tonic-gate 	    }
22340Sstevel@tonic-gate 	    if (cyl == 0) {
2235*251Slclee 		(void) printf(E_LINE);
2236*251Slclee 		(void) printf("New partition cannot start at cylinder 0.\n");
22370Sstevel@tonic-gate 		return (-1);
22380Sstevel@tonic-gate 	    }
22390Sstevel@tonic-gate 	    if (cyl >= (unsigned int)Numcyl) {
2240*251Slclee 		(void) printf(E_LINE);
2241*251Slclee 		(void) printf(
2242*251Slclee 		    "Cylinder %d is out of bounds, the maximum is %d.\n",
22430Sstevel@tonic-gate 		    cyl, Numcyl - 1);
22440Sstevel@tonic-gate 		return (-1);
22450Sstevel@tonic-gate 	    }
2246*251Slclee 	    (void) printf(Q_LINE);
2247*251Slclee 	    (void) printf("Enter partition size in cylinders: ");
22480Sstevel@tonic-gate 	    if ((cylen = getcyl()) == -1) {
2249*251Slclee 		(void) printf(E_LINE);
2250*251Slclee 		(void) printf("Invalid number, retry the operation.");
22510Sstevel@tonic-gate 		return (-1);
22520Sstevel@tonic-gate 	    }
22530Sstevel@tonic-gate 
22540Sstevel@tonic-gate 	    /* Verify that the DOS12 partition does not exceed the maximum */
22550Sstevel@tonic-gate 	    /* size of 32MB. */
22560Sstevel@tonic-gate 	    if ((tsystid == DOSOS12) &&
2257*251Slclee 		((long)((long)cylen * heads * sectors) > MAXDOS)) {
2258*251Slclee 		(void) printf(E_LINE);
2259*251Slclee 		(void) printf(
2260*251Slclee 		    "Maximum size for a %s partition is %ld cylinders;"
22610Sstevel@tonic-gate 		    "\nretry the operation.",
2262*251Slclee 		    Dstr, MAXDOS / (int)(heads * sectors));
22630Sstevel@tonic-gate 		return (-1);
22640Sstevel@tonic-gate 	    }
22650Sstevel@tonic-gate 
2266*251Slclee 	    i = insert_tbl(tsystid, 0, 0, 0, 0, 0, 0, 0, cyl * heads * sectors,
2267*251Slclee 		cylen * heads * sectors);
22680Sstevel@tonic-gate 
22690Sstevel@tonic-gate 	    if (verify_tbl() < 0) {
2270*251Slclee 		(void) printf(E_LINE);
2271*251Slclee 		(void) printf("fdisk: Cannot create partition table\n");
22720Sstevel@tonic-gate 		return (-1);
22730Sstevel@tonic-gate 	    }
22740Sstevel@tonic-gate 
22750Sstevel@tonic-gate 	    return (i);
22760Sstevel@tonic-gate 	}
22770Sstevel@tonic-gate }
22780Sstevel@tonic-gate 
22790Sstevel@tonic-gate /*
22800Sstevel@tonic-gate  * dispmenu
22810Sstevel@tonic-gate  * Display command menu (interactive mode).
22820Sstevel@tonic-gate  */
2283*251Slclee static void
2284*251Slclee dispmenu(void)
22850Sstevel@tonic-gate {
2286*251Slclee 	(void) printf(M_LINE);
2287*251Slclee 	(void) printf(
2288*251Slclee 	    "SELECT ONE OF THE FOLLOWING:\n"
2289*251Slclee 	    "   1. Create a partition\n"
2290*251Slclee 	    "   2. Specify the active partition\n"
2291*251Slclee 	    "   3. Delete a partition\n"
2292*251Slclee 	    "   4. Change between Solaris and Solaris2 Partition IDs\n"
2293*251Slclee 	    "   5. Exit (update disk configuration and exit)\n"
2294*251Slclee 	    "   6. Cancel (exit without updating disk configuration)\n");
22950Sstevel@tonic-gate }
22960Sstevel@tonic-gate 
22970Sstevel@tonic-gate /*
22980Sstevel@tonic-gate  * pchange
22990Sstevel@tonic-gate  * Change the ACTIVE designation of a partition.
23000Sstevel@tonic-gate  */
2301*251Slclee static int
2302*251Slclee pchange(void)
23030Sstevel@tonic-gate {
23040Sstevel@tonic-gate 	char s[80];
23050Sstevel@tonic-gate 	int i, j;
23060Sstevel@tonic-gate 
2307*251Slclee 	for (;;) {
2308*251Slclee 		(void) printf(Q_LINE);
23090Sstevel@tonic-gate 			{
2310*251Slclee 			(void) printf(
2311*251Slclee 			    "Specify the partition number to boot from"
23120Sstevel@tonic-gate 			    " (or specify 0 for none): ");
23130Sstevel@tonic-gate 			}
2314*251Slclee 		(void) gets(s);
23150Sstevel@tonic-gate 		rm_blanks(s);
23160Sstevel@tonic-gate 		if ((s[1] != 0) || (s[0] < '0') || (s[0] > '4')) {
2317*251Slclee 			(void) printf(E_LINE);
2318*251Slclee 			(void) printf(
2319*251Slclee 			    "Invalid response, please specify a number"
23200Sstevel@tonic-gate 			    " between 0 and 4.\n");
23210Sstevel@tonic-gate 		} else {
23220Sstevel@tonic-gate 			break;
23230Sstevel@tonic-gate 		}
23240Sstevel@tonic-gate 	}
23250Sstevel@tonic-gate 	if (s[0] == '0') {	/* No active partitions */
23260Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
23270Sstevel@tonic-gate 			if (Table[i].systid != UNUSED &&
23280Sstevel@tonic-gate 			    Table[i].bootid == ACTIVE)
23290Sstevel@tonic-gate 				Table[i].bootid = 0;
23300Sstevel@tonic-gate 		}
2331*251Slclee 		(void) printf(E_LINE);
2332*251Slclee 			(void) printf(
2333*251Slclee 			    "No partition is currently marked as active.");
23340Sstevel@tonic-gate 		return (0);
23350Sstevel@tonic-gate 	} else {	/* User has selected a partition to be active */
23360Sstevel@tonic-gate 		i = s[0] - '1';
23370Sstevel@tonic-gate 		if (Table[i].systid == UNUSED) {
2338*251Slclee 			(void) printf(E_LINE);
2339*251Slclee 			(void) printf("Partition does not exist.");
23400Sstevel@tonic-gate 			return (-1);
23410Sstevel@tonic-gate 		}
23420Sstevel@tonic-gate 		/* a DOS-DATA or EXT-DOS partition cannot be active */
23430Sstevel@tonic-gate 		else if ((Table[i].systid == DOSDATA) ||
23440Sstevel@tonic-gate 		    (Table[i].systid == EXTDOS) ||
23450Sstevel@tonic-gate 		    (Table[i].systid == FDISK_EXTLBA)) {
2346*251Slclee 			(void) printf(E_LINE);
2347*251Slclee 			(void) printf(
2348*251Slclee 			    "DOS-DATA, EXT_DOS and EXT_DOS_LBA partitions "
23490Sstevel@tonic-gate 			    "cannot be made active.\n");
2350*251Slclee 			(void) printf("Select another partition.");
23510Sstevel@tonic-gate 			return (-1);
23520Sstevel@tonic-gate 		}
23530Sstevel@tonic-gate 		Table[i].bootid = ACTIVE;
23540Sstevel@tonic-gate 		for (j = 0; j < FD_NUMPART; j++) {
23550Sstevel@tonic-gate 			if (j != i)
23560Sstevel@tonic-gate 			Table[j].bootid = 0;
23570Sstevel@tonic-gate 		}
23580Sstevel@tonic-gate 	}
2359*251Slclee 	(void) printf(E_LINE);
23600Sstevel@tonic-gate 		{
2361*251Slclee 		(void) printf(
2362*251Slclee 		    "Partition %d is now active. The system will start up"
2363*251Slclee 		    " from this\n", i + 1);
2364*251Slclee 		(void) printf("partition after the next reboot.");
23650Sstevel@tonic-gate 		}
23660Sstevel@tonic-gate 	return (1);
23670Sstevel@tonic-gate }
23680Sstevel@tonic-gate 
23690Sstevel@tonic-gate /*
23700Sstevel@tonic-gate  * Change between SOLARIS and SOLARIS2 partition id
23710Sstevel@tonic-gate  */
2372*251Slclee static int
2373*251Slclee ppartid(void)
23740Sstevel@tonic-gate {
23750Sstevel@tonic-gate 	char	*p, s[80];
23760Sstevel@tonic-gate 	int	i;
23770Sstevel@tonic-gate 
23780Sstevel@tonic-gate 	for (;;) {
2379*251Slclee 		(void) printf(Q_LINE);
2380*251Slclee 		(void) printf("Specify the partition number to change"
23810Sstevel@tonic-gate 			" (or enter 0 to exit): ");
2382*251Slclee 		if (!fgets(s, sizeof (s), stdin))
2383*251Slclee 			return (1);
23840Sstevel@tonic-gate 		i = strtol(s, &p, 10);
23850Sstevel@tonic-gate 
23860Sstevel@tonic-gate 		if (*p != '\n' || i < 0 || i > FD_NUMPART) {
2387*251Slclee 			(void) printf(E_LINE);
2388*251Slclee 			(void) printf(
2389*251Slclee 			    "Invalid response, retry the operation.\n");
23900Sstevel@tonic-gate 			continue;
23910Sstevel@tonic-gate 		}
23920Sstevel@tonic-gate 
23930Sstevel@tonic-gate 		if (i == 0) {
23940Sstevel@tonic-gate 			/* exit delete command */
2395*251Slclee 			(void) printf(E_LINE); /* clear error message */
23960Sstevel@tonic-gate 			return (1);
23970Sstevel@tonic-gate 		}
23980Sstevel@tonic-gate 
23990Sstevel@tonic-gate 		i -= 1;
24000Sstevel@tonic-gate 		if (Table[i].systid == SUNIXOS) {
24010Sstevel@tonic-gate 			Table[i].systid = SUNIXOS2;
24020Sstevel@tonic-gate 		} else if (Table[i].systid == SUNIXOS2) {
24030Sstevel@tonic-gate 			Table[i].systid = SUNIXOS;
24040Sstevel@tonic-gate 		} else {
2405*251Slclee 			(void) printf(E_LINE);
2406*251Slclee 			(void) printf(
2407*251Slclee 			    "Partition %d is not a Solaris partition.",
24080Sstevel@tonic-gate 			    i + 1);
24090Sstevel@tonic-gate 			continue;
24100Sstevel@tonic-gate 		}
24110Sstevel@tonic-gate 
2412*251Slclee 		(void) printf(E_LINE);
2413*251Slclee 		(void) printf("Partition %d has been changed.", i + 1);
24140Sstevel@tonic-gate 		return (1);
24150Sstevel@tonic-gate 	}
24160Sstevel@tonic-gate }
24170Sstevel@tonic-gate 
24180Sstevel@tonic-gate /*
24190Sstevel@tonic-gate  * pdelete
24200Sstevel@tonic-gate  * Remove partition entry from the table (interactive mode).
24210Sstevel@tonic-gate  */
2422*251Slclee static char
2423*251Slclee pdelete(void)
24240Sstevel@tonic-gate {
24250Sstevel@tonic-gate 	char s[80];
24260Sstevel@tonic-gate 	int i, j;
24270Sstevel@tonic-gate 	char pactive;
24280Sstevel@tonic-gate 
2429*251Slclee DEL1:	(void) printf(Q_LINE);
2430*251Slclee 	(void) printf("Specify the partition number to delete"
24310Sstevel@tonic-gate 	    " (or enter 0 to exit): ");
2432*251Slclee 	(void) gets(s);
24330Sstevel@tonic-gate 	rm_blanks(s);
24340Sstevel@tonic-gate 	if ((s[0] == '0')) {	/* exit delete command */
2435*251Slclee 		(void) printf(E_LINE);	/* clear error message */
24360Sstevel@tonic-gate 		return (1);
24370Sstevel@tonic-gate 	}
24380Sstevel@tonic-gate 	/* Accept only a single digit between 1 and 4 */
24390Sstevel@tonic-gate 	if (s[1] != 0 || (i = atoi(s)) < 1 || i > FD_NUMPART) {
2440*251Slclee 		(void) printf(E_LINE);
2441*251Slclee 		(void) printf("Invalid response, retry the operation.\n");
24420Sstevel@tonic-gate 		goto DEL1;
24430Sstevel@tonic-gate 	} else {		/* Found a digit between 1 and 4 */
24440Sstevel@tonic-gate 		--i;	/* Structure begins with element 0 */
24450Sstevel@tonic-gate 	}
24460Sstevel@tonic-gate 
24470Sstevel@tonic-gate 	if (Table[i].systid == UNUSED) {
2448*251Slclee 		(void) printf(E_LINE);
2449*251Slclee 		(void) printf("Partition %d does not exist.", i + 1);
24500Sstevel@tonic-gate 		return (-1);
24510Sstevel@tonic-gate 	}
24520Sstevel@tonic-gate 
2453*251Slclee 	(void) printf(Q_LINE);
2454*251Slclee 	(void) printf("Are you sure you want to delete partition %d?"
2455*251Slclee 	    " This will make all files and \n", i + 1);
2456*251Slclee 	(void) printf("programs in this partition inaccessible (type"
24570Sstevel@tonic-gate 	    " \"y\" or \"n\"). ");
24580Sstevel@tonic-gate 
2459*251Slclee 	(void) printf(E_LINE);
24600Sstevel@tonic-gate 	if (! yesno()) {
24610Sstevel@tonic-gate 		return (1);
24620Sstevel@tonic-gate 	}
24630Sstevel@tonic-gate 
24640Sstevel@tonic-gate 	if (Table[i].bootid == ACTIVE) {
24650Sstevel@tonic-gate 		pactive = 1;
24660Sstevel@tonic-gate 	} else {
24670Sstevel@tonic-gate 		pactive = 0;
24680Sstevel@tonic-gate 	}
24690Sstevel@tonic-gate 
24700Sstevel@tonic-gate 	for (j = i; j < FD_NUMPART - 1; j++) {
2471*251Slclee 	    Table[j] = Table[j + 1];
24720Sstevel@tonic-gate 	}
24730Sstevel@tonic-gate 
24740Sstevel@tonic-gate 	Table[j].systid = UNUSED;
24750Sstevel@tonic-gate 	Table[j].numsect = 0;
24760Sstevel@tonic-gate 	Table[j].relsect = 0;
24770Sstevel@tonic-gate 	Table[j].bootid = 0;
2478*251Slclee 	(void) printf(E_LINE);
2479*251Slclee 	(void) printf("Partition %d has been deleted.", i + 1);
24800Sstevel@tonic-gate 
24810Sstevel@tonic-gate 	if (pactive) {
2482*251Slclee 	    (void) printf(" This was the active partition.");
24830Sstevel@tonic-gate 	}
24840Sstevel@tonic-gate 
24850Sstevel@tonic-gate 	return (1);
24860Sstevel@tonic-gate }
24870Sstevel@tonic-gate 
24880Sstevel@tonic-gate /*
24890Sstevel@tonic-gate  * rm_blanks
24900Sstevel@tonic-gate  * Remove blanks from strings of user responses.
24910Sstevel@tonic-gate  */
2492*251Slclee static void
2493*251Slclee rm_blanks(char *s)
24940Sstevel@tonic-gate {
24950Sstevel@tonic-gate 	register int i, j;
24960Sstevel@tonic-gate 
24970Sstevel@tonic-gate 	for (i = 0; i < CBUFLEN; i++) {
24980Sstevel@tonic-gate 		if ((s[i] == ' ') || (s[i] == '\t'))
24990Sstevel@tonic-gate 			continue;
25000Sstevel@tonic-gate 		else
25010Sstevel@tonic-gate 			/* Found first non-blank character of the string */
25020Sstevel@tonic-gate 			break;
25030Sstevel@tonic-gate 	}
25040Sstevel@tonic-gate 	for (j = 0; i < CBUFLEN; j++, i++) {
25050Sstevel@tonic-gate 		if ((s[j] = s[i]) == '\0') {
25060Sstevel@tonic-gate 			/* Reached end of string */
25070Sstevel@tonic-gate 			return;
25080Sstevel@tonic-gate 		}
25090Sstevel@tonic-gate 	}
25100Sstevel@tonic-gate }
25110Sstevel@tonic-gate 
25120Sstevel@tonic-gate /*
25130Sstevel@tonic-gate  * getcyl
25140Sstevel@tonic-gate  * Take the user-specified cylinder number and convert it from a
25150Sstevel@tonic-gate  * string to a decimal value.
25160Sstevel@tonic-gate  */
2517*251Slclee static int
2518*251Slclee getcyl(void)
25190Sstevel@tonic-gate {
25200Sstevel@tonic-gate int slen, i, j;
25210Sstevel@tonic-gate unsigned int cyl;
2522*251Slclee 	(void) gets(s);
25230Sstevel@tonic-gate 	rm_blanks(s);
25240Sstevel@tonic-gate 	slen = strlen(s);
25250Sstevel@tonic-gate 	j = 1;
25260Sstevel@tonic-gate 	cyl = 0;
2527*251Slclee 	for (i = slen - 1; i >= 0; i--) {
25280Sstevel@tonic-gate 		if (s[i] < '0' || s[i] > '9') {
25290Sstevel@tonic-gate 			return (-1);
25300Sstevel@tonic-gate 		}
2531*251Slclee 		cyl += (j * (s[i] - '0'));
25320Sstevel@tonic-gate 		j *= 10;
25330Sstevel@tonic-gate 	}
25340Sstevel@tonic-gate 	return (cyl);
25350Sstevel@tonic-gate }
25360Sstevel@tonic-gate 
25370Sstevel@tonic-gate /*
25380Sstevel@tonic-gate  * disptbl
25390Sstevel@tonic-gate  * Display the current fdisk table; determine percentage
25400Sstevel@tonic-gate  * of the disk used for each partition.
25410Sstevel@tonic-gate  */
2542*251Slclee static void
2543*251Slclee disptbl(void)
25440Sstevel@tonic-gate {
25450Sstevel@tonic-gate 	int i;
25460Sstevel@tonic-gate 	unsigned int startcyl, endcyl, length, percent, remainder;
25470Sstevel@tonic-gate 	char *stat, *type;
25480Sstevel@tonic-gate 
25490Sstevel@tonic-gate 	if ((heads == 0) || (sectors == 0)) {
2550*251Slclee 		(void) printf("WARNING: critical disk geometry information"
25510Sstevel@tonic-gate 			" missing!\n");
2552*251Slclee 		(void) printf("\theads = %d, sectors = %d\n", heads, sectors);
25530Sstevel@tonic-gate 		exit(1);
25540Sstevel@tonic-gate 	}
25550Sstevel@tonic-gate 
2556*251Slclee 	(void) printf(HOME);
2557*251Slclee 	(void) printf(T_LINE);
2558*251Slclee 	(void) printf("             Total disk size is %d cylinders\n", Numcyl);
2559*251Slclee 	(void) printf("             Cylinder size is %d (512 byte) blocks\n\n",
2560*251Slclee 	    heads * sectors);
2561*251Slclee 	(void) printf(
2562*251Slclee 	    "                                               Cylinders\n");
2563*251Slclee 	(void) printf(
2564*251Slclee 	    "      Partition   Status    Type          Start   End   Length"
25650Sstevel@tonic-gate 	    "    %%\n");
2566*251Slclee 	(void) printf(
2567*251Slclee 	    "      =========   ======    ============  =====   ===   ======"
25680Sstevel@tonic-gate 	    "   ===");
25690Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
25700Sstevel@tonic-gate 		if (Table[i].systid == UNUSED) {
2571*251Slclee 			(void) printf("\n");
2572*251Slclee 			(void) printf(CLR_LIN);
25730Sstevel@tonic-gate 			continue;
25740Sstevel@tonic-gate 		}
25750Sstevel@tonic-gate 		if (Table[i].bootid == ACTIVE)
25760Sstevel@tonic-gate 		    stat = Actvstr;
25770Sstevel@tonic-gate 		else
25780Sstevel@tonic-gate 		    stat = NAstr;
25790Sstevel@tonic-gate 		switch (Table[i].systid) {
25800Sstevel@tonic-gate 		case UNIXOS:
25810Sstevel@tonic-gate 		    type = Ustr;
25820Sstevel@tonic-gate 		    break;
25830Sstevel@tonic-gate 		case SUNIXOS:
25840Sstevel@tonic-gate 		    type = SUstr;
25850Sstevel@tonic-gate 		    break;
25860Sstevel@tonic-gate 		case SUNIXOS2:
25870Sstevel@tonic-gate 		    type = SU2str;
25880Sstevel@tonic-gate 		    break;
25890Sstevel@tonic-gate 		case X86BOOT:
25900Sstevel@tonic-gate 		    type = X86str;
25910Sstevel@tonic-gate 		    break;
25920Sstevel@tonic-gate 		case DOSOS12:
25930Sstevel@tonic-gate 		    type = Dstr;
25940Sstevel@tonic-gate 		    break;
25950Sstevel@tonic-gate 		case DOSOS16:
25960Sstevel@tonic-gate 		    type = D16str;
25970Sstevel@tonic-gate 		    break;
25980Sstevel@tonic-gate 		case EXTDOS:
25990Sstevel@tonic-gate 		    type = EDstr;
26000Sstevel@tonic-gate 		    break;
26010Sstevel@tonic-gate 		case DOSDATA:
26020Sstevel@tonic-gate 		    type = DDstr;
26030Sstevel@tonic-gate 		    break;
26040Sstevel@tonic-gate 		case DOSHUGE:
26050Sstevel@tonic-gate 		    type = DBstr;
26060Sstevel@tonic-gate 		    break;
26070Sstevel@tonic-gate 		case PCIXOS:
26080Sstevel@tonic-gate 		    type = PCstr;
26090Sstevel@tonic-gate 		    break;
26100Sstevel@tonic-gate 		case DIAGPART:
26110Sstevel@tonic-gate 		    type = DIAGstr;
26120Sstevel@tonic-gate 		    break;
26130Sstevel@tonic-gate 		case FDISK_IFS:
26140Sstevel@tonic-gate 		    type = IFSstr;
26150Sstevel@tonic-gate 		    break;
26160Sstevel@tonic-gate 		case FDISK_AIXBOOT:
26170Sstevel@tonic-gate 		    type = AIXstr;
26180Sstevel@tonic-gate 		    break;
26190Sstevel@tonic-gate 		case FDISK_AIXDATA:
26200Sstevel@tonic-gate 		    type = AIXDstr;
26210Sstevel@tonic-gate 		    break;
26220Sstevel@tonic-gate 		case FDISK_OS2BOOT:
26230Sstevel@tonic-gate 		    type = OS2str;
26240Sstevel@tonic-gate 		    break;
26250Sstevel@tonic-gate 		case FDISK_WINDOWS:
26260Sstevel@tonic-gate 		    type = WINstr;
26270Sstevel@tonic-gate 		    break;
26280Sstevel@tonic-gate 		case FDISK_EXT_WIN:
26290Sstevel@tonic-gate 		    type = EWINstr;
26300Sstevel@tonic-gate 		    break;
26310Sstevel@tonic-gate 		case FDISK_FAT95:
26320Sstevel@tonic-gate 		    type = FAT95str;
26330Sstevel@tonic-gate 		    break;
26340Sstevel@tonic-gate 		case FDISK_EXTLBA:
26350Sstevel@tonic-gate 		    type = EXTLstr;
26360Sstevel@tonic-gate 		    break;
26370Sstevel@tonic-gate 		case FDISK_LINUX:
26380Sstevel@tonic-gate 		    type = LINUXstr;
26390Sstevel@tonic-gate 		    break;
26400Sstevel@tonic-gate 		case FDISK_CPM:
26410Sstevel@tonic-gate 		    type = CPMstr;
26420Sstevel@tonic-gate 		    break;
26430Sstevel@tonic-gate 		case FDISK_NOVELL3:
26440Sstevel@tonic-gate 		    type = NOVstr;
26450Sstevel@tonic-gate 		    break;
26460Sstevel@tonic-gate 		case FDISK_QNX4:
26470Sstevel@tonic-gate 		    type = QNXstr;
26480Sstevel@tonic-gate 		    break;
26490Sstevel@tonic-gate 		case FDISK_QNX42:
26500Sstevel@tonic-gate 		    type = QNX2str;
26510Sstevel@tonic-gate 		    break;
26520Sstevel@tonic-gate 		case FDISK_QNX43:
26530Sstevel@tonic-gate 		    type = QNX3str;
26540Sstevel@tonic-gate 		    break;
26550Sstevel@tonic-gate 		case FDISK_LINUXNAT:
26560Sstevel@tonic-gate 		    type = LINNATstr;
26570Sstevel@tonic-gate 		    break;
26580Sstevel@tonic-gate 		case FDISK_NTFSVOL1:
26590Sstevel@tonic-gate 		    type = NTFSVOL1str;
26600Sstevel@tonic-gate 		    break;
26610Sstevel@tonic-gate 		case FDISK_NTFSVOL2:
26620Sstevel@tonic-gate 		    type = NTFSVOL2str;
26630Sstevel@tonic-gate 		    break;
26640Sstevel@tonic-gate 		case FDISK_BSD:
26650Sstevel@tonic-gate 		    type = BSDstr;
26660Sstevel@tonic-gate 		    break;
26670Sstevel@tonic-gate 		case FDISK_NEXTSTEP:
26680Sstevel@tonic-gate 		    type = NEXTSTEPstr;
26690Sstevel@tonic-gate 		    break;
26700Sstevel@tonic-gate 		case FDISK_BSDIFS:
26710Sstevel@tonic-gate 		    type = BSDIFSstr;
26720Sstevel@tonic-gate 		    break;
26730Sstevel@tonic-gate 		case FDISK_BSDISWAP:
26740Sstevel@tonic-gate 		    type = BSDISWAPstr;
26750Sstevel@tonic-gate 		    break;
26760Sstevel@tonic-gate 		case EFI_PMBR:
26770Sstevel@tonic-gate 		    type = EFIstr;
26780Sstevel@tonic-gate 		    break;
26790Sstevel@tonic-gate 		default:
26800Sstevel@tonic-gate 		    type = Ostr;
26810Sstevel@tonic-gate 		    break;
26820Sstevel@tonic-gate 		}
2683*251Slclee 		startcyl = lel(Table[i].relsect) / (heads * sectors);
26840Sstevel@tonic-gate 		length = lel(Table[i].numsect) / (long)(heads * sectors);
26850Sstevel@tonic-gate 		if (lel(Table[i].numsect) % (long)(heads * sectors))
26860Sstevel@tonic-gate 			length++;
26870Sstevel@tonic-gate 		endcyl = startcyl + length - 1;
26880Sstevel@tonic-gate 		percent = length * 100 / Numcyl;
2689*251Slclee 		if ((remainder = (length * 100 % Numcyl)) != 0) {
26900Sstevel@tonic-gate 			if ((remainder * 100 / Numcyl) > 50) {
26910Sstevel@tonic-gate 				/* round up */
26920Sstevel@tonic-gate 				percent++;
26930Sstevel@tonic-gate 			}
26940Sstevel@tonic-gate 			/* Else leave the percent as is since it's already */
26950Sstevel@tonic-gate 			/* rounded down */
26960Sstevel@tonic-gate 		}
26970Sstevel@tonic-gate 		if (percent > 100)
26980Sstevel@tonic-gate 			percent = 100;
2699*251Slclee 		(void) printf(
2700*251Slclee 		    "\n          %d       %s    %-12.12s   %4d  %4d    %4d"
2701*251Slclee 		    "    %3d",
2702*251Slclee 		    i + 1, stat, type, startcyl, endcyl, length, percent);
27030Sstevel@tonic-gate 	}
27040Sstevel@tonic-gate 	/* Print warning message if table is empty */
27050Sstevel@tonic-gate 	if (Table[0].systid == UNUSED) {
2706*251Slclee 		(void) printf(W_LINE);
2707*251Slclee 		(void) printf("WARNING: no partitions are defined!");
27080Sstevel@tonic-gate 	} else {
27090Sstevel@tonic-gate 		/* Clear the warning line */
2710*251Slclee 		(void) printf(W_LINE);
27110Sstevel@tonic-gate 	}
27120Sstevel@tonic-gate }
27130Sstevel@tonic-gate 
27140Sstevel@tonic-gate /*
27150Sstevel@tonic-gate  * print_Table
27160Sstevel@tonic-gate  * Write the detailed fdisk table to standard error for
27170Sstevel@tonic-gate  * the selected disk device.
27180Sstevel@tonic-gate  */
2719*251Slclee static void
2720*251Slclee print_Table(void)
2721*251Slclee {
27220Sstevel@tonic-gate 	int i;
27230Sstevel@tonic-gate 
2724*251Slclee 	(void) fprintf(stderr,
27250Sstevel@tonic-gate 	    "  SYSID ACT BHEAD BSECT BEGCYL   EHEAD ESECT ENDCYL   RELSECT"
27260Sstevel@tonic-gate 	    "   NUMSECT\n");
27270Sstevel@tonic-gate 
27280Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
2729*251Slclee 		(void) fprintf(stderr, "  %-5d ", Table[i].systid);
2730*251Slclee 		(void) fprintf(stderr, "%-3d ", Table[i].bootid);
2731*251Slclee 		(void) fprintf(stderr, "%-5d ", Table[i].beghead);
2732*251Slclee 		(void) fprintf(stderr, "%-5d ", Table[i].begsect & 0x3f);
2733*251Slclee 		(void) fprintf(stderr, "%-8d ", (((uint_t)Table[i].begsect &
27340Sstevel@tonic-gate 			0xc0) << 2) + Table[i].begcyl);
27350Sstevel@tonic-gate 
2736*251Slclee 		(void) fprintf(stderr, "%-5d ", Table[i].endhead);
2737*251Slclee 		(void) fprintf(stderr, "%-5d ", Table[i].endsect & 0x3f);
2738*251Slclee 		(void) fprintf(stderr, "%-8d ", (((uint_t)Table[i].endsect &
27390Sstevel@tonic-gate 			0xc0) << 2) + Table[i].endcyl);
2740*251Slclee 		(void) fprintf(stderr, "%-9d ", lel(Table[i].relsect));
2741*251Slclee 		(void) fprintf(stderr, "%-9d\n", lel(Table[i].numsect));
27420Sstevel@tonic-gate 
27430Sstevel@tonic-gate 	}
27440Sstevel@tonic-gate }
27450Sstevel@tonic-gate 
27460Sstevel@tonic-gate /*
27470Sstevel@tonic-gate  * copy_Table_to_Old_Table
27480Sstevel@tonic-gate  * Copy Table into Old_Table. The function only copies the systid,
27490Sstevel@tonic-gate  * numsect, relsect, and bootid values because they are the only
27500Sstevel@tonic-gate  * ones compared when determining if Table has changed.
27510Sstevel@tonic-gate  */
2752*251Slclee static void
2753*251Slclee copy_Table_to_Old_Table(void)
27540Sstevel@tonic-gate {
27550Sstevel@tonic-gate 	int i;
27560Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++)  {
2757*251Slclee 	    (void) memcpy(&Old_Table[i], &Table[i], sizeof (Table[0]));
27580Sstevel@tonic-gate 	}
27590Sstevel@tonic-gate }
27600Sstevel@tonic-gate 
27610Sstevel@tonic-gate /*
27620Sstevel@tonic-gate  * nulltbl
27630Sstevel@tonic-gate  * Zero out the systid, numsect, relsect, and bootid values in the
27640Sstevel@tonic-gate  * fdisk table.
27650Sstevel@tonic-gate  */
2766*251Slclee static void
2767*251Slclee nulltbl(void)
27680Sstevel@tonic-gate {
27690Sstevel@tonic-gate 	int i;
27700Sstevel@tonic-gate 
27710Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++)  {
27720Sstevel@tonic-gate 	    Table[i].systid = UNUSED;
27730Sstevel@tonic-gate 	    Table[i].numsect = lel(UNUSED);
27740Sstevel@tonic-gate 	    Table[i].relsect = lel(UNUSED);
27750Sstevel@tonic-gate 	    Table[i].bootid = 0;
27760Sstevel@tonic-gate 	}
27770Sstevel@tonic-gate }
27780Sstevel@tonic-gate 
27790Sstevel@tonic-gate /*
27800Sstevel@tonic-gate  * copy_Bootblk_to_Table
27810Sstevel@tonic-gate  * Copy the bytes from the boot record to an internal "Table".
27820Sstevel@tonic-gate  * All unused are padded with zeros starting at offset 446.
27830Sstevel@tonic-gate  */
2784*251Slclee static void
2785*251Slclee copy_Bootblk_to_Table(void)
27860Sstevel@tonic-gate {
27870Sstevel@tonic-gate 	int i, j;
27880Sstevel@tonic-gate 	char *bootptr;
27890Sstevel@tonic-gate 	struct ipart iparts[FD_NUMPART];
27900Sstevel@tonic-gate 
27910Sstevel@tonic-gate 	/* Get an aligned copy of the partition tables */
2792*251Slclee 	(void) memcpy(iparts, Bootblk->parts, sizeof (iparts));
27930Sstevel@tonic-gate 	bootptr = (char *)iparts;	/* Points to start of partition table */
27940Sstevel@tonic-gate 	if (les(Bootblk->signature) != MBB_MAGIC)  {
27950Sstevel@tonic-gate 		/* Signature is missing */
27960Sstevel@tonic-gate 		nulltbl();
2797*251Slclee 		(void) memcpy(Bootblk->bootinst, &BootCod, BOOTSZ);
27980Sstevel@tonic-gate 		return;
27990Sstevel@tonic-gate 	}
28000Sstevel@tonic-gate 	/*
28010Sstevel@tonic-gate 	 * When the DOS fdisk command deletes a partition, it is not
28020Sstevel@tonic-gate 	 * recognized by the old algorithm.  The algorithm that
28030Sstevel@tonic-gate 	 * follows looks at each entry in the Bootrec and copies all
28040Sstevel@tonic-gate 	 * those that are valid.
28050Sstevel@tonic-gate 	 */
28060Sstevel@tonic-gate 	j = 0;
28070Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
28080Sstevel@tonic-gate 		if (iparts[i].systid == 0) {
28090Sstevel@tonic-gate 			/* Null entry */
28100Sstevel@tonic-gate 			bootptr += sizeof (struct ipart);
28110Sstevel@tonic-gate 		} else {
2812*251Slclee 			fill_ipart(bootptr, &Table[j]);
28130Sstevel@tonic-gate 			j++;
28140Sstevel@tonic-gate 			bootptr += sizeof (struct ipart);
28150Sstevel@tonic-gate 		}
28160Sstevel@tonic-gate 	}
28170Sstevel@tonic-gate 	for (i = j; i < FD_NUMPART; i++) {
28180Sstevel@tonic-gate 		Table[i].systid = UNUSED;
28190Sstevel@tonic-gate 		Table[i].numsect = lel(UNUSED);
28200Sstevel@tonic-gate 		Table[i].relsect = lel(UNUSED);
28210Sstevel@tonic-gate 		Table[i].bootid = 0;
28220Sstevel@tonic-gate 
28230Sstevel@tonic-gate 	}
28240Sstevel@tonic-gate 	/* For now, always replace the bootcode with ours */
2825*251Slclee 	(void) memcpy(Bootblk->bootinst, &BootCod, BOOTSZ);
28260Sstevel@tonic-gate 	copy_Table_to_Bootblk();
28270Sstevel@tonic-gate }
28280Sstevel@tonic-gate 
28290Sstevel@tonic-gate /*
28300Sstevel@tonic-gate  * fill_ipart
28310Sstevel@tonic-gate  * Initialize ipart structure values.
28320Sstevel@tonic-gate  */
2833*251Slclee static void
28340Sstevel@tonic-gate fill_ipart(char *bootptr, struct ipart *partp)
28350Sstevel@tonic-gate {
28360Sstevel@tonic-gate #ifdef sparc
28370Sstevel@tonic-gate 	/* Packing struct ipart for Sparc */
2838*251Slclee 	partp->bootid	= getbyte(&bootptr);
2839*251Slclee 	partp->beghead	= getbyte(&bootptr);
2840*251Slclee 	partp->begsect	= getbyte(&bootptr);
2841*251Slclee 	partp->begcyl	= getbyte(&bootptr);
2842*251Slclee 	partp->systid	= getbyte(&bootptr);
2843*251Slclee 	partp->endhead	= getbyte(&bootptr);
2844*251Slclee 	partp->endsect	= getbyte(&bootptr);
2845*251Slclee 	partp->endcyl	= getbyte(&bootptr);
2846*251Slclee 	partp->relsect	= (int32_t)getlong(&bootptr);
2847*251Slclee 	partp->numsect	= (int32_t)getlong(&bootptr);
28480Sstevel@tonic-gate #else
28490Sstevel@tonic-gate 	*partp = *(struct ipart *)bootptr;
28500Sstevel@tonic-gate #endif
28510Sstevel@tonic-gate }
28520Sstevel@tonic-gate 
28530Sstevel@tonic-gate /*
2854*251Slclee  * getbyte, getlong
28550Sstevel@tonic-gate  * 	Get a byte, a short, or a long (SPARC only).
28560Sstevel@tonic-gate  */
28570Sstevel@tonic-gate #ifdef sparc
2858*251Slclee uchar_t
2859*251Slclee getbyte(char **bp)
28600Sstevel@tonic-gate {
2861*251Slclee 	uchar_t	b;
2862*251Slclee 
2863*251Slclee 	b = (uchar_t)**bp;
28640Sstevel@tonic-gate 	*bp = *bp + 1;
28650Sstevel@tonic-gate 	return (b);
28660Sstevel@tonic-gate }
28670Sstevel@tonic-gate 
2868*251Slclee uint32_t
2869*251Slclee getlong(char **bp)
28700Sstevel@tonic-gate {
2871*251Slclee 	int32_t	b, bh, bl;
28720Sstevel@tonic-gate 
28730Sstevel@tonic-gate 	bh = ((**bp) << 8) | *(*bp + 1);
28740Sstevel@tonic-gate 	*bp += 2;
28750Sstevel@tonic-gate 	bl = ((**bp) << 8) | *(*bp + 1);
28760Sstevel@tonic-gate 	*bp += 2;
28770Sstevel@tonic-gate 
28780Sstevel@tonic-gate 	b = (bh << 16) | bl;
2879*251Slclee 	return ((uint32_t)b);
28800Sstevel@tonic-gate }
28810Sstevel@tonic-gate #endif
28820Sstevel@tonic-gate 
28830Sstevel@tonic-gate /*
28840Sstevel@tonic-gate  * copy_Table_to_Bootblk
28850Sstevel@tonic-gate  * Copy the table into the 512 boot record. Note that the unused
28860Sstevel@tonic-gate  * entries will always be the last ones in the table and they are
28870Sstevel@tonic-gate  * marked with 100 in sysind. The the unused portion of the table
28880Sstevel@tonic-gate  * is padded with zeros in the bytes after the used entries.
28890Sstevel@tonic-gate  */
2890*251Slclee static void
2891*251Slclee copy_Table_to_Bootblk(void)
28920Sstevel@tonic-gate {
28930Sstevel@tonic-gate 	struct ipart *boot_ptr, *tbl_ptr;
28940Sstevel@tonic-gate 
28950Sstevel@tonic-gate 	boot_ptr = (struct ipart *)Bootblk->parts;
28960Sstevel@tonic-gate 	tbl_ptr = (struct ipart *)&Table[0].bootid;
28970Sstevel@tonic-gate 	for (; tbl_ptr < (struct ipart *)&Table[FD_NUMPART].bootid;
28980Sstevel@tonic-gate 	    tbl_ptr++, boot_ptr++) {
28990Sstevel@tonic-gate 	    if (tbl_ptr->systid == UNUSED)
2900*251Slclee 		(void) memset(boot_ptr, 0, sizeof (struct ipart));
29010Sstevel@tonic-gate 	    else
2902*251Slclee 		(void) memcpy(boot_ptr, tbl_ptr, sizeof (struct ipart));
29030Sstevel@tonic-gate 	}
29040Sstevel@tonic-gate 	Bootblk->signature = les(MBB_MAGIC);
29050Sstevel@tonic-gate }
29060Sstevel@tonic-gate 
29070Sstevel@tonic-gate /*
29080Sstevel@tonic-gate  * TableChanged
29090Sstevel@tonic-gate  * 	Check for any changes in the partition table.
29100Sstevel@tonic-gate  */
2911*251Slclee static int
2912*251Slclee TableChanged(void)
29130Sstevel@tonic-gate {
29140Sstevel@tonic-gate 	int i, changed;
29150Sstevel@tonic-gate 
29160Sstevel@tonic-gate 	changed = 0;
29170Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
29180Sstevel@tonic-gate 	    if (memcmp(&Old_Table[i], &Table[i], sizeof (Table[0])) != 0) {
29190Sstevel@tonic-gate 		/* Partition table changed, write back to disk */
29200Sstevel@tonic-gate 		changed = 1;
29210Sstevel@tonic-gate 	    }
29220Sstevel@tonic-gate 	}
29230Sstevel@tonic-gate 
29240Sstevel@tonic-gate 	return (changed);
29250Sstevel@tonic-gate }
29260Sstevel@tonic-gate 
29270Sstevel@tonic-gate /*
29280Sstevel@tonic-gate  * ffile_write
29290Sstevel@tonic-gate  * 	Display contents of partition table to standard output or
29300Sstevel@tonic-gate  *	another file name without writing it to the disk (-W file).
29310Sstevel@tonic-gate  */
2932*251Slclee static void
2933*251Slclee ffile_write(char *file)
29340Sstevel@tonic-gate {
29350Sstevel@tonic-gate 	register int	i;
29360Sstevel@tonic-gate 	FILE *fp;
29370Sstevel@tonic-gate 
29380Sstevel@tonic-gate 	/*
29390Sstevel@tonic-gate 	 * If file isn't standard output, then it's a file name.
29400Sstevel@tonic-gate 	 * Open file and write it.
29410Sstevel@tonic-gate 	 */
29420Sstevel@tonic-gate 	if (file != (char *)stdout) {
29430Sstevel@tonic-gate 	    if ((fp = fopen(file, "w")) == NULL) {
29440Sstevel@tonic-gate 		(void) fprintf(stderr, "fdisk: Cannot open output file %s.\n",
29450Sstevel@tonic-gate 		    file);
29460Sstevel@tonic-gate 		exit(1);
29470Sstevel@tonic-gate 	    }
29480Sstevel@tonic-gate 	}
29490Sstevel@tonic-gate 	else
29500Sstevel@tonic-gate 	    fp = stdout;
29510Sstevel@tonic-gate 
29520Sstevel@tonic-gate 	/*
29530Sstevel@tonic-gate 	 * Write the fdisk table information
29540Sstevel@tonic-gate 	 */
2955*251Slclee 	(void) fprintf(fp, "\n* %s default fdisk table\n", Dfltdev);
2956*251Slclee 	(void) fprintf(fp, "* Dimensions:\n");
2957*251Slclee 	(void) fprintf(fp, "*   %4d bytes/sector\n", sectsiz);
2958*251Slclee 	(void) fprintf(fp, "*   %4d sectors/track\n", sectors);
2959*251Slclee 	(void) fprintf(fp, "*   %4d tracks/cylinder\n", heads);
2960*251Slclee 	(void) fprintf(fp, "*   %4d cylinders\n", Numcyl);
2961*251Slclee 	(void) fprintf(fp, "*\n");
29620Sstevel@tonic-gate 	/* Write virtual (HBA) geometry, if required	*/
29630Sstevel@tonic-gate 	if (v_flag) {
2964*251Slclee 		(void) fprintf(fp, "* HBA Dimensions:\n");
2965*251Slclee 		(void) fprintf(fp, "*   %4d bytes/sector\n", sectsiz);
2966*251Slclee 		(void) fprintf(fp, "*   %4d sectors/track\n", hba_sectors);
2967*251Slclee 		(void) fprintf(fp, "*   %4d tracks/cylinder\n", hba_heads);
2968*251Slclee 		(void) fprintf(fp, "*   %4d cylinders\n", hba_Numcyl);
2969*251Slclee 		(void) fprintf(fp, "*\n");
29700Sstevel@tonic-gate 	}
2971*251Slclee 	(void) fprintf(fp, "* systid:\n");
2972*251Slclee 	(void) fprintf(fp, "*    1: DOSOS12\n");
2973*251Slclee 	(void) fprintf(fp, "*    2: PCIXOS\n");
2974*251Slclee 	(void) fprintf(fp, "*    4: DOSOS16\n");
2975*251Slclee 	(void) fprintf(fp, "*    5: EXTDOS\n");
2976*251Slclee 	(void) fprintf(fp, "*    6: DOSBIG\n");
2977*251Slclee 	(void) fprintf(fp, "*    7: FDISK_IFS\n");
2978*251Slclee 	(void) fprintf(fp, "*    8: FDISK_AIXBOOT\n");
2979*251Slclee 	(void) fprintf(fp, "*    9: FDISK_AIXDATA\n");
2980*251Slclee 	(void) fprintf(fp, "*   10: FDISK_0S2BOOT\n");
2981*251Slclee 	(void) fprintf(fp, "*   11: FDISK_WINDOWS\n");
2982*251Slclee 	(void) fprintf(fp, "*   12: FDISK_EXT_WIN\n");
2983*251Slclee 	(void) fprintf(fp, "*   14: FDISK_FAT95\n");
2984*251Slclee 	(void) fprintf(fp, "*   15: FDISK_EXTLBA\n");
2985*251Slclee 	(void) fprintf(fp, "*   18: DIAGPART\n");
2986*251Slclee 	(void) fprintf(fp, "*   65: FDISK_LINUX\n");
2987*251Slclee 	(void) fprintf(fp, "*   82: FDISK_CPM\n");
2988*251Slclee 	(void) fprintf(fp, "*   86: DOSDATA\n");
2989*251Slclee 	(void) fprintf(fp, "*   98: OTHEROS\n");
2990*251Slclee 	(void) fprintf(fp, "*   99: UNIXOS\n");
2991*251Slclee 	(void) fprintf(fp, "*  101: FDISK_NOVELL3\n");
2992*251Slclee 	(void) fprintf(fp, "*  119: FDISK_QNX4\n");
2993*251Slclee 	(void) fprintf(fp, "*  120: FDISK_QNX42\n");
2994*251Slclee 	(void) fprintf(fp, "*  121: FDISK_QNX43\n");
2995*251Slclee 	(void) fprintf(fp, "*  130: SUNIXOS\n");
2996*251Slclee 	(void) fprintf(fp, "*  131: FDISK_LINUXNAT\n");
2997*251Slclee 	(void) fprintf(fp, "*  134: FDISK_NTFSVOL1\n");
2998*251Slclee 	(void) fprintf(fp, "*  135: FDISK_NTFSVOL2\n");
2999*251Slclee 	(void) fprintf(fp, "*  165: FDISK_BSD\n");
3000*251Slclee 	(void) fprintf(fp, "*  167: FDISK_NEXTSTEP\n");
3001*251Slclee 	(void) fprintf(fp, "*  183: FDISK_BSDIFS\n");
3002*251Slclee 	(void) fprintf(fp, "*  184: FDISK_BSDISWAP\n");
3003*251Slclee 	(void) fprintf(fp, "*  190: X86BOOT\n");
3004*251Slclee 	(void) fprintf(fp, "*  191: SUNIXOS2\n");
3005*251Slclee 	(void) fprintf(fp, "*  238: EFI_PMBR\n");
3006*251Slclee 	(void) fprintf(fp, "*  239: EFI_FS\n");
3007*251Slclee 	(void) fprintf(fp, "*\n");
3008*251Slclee 	(void) fprintf(fp,
30090Sstevel@tonic-gate 	    "\n* Id    Act  Bhead  Bsect  Bcyl    Ehead  Esect  Ecyl"
30100Sstevel@tonic-gate 	    "    Rsect    Numsect\n");
30110Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
30120Sstevel@tonic-gate 		if (Table[i].systid != UNUSED)
3013*251Slclee 			(void) fprintf(fp,
30140Sstevel@tonic-gate 			    "  %-5d %-4d %-6d %-6d %-7d %-6d %-6d %-7d %-8d"
30150Sstevel@tonic-gate 			    " %-8d\n",
30160Sstevel@tonic-gate 			    Table[i].systid,
30170Sstevel@tonic-gate 			    Table[i].bootid,
30180Sstevel@tonic-gate 			    Table[i].beghead,
30190Sstevel@tonic-gate 			    Table[i].begsect & 0x3f,
30200Sstevel@tonic-gate 			    ((Table[i].begcyl & 0xff) | ((Table[i].begsect &
30210Sstevel@tonic-gate 				0xc0) << 2)),
30220Sstevel@tonic-gate 			    Table[i].endhead,
30230Sstevel@tonic-gate 			    Table[i].endsect & 0x3f,
30240Sstevel@tonic-gate 			    ((Table[i].endcyl & 0xff) | ((Table[i].endsect &
30250Sstevel@tonic-gate 				0xc0) << 2)),
30260Sstevel@tonic-gate 			    lel(Table[i].relsect),
30270Sstevel@tonic-gate 			    lel(Table[i].numsect));
30280Sstevel@tonic-gate 	}
30290Sstevel@tonic-gate 	if (fp != stdout)
3030*251Slclee 		(void) fclose(fp);
30310Sstevel@tonic-gate }
30320Sstevel@tonic-gate 
30330Sstevel@tonic-gate /*
30340Sstevel@tonic-gate  * fix_slice
30350Sstevel@tonic-gate  * 	Read the VTOC table on the Solaris partition and check that no
30360Sstevel@tonic-gate  *	slices exist that extend past the end of the Solaris partition.
30370Sstevel@tonic-gate  *	If no Solaris partition exists, nothing is done.
30380Sstevel@tonic-gate  */
3039*251Slclee static void
3040*251Slclee fix_slice(void)
30410Sstevel@tonic-gate {
30420Sstevel@tonic-gate 	int	i;
30430Sstevel@tonic-gate 	int	numsect;
30440Sstevel@tonic-gate 
30450Sstevel@tonic-gate 	if (io_image) {
3046*251Slclee 		return;
30470Sstevel@tonic-gate 	}
30480Sstevel@tonic-gate 
30490Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
30500Sstevel@tonic-gate 		if (Table[i].systid == SUNIXOS || Table[i].systid == SUNIXOS2) {
30510Sstevel@tonic-gate 			/*
30520Sstevel@tonic-gate 			 * Only the size matters (not starting point), since
30530Sstevel@tonic-gate 			 * VTOC entries are relative to the start of
30540Sstevel@tonic-gate 			 * the partition.
30550Sstevel@tonic-gate 			 */
30560Sstevel@tonic-gate 			numsect = lel(Table[i].numsect);
30570Sstevel@tonic-gate 			break;
30580Sstevel@tonic-gate 		}
30590Sstevel@tonic-gate 	}
30600Sstevel@tonic-gate 
30610Sstevel@tonic-gate 	if (i >= FD_NUMPART) {
30620Sstevel@tonic-gate 		if (!io_nifdisk) {
30630Sstevel@tonic-gate 			(void) fprintf(stderr,
30640Sstevel@tonic-gate 			    "fdisk: No Solaris partition found - VTOC not"
30650Sstevel@tonic-gate 			    " checked.\n");
30660Sstevel@tonic-gate 		}
3067*251Slclee 		return;
30680Sstevel@tonic-gate 	}
30690Sstevel@tonic-gate 
3070*251Slclee 	if (readvtoc() != VTOC_OK) {
30710Sstevel@tonic-gate 		exit(1);		/* Failed to read the VTOC */
30720Sstevel@tonic-gate 	} else {
30730Sstevel@tonic-gate 		for (i = 0; i < V_NUMPAR; i++) {
30740Sstevel@tonic-gate 			/* Special case for slice two (entire disk) */
30750Sstevel@tonic-gate 			if (i == 2) {
30760Sstevel@tonic-gate 				if (disk_vtoc.v_part[i].p_start != 0) {
30770Sstevel@tonic-gate 					(void) fprintf(stderr,
3078*251Slclee 					    "slice %d starts at %ld, is not at"
30790Sstevel@tonic-gate 					    " start of partition",
30800Sstevel@tonic-gate 						i, disk_vtoc.v_part[i].p_start);
30810Sstevel@tonic-gate 					if (!io_nifdisk) {
3082*251Slclee 					    (void) printf(" adjust ?:");
30830Sstevel@tonic-gate 					    if (yesno())
30840Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_start = 0;
30850Sstevel@tonic-gate 					} else {
30860Sstevel@tonic-gate 					    disk_vtoc.v_part[i].p_start = 0;
30870Sstevel@tonic-gate 					    (void) fprintf(stderr,
30880Sstevel@tonic-gate 						" adjusted!\n");
30890Sstevel@tonic-gate 					}
30900Sstevel@tonic-gate 
30910Sstevel@tonic-gate 				}
30920Sstevel@tonic-gate 				if (disk_vtoc.v_part[i].p_size != numsect) {
30930Sstevel@tonic-gate 					(void) fprintf(stderr,
3094*251Slclee 					    "slice %d size %ld does not cover"
30950Sstevel@tonic-gate 					    " complete partition",
30960Sstevel@tonic-gate 						i, disk_vtoc.v_part[i].p_size);
30970Sstevel@tonic-gate 					if (!io_nifdisk) {
3098*251Slclee 					    (void) printf(" adjust ?:");
30990Sstevel@tonic-gate 					    if (yesno())
31000Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_size =
31010Sstevel@tonic-gate 						    numsect;
31020Sstevel@tonic-gate 					} else {
31030Sstevel@tonic-gate 					    disk_vtoc.v_part[i].p_size =
31040Sstevel@tonic-gate 						numsect;
31050Sstevel@tonic-gate 					    (void) fprintf(stderr,
31060Sstevel@tonic-gate 						" adjusted!\n");
31070Sstevel@tonic-gate 					}
31080Sstevel@tonic-gate 				}
31090Sstevel@tonic-gate 				if (disk_vtoc.v_part[i].p_tag != V_BACKUP) {
31100Sstevel@tonic-gate 				    (void) fprintf(stderr,
31110Sstevel@tonic-gate 					"slice %d tag was %d should be %d",
31120Sstevel@tonic-gate 					i, disk_vtoc.v_part[i].p_tag,
31130Sstevel@tonic-gate 					V_BACKUP);
31140Sstevel@tonic-gate 				    if (!io_nifdisk) {
3115*251Slclee 					(void) printf(" fix ?:");
31160Sstevel@tonic-gate 					    if (yesno())
31170Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_tag =
31180Sstevel@tonic-gate 						    V_BACKUP;
31190Sstevel@tonic-gate 				    } else {
31200Sstevel@tonic-gate 					disk_vtoc.v_part[i].p_tag = V_BACKUP;
31210Sstevel@tonic-gate 					(void) fprintf(stderr, " fixed!\n");
31220Sstevel@tonic-gate 					}
31230Sstevel@tonic-gate 				}
31240Sstevel@tonic-gate 			} else {
31250Sstevel@tonic-gate 				if (io_ADJT) {
31260Sstevel@tonic-gate 				    if (disk_vtoc.v_part[i].p_start > numsect ||
31270Sstevel@tonic-gate 					disk_vtoc.v_part[i].p_start +
31280Sstevel@tonic-gate 					disk_vtoc.v_part[i].p_size > numsect) {
31290Sstevel@tonic-gate 					    (void) fprintf(stderr,
3130*251Slclee 						"slice %d (start %ld, end %ld)"
3131*251Slclee 						" is larger than the partition",
31320Sstevel@tonic-gate 						i, disk_vtoc.v_part[i].p_start,
31330Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_start +
31340Sstevel@tonic-gate 						    disk_vtoc.v_part[i].p_size);
31350Sstevel@tonic-gate 					    if (!io_nifdisk) {
3136*251Slclee 						(void) printf(" remove ?:");
31370Sstevel@tonic-gate 						if (yesno()) {
31380Sstevel@tonic-gate 						    disk_vtoc.v_part[i].p_size =
31390Sstevel@tonic-gate 							0;
31400Sstevel@tonic-gate 						    disk_vtoc.v_part[i].p_start
31410Sstevel@tonic-gate 							= 0;
31420Sstevel@tonic-gate 						    disk_vtoc.v_part[i].p_tag =
31430Sstevel@tonic-gate 							0;
31440Sstevel@tonic-gate 						    disk_vtoc.v_part[i].p_flag =
31450Sstevel@tonic-gate 							0;
31460Sstevel@tonic-gate 						}
31470Sstevel@tonic-gate 					    } else {
31480Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_size = 0;
31490Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_start = 0;
31500Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_tag = 0;
31510Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_flag = 0;
31520Sstevel@tonic-gate 						(void) fprintf(stderr,
31530Sstevel@tonic-gate 						    " removed!\n");
31540Sstevel@tonic-gate 						}
31550Sstevel@tonic-gate 					}
31560Sstevel@tonic-gate 				} else {
31570Sstevel@tonic-gate 				    if (disk_vtoc.v_part[i].p_start >
31580Sstevel@tonic-gate 					numsect) {
31590Sstevel@tonic-gate 					(void) fprintf(stderr,
3160*251Slclee 					    "slice %d (start %ld) is larger"
31610Sstevel@tonic-gate 					    " than the partition",
31620Sstevel@tonic-gate 						i, disk_vtoc.v_part[i].p_start);
31630Sstevel@tonic-gate 					if (!io_nifdisk) {
3164*251Slclee 					    (void) printf(" remove ?:");
31650Sstevel@tonic-gate 					    if (yesno()) {
31660Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_size = 0;
31670Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_start =
31680Sstevel@tonic-gate 						    0;
31690Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_tag = 0;
31700Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_flag = 0;
31710Sstevel@tonic-gate 					    }
31720Sstevel@tonic-gate 					} else {
31730Sstevel@tonic-gate 					    disk_vtoc.v_part[i].p_size = 0;
31740Sstevel@tonic-gate 					    disk_vtoc.v_part[i].p_start = 0;
31750Sstevel@tonic-gate 					    disk_vtoc.v_part[i].p_tag = 0;
31760Sstevel@tonic-gate 					    disk_vtoc.v_part[i].p_flag = 0;
31770Sstevel@tonic-gate 					    (void) fprintf(stderr,
31780Sstevel@tonic-gate 						" removed!\n");
31790Sstevel@tonic-gate 					    }
31800Sstevel@tonic-gate 					} else if (disk_vtoc.v_part[i].p_start
31810Sstevel@tonic-gate 					    + disk_vtoc.v_part[i].p_size >
31820Sstevel@tonic-gate 					    numsect) {
31830Sstevel@tonic-gate 					    (void) fprintf(stderr,
3184*251Slclee 						"slice %d (end %ld) is larger"
31850Sstevel@tonic-gate 						" than the partition",
31860Sstevel@tonic-gate 						i,
31870Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_start +
31880Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_size);
31890Sstevel@tonic-gate 					    if (!io_nifdisk) {
3190*251Slclee 						(void) printf(" adjust ?:");
31910Sstevel@tonic-gate 						if (yesno()) {
31920Sstevel@tonic-gate 						    disk_vtoc.v_part[i].p_size
31930Sstevel@tonic-gate 							= numsect;
31940Sstevel@tonic-gate 						}
31950Sstevel@tonic-gate 					    } else {
31960Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_size =
31970Sstevel@tonic-gate 						    numsect;
31980Sstevel@tonic-gate 						(void) fprintf(stderr,
31990Sstevel@tonic-gate 						    " adjusted!\n");
32000Sstevel@tonic-gate 						}
32010Sstevel@tonic-gate 					}
32020Sstevel@tonic-gate 				}
32030Sstevel@tonic-gate 			}
32040Sstevel@tonic-gate 		}
32050Sstevel@tonic-gate 	}
32060Sstevel@tonic-gate #if 1		/* bh for now */
32070Sstevel@tonic-gate 	/* Make the VTOC look sane - ha ha */
32080Sstevel@tonic-gate 	disk_vtoc.v_version = V_VERSION;
32090Sstevel@tonic-gate 	disk_vtoc.v_sanity = VTOC_SANE;
32100Sstevel@tonic-gate 	disk_vtoc.v_nparts = V_NUMPAR;
32110Sstevel@tonic-gate 	if (disk_vtoc.v_sectorsz == 0)
32120Sstevel@tonic-gate 		disk_vtoc.v_sectorsz = NBPSCTR;
32130Sstevel@tonic-gate #endif
32140Sstevel@tonic-gate 
32150Sstevel@tonic-gate 	/* Write the VTOC back to the disk */
32160Sstevel@tonic-gate 	if (!io_readonly)
3217*251Slclee 		(void) writevtoc();
32180Sstevel@tonic-gate }
32190Sstevel@tonic-gate 
32200Sstevel@tonic-gate /*
32210Sstevel@tonic-gate  * yesno
32220Sstevel@tonic-gate  * Get yes or no answer. Return 1 for yes and 0 for no.
32230Sstevel@tonic-gate  */
32240Sstevel@tonic-gate 
3225*251Slclee static int
3226*251Slclee yesno(void)
32270Sstevel@tonic-gate {
32280Sstevel@tonic-gate 	char	s[80];
32290Sstevel@tonic-gate 
32300Sstevel@tonic-gate 	for (;;) {
3231*251Slclee 		(void) gets(s);
32320Sstevel@tonic-gate 		rm_blanks(s);
32330Sstevel@tonic-gate 		if ((s[1] != 0) || ((s[0] != 'y') && (s[0] != 'n'))) {
3234*251Slclee 			(void) printf(E_LINE);
3235*251Slclee 			(void) printf("Please answer with \"y\" or \"n\": ");
32360Sstevel@tonic-gate 			continue;
32370Sstevel@tonic-gate 		}
32380Sstevel@tonic-gate 		if (s[0] == 'y')
32390Sstevel@tonic-gate 			return (1);
32400Sstevel@tonic-gate 		else
32410Sstevel@tonic-gate 			return (0);
32420Sstevel@tonic-gate 	}
32430Sstevel@tonic-gate }
32440Sstevel@tonic-gate 
32450Sstevel@tonic-gate /*
32460Sstevel@tonic-gate  * readvtoc
32470Sstevel@tonic-gate  * 	Read the VTOC from the Solaris partition of the device.
32480Sstevel@tonic-gate  */
3249*251Slclee static int
3250*251Slclee readvtoc(void)
32510Sstevel@tonic-gate {
32520Sstevel@tonic-gate 	int	i;
32530Sstevel@tonic-gate 	int	retval = VTOC_OK;
32540Sstevel@tonic-gate 
32550Sstevel@tonic-gate 	if ((i = read_vtoc(Dev, &disk_vtoc)) < VTOC_OK) {
32560Sstevel@tonic-gate 		if (i == VT_EINVAL) {
32570Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: Invalid VTOC.\n");
32580Sstevel@tonic-gate 			vt_inval++;
32590Sstevel@tonic-gate 			retval = VTOC_INVAL;
32600Sstevel@tonic-gate 		} else if (i == VT_ENOTSUP) {
32610Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: partition may have EFI "
32620Sstevel@tonic-gate 				"GPT\n");
32630Sstevel@tonic-gate 			retval = VTOC_NOTSUP;
32640Sstevel@tonic-gate 		} else {
32650Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: Cannot read VTOC.\n");
32660Sstevel@tonic-gate 			retval = VTOC_RWERR;
32670Sstevel@tonic-gate 		}
32680Sstevel@tonic-gate 	}
32690Sstevel@tonic-gate 	return (retval);
32700Sstevel@tonic-gate }
32710Sstevel@tonic-gate 
32720Sstevel@tonic-gate /*
32730Sstevel@tonic-gate  * writevtoc
32740Sstevel@tonic-gate  * 	Write the VTOC to the Solaris partition on the device.
32750Sstevel@tonic-gate  */
3276*251Slclee static int
3277*251Slclee writevtoc(void)
32780Sstevel@tonic-gate {
32790Sstevel@tonic-gate 	int	i;
32800Sstevel@tonic-gate 	int	retval = 0;
32810Sstevel@tonic-gate 
32820Sstevel@tonic-gate 	if ((i = write_vtoc(Dev, &disk_vtoc)) != 0) {
32830Sstevel@tonic-gate 		if (i == VT_EINVAL) {
32840Sstevel@tonic-gate 			(void) fprintf(stderr,
32850Sstevel@tonic-gate 			    "fdisk: Invalid entry exists in VTOC.\n");
32860Sstevel@tonic-gate 			retval = VTOC_INVAL;
32870Sstevel@tonic-gate 		} else if (i == VT_ENOTSUP) {
32880Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: partition may have EFI "
32890Sstevel@tonic-gate 				"GPT\n");
32900Sstevel@tonic-gate 			retval = VTOC_NOTSUP;
32910Sstevel@tonic-gate 		} else {
32920Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: Cannot write VTOC.\n");
32930Sstevel@tonic-gate 			retval = VTOC_RWERR;
32940Sstevel@tonic-gate 		}
32950Sstevel@tonic-gate 	}
32960Sstevel@tonic-gate 	return (retval);
32970Sstevel@tonic-gate }
32980Sstevel@tonic-gate 
32990Sstevel@tonic-gate /*
33000Sstevel@tonic-gate  * efi_ioctl
33010Sstevel@tonic-gate  * issues DKIOCSETEFI IOCTL
33020Sstevel@tonic-gate  * (duplicate of private efi_ioctl() in rdwr_efi.c
33030Sstevel@tonic-gate  */
33040Sstevel@tonic-gate static int
33050Sstevel@tonic-gate efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc)
33060Sstevel@tonic-gate {
33070Sstevel@tonic-gate 	void *data = dk_ioc->dki_data;
33080Sstevel@tonic-gate 	int error;
33090Sstevel@tonic-gate 
33100Sstevel@tonic-gate 	dk_ioc->dki_data_64 = (uintptr_t)data;
33110Sstevel@tonic-gate 	error = ioctl(fd, cmd, (void *)dk_ioc);
33120Sstevel@tonic-gate 
33130Sstevel@tonic-gate 	return (error);
33140Sstevel@tonic-gate }
33150Sstevel@tonic-gate 
33160Sstevel@tonic-gate /*
33170Sstevel@tonic-gate  * clear_efi
33180Sstevel@tonic-gate  * Clear EFI labels from the EFI_PMBR partition on the device
33190Sstevel@tonic-gate  * This function is modeled on the libefi(3LIB) call efi_write()
33200Sstevel@tonic-gate  */
3321*251Slclee static int
3322*251Slclee clear_efi(void)
33230Sstevel@tonic-gate {
33240Sstevel@tonic-gate 	struct dk_gpt	*efi_vtoc;
33250Sstevel@tonic-gate 	dk_efi_t	dk_ioc;
33260Sstevel@tonic-gate 
33270Sstevel@tonic-gate 	/*
33280Sstevel@tonic-gate 	 * see if we can read the EFI label
33290Sstevel@tonic-gate 	 */
33300Sstevel@tonic-gate 	if (efi_alloc_and_read(Dev, &efi_vtoc) < 0) {
33310Sstevel@tonic-gate 		return (VT_ERROR);
33320Sstevel@tonic-gate 	}
33330Sstevel@tonic-gate 
33340Sstevel@tonic-gate 	/*
33350Sstevel@tonic-gate 	 * set up the dk_ioc structure for writing
33360Sstevel@tonic-gate 	 */
33370Sstevel@tonic-gate 	dk_ioc.dki_lba = 1;
33380Sstevel@tonic-gate 	dk_ioc.dki_length = EFI_MIN_ARRAY_SIZE + efi_vtoc->efi_lbasize;
33390Sstevel@tonic-gate 
33400Sstevel@tonic-gate 	if ((dk_ioc.dki_data = calloc(dk_ioc.dki_length, 1)) == NULL) {
33410Sstevel@tonic-gate 		return (VT_ERROR);
33420Sstevel@tonic-gate 	}
33430Sstevel@tonic-gate 
33440Sstevel@tonic-gate 	/*
33450Sstevel@tonic-gate 	 * clear the primary label
33460Sstevel@tonic-gate 	 */
33470Sstevel@tonic-gate 	if (io_debug) {
3348*251Slclee 		(void) fprintf(stderr,
3349*251Slclee 		    "\tClearing primary EFI label at block %lld\n",
3350*251Slclee 		    dk_ioc.dki_lba);
33510Sstevel@tonic-gate 	}
33520Sstevel@tonic-gate 
33530Sstevel@tonic-gate 	if (efi_ioctl(Dev, DKIOCSETEFI, &dk_ioc) == -1) {
33540Sstevel@tonic-gate 		free(dk_ioc.dki_data);
33550Sstevel@tonic-gate 		switch (errno) {
33560Sstevel@tonic-gate 			case EIO:
33570Sstevel@tonic-gate 				return (VT_EIO);
33580Sstevel@tonic-gate 			case EINVAL:
33590Sstevel@tonic-gate 				return (VT_EINVAL);
33600Sstevel@tonic-gate 			default:
33610Sstevel@tonic-gate 				return (VT_ERROR);
33620Sstevel@tonic-gate 		}
33630Sstevel@tonic-gate 	}
33640Sstevel@tonic-gate 
33650Sstevel@tonic-gate 	/*
33660Sstevel@tonic-gate 	 * clear the backup partition table
33670Sstevel@tonic-gate 	 */
33680Sstevel@tonic-gate 	dk_ioc.dki_lba = efi_vtoc->efi_last_u_lba + 1;
33690Sstevel@tonic-gate 	dk_ioc.dki_length -= efi_vtoc->efi_lbasize;
33700Sstevel@tonic-gate 	dk_ioc.dki_data++;
33710Sstevel@tonic-gate 	if (io_debug) {
3372*251Slclee 		(void) fprintf(stderr,
3373*251Slclee 		    "\tClearing backup partition table at block %lld\n",
3374*251Slclee 		    dk_ioc.dki_lba);
33750Sstevel@tonic-gate 	}
33760Sstevel@tonic-gate 
33770Sstevel@tonic-gate 	if (efi_ioctl(Dev, DKIOCSETEFI, &dk_ioc) == -1) {
33780Sstevel@tonic-gate 		(void) fprintf(stderr, "\tUnable to clear backup EFI label at "
33790Sstevel@tonic-gate 			"block %llu; errno %d\n", efi_vtoc->efi_last_u_lba + 1,
33800Sstevel@tonic-gate 			errno);
33810Sstevel@tonic-gate 	}
33820Sstevel@tonic-gate 
33830Sstevel@tonic-gate 	/*
33840Sstevel@tonic-gate 	 * clear the backup label
33850Sstevel@tonic-gate 	 */
33860Sstevel@tonic-gate 	dk_ioc.dki_lba = efi_vtoc->efi_last_lba;
33870Sstevel@tonic-gate 	dk_ioc.dki_length = efi_vtoc->efi_lbasize;
33880Sstevel@tonic-gate 	dk_ioc.dki_data--;
33890Sstevel@tonic-gate 	if (io_debug) {
3390*251Slclee 		(void) fprintf(stderr, "\tClearing backup label at block "
3391*251Slclee 		    "%lld\n", dk_ioc.dki_lba);
33920Sstevel@tonic-gate 	}
33930Sstevel@tonic-gate 
33940Sstevel@tonic-gate 	if (efi_ioctl(Dev, DKIOCSETEFI, &dk_ioc) == -1) {
3395*251Slclee 		(void) fprintf(stderr,
3396*251Slclee 		    "\tUnable to clear backup EFI label at "
3397*251Slclee 		    "block %llu; errno %d\n",
3398*251Slclee 		    efi_vtoc->efi_last_lba,
3399*251Slclee 		    errno);
34000Sstevel@tonic-gate 	}
34010Sstevel@tonic-gate 
34020Sstevel@tonic-gate 	free(dk_ioc.dki_data);
34030Sstevel@tonic-gate 	efi_free(efi_vtoc);
34040Sstevel@tonic-gate 
34050Sstevel@tonic-gate 	return (0);
34060Sstevel@tonic-gate }
34070Sstevel@tonic-gate 
34080Sstevel@tonic-gate /*
34090Sstevel@tonic-gate  * clear_vtoc
34100Sstevel@tonic-gate  * 	Clear the VTOC from the current or previous Solaris partition on the
34110Sstevel@tonic-gate  *      device.
34120Sstevel@tonic-gate  */
3413*251Slclee static void
34140Sstevel@tonic-gate clear_vtoc(int table, int part)
34150Sstevel@tonic-gate {
34160Sstevel@tonic-gate 	struct ipart *clr_table;
34170Sstevel@tonic-gate 	struct dk_label disk_label;
34180Sstevel@tonic-gate 	int pcyl, ncyl, backup_block, solaris_offset, count, bytes, seek_byte;
34190Sstevel@tonic-gate 
34200Sstevel@tonic-gate #ifdef DEBUG
34210Sstevel@tonic-gate 	struct dk_label	read_label;
34220Sstevel@tonic-gate #endif /* DEBUG */
34230Sstevel@tonic-gate 
34240Sstevel@tonic-gate 	if (table == OLD) {
34250Sstevel@tonic-gate 		clr_table = &Old_Table[part];
34260Sstevel@tonic-gate 	} else {
34270Sstevel@tonic-gate 		clr_table = &Table[part];
34280Sstevel@tonic-gate 	}
34290Sstevel@tonic-gate 
3430*251Slclee 	(void) memset(&disk_label, 0, sizeof (struct dk_label));
34310Sstevel@tonic-gate 
34320Sstevel@tonic-gate 	seek_byte = (lel(clr_table->relsect) * sectsiz) + VTOC_OFFSET;
34330Sstevel@tonic-gate 
34340Sstevel@tonic-gate 	if (io_debug) {
3435*251Slclee 		(void) fprintf(stderr, "\tClearing primary VTOC at byte %d\n",
34360Sstevel@tonic-gate 		    seek_byte);
34370Sstevel@tonic-gate 	}
34380Sstevel@tonic-gate 
34390Sstevel@tonic-gate 	if (lseek(Dev, seek_byte, SEEK_SET) == -1) {
3440*251Slclee 		(void) fprintf(stderr,
3441*251Slclee 		    "\tError seeking to primary label at byte %d\n",
34420Sstevel@tonic-gate 		    seek_byte);
3443*251Slclee 		return;
34440Sstevel@tonic-gate 	}
34450Sstevel@tonic-gate 
34460Sstevel@tonic-gate 	bytes = write(Dev, &disk_label, sizeof (struct dk_label));
34470Sstevel@tonic-gate 
34480Sstevel@tonic-gate 	if (bytes != sizeof (struct dk_label)) {
3449*251Slclee 		(void) fprintf(stderr,
3450*251Slclee 		    "\tWarning: only %d bytes written to clear primary VTOC!\n",
3451*251Slclee 		    bytes);
34520Sstevel@tonic-gate 	}
34530Sstevel@tonic-gate 
34540Sstevel@tonic-gate #ifdef DEBUG
34550Sstevel@tonic-gate 	if (lseek(Dev, seek_byte, SEEK_SET) == -1) {
3456*251Slclee 		(void) fprintf(stderr,
3457*251Slclee 		    "DEBUG: Error seeking to primary label at byte %d\n",
3458*251Slclee 		    seek_byte);
3459*251Slclee 		return;
34600Sstevel@tonic-gate 	} else {
3461*251Slclee 		(void) fprintf(stderr, "DEBUG: Successful lseek() to byte %d\n",
34620Sstevel@tonic-gate 		    seek_byte);
34630Sstevel@tonic-gate 	}
34640Sstevel@tonic-gate 
34650Sstevel@tonic-gate 	bytes = read(Dev, &read_label, sizeof (struct dk_label));
34660Sstevel@tonic-gate 
34670Sstevel@tonic-gate 	if (bytes != sizeof (struct dk_label)) {
3468*251Slclee 		(void) fprintf(stderr,
3469*251Slclee 		    "DEBUG: Warning: only %d bytes read of label\n",
34700Sstevel@tonic-gate 		    bytes);
34710Sstevel@tonic-gate 	}
34720Sstevel@tonic-gate 
34730Sstevel@tonic-gate 	if (memcmp(&disk_label, &read_label, sizeof (struct dk_label)) != 0) {
3474*251Slclee 		(void) fprintf(stderr,
3475*251Slclee 		    "DEBUG: Warning: disk_label and read_label differ!!!\n");
34760Sstevel@tonic-gate 	} else {
3477*251Slclee 		(void) fprintf(stderr, "DEBUG Good compare of disk_label and "
34780Sstevel@tonic-gate 		    "read_label\n");
34790Sstevel@tonic-gate 	}
34800Sstevel@tonic-gate #endif /* DEBUG */
34810Sstevel@tonic-gate 
34820Sstevel@tonic-gate 	/* Clear backup label */
34830Sstevel@tonic-gate 	pcyl = lel(clr_table->numsect) / (heads * sectors);
34840Sstevel@tonic-gate 	solaris_offset = lel(clr_table->relsect);
34850Sstevel@tonic-gate 	ncyl = pcyl - acyl;
34860Sstevel@tonic-gate 
34870Sstevel@tonic-gate 	backup_block = ((ncyl + acyl - 1) *
34880Sstevel@tonic-gate 	    (heads * sectors)) + ((heads - 1) * sectors) + 1;
34890Sstevel@tonic-gate 
34900Sstevel@tonic-gate 	for (count = 1; count < 6; count++) {
34910Sstevel@tonic-gate 		seek_byte = (solaris_offset + backup_block) * 512;
34920Sstevel@tonic-gate 
34930Sstevel@tonic-gate 		if (lseek(Dev, seek_byte, SEEK_SET) == -1) {
3494*251Slclee 			(void) fprintf(stderr,
34950Sstevel@tonic-gate 			    "\tError seeking to backup label at byte %d on "
34960Sstevel@tonic-gate 			    "%s.\n", seek_byte, Dfltdev);
3497*251Slclee 			return;
34980Sstevel@tonic-gate 		}
34990Sstevel@tonic-gate 
35000Sstevel@tonic-gate 		if (io_debug) {
3501*251Slclee 			(void) fprintf(stderr, "\tClearing backup VTOC at"
35020Sstevel@tonic-gate 			    " byte %d (block %d)\n",
35030Sstevel@tonic-gate 			    (solaris_offset + backup_block) * 512,
35040Sstevel@tonic-gate 			    (solaris_offset + backup_block));
35050Sstevel@tonic-gate 		}
35060Sstevel@tonic-gate 
35070Sstevel@tonic-gate 		bytes = write(Dev, &disk_label, sizeof (struct dk_label));
35080Sstevel@tonic-gate 
35090Sstevel@tonic-gate 		if (bytes != sizeof (struct dk_label)) {
3510*251Slclee 			(void) fprintf(stderr,
3511*251Slclee 			    "\t\tWarning: only %d bytes written to "
35120Sstevel@tonic-gate 			    "clear backup VTOC at block %d!\n", bytes,
35130Sstevel@tonic-gate 			    (solaris_offset + backup_block));
35140Sstevel@tonic-gate 		}
35150Sstevel@tonic-gate 
35160Sstevel@tonic-gate #ifdef DEBUG
35170Sstevel@tonic-gate 	if (lseek(Dev, seek_byte, SEEK_SET) == -1) {
3518*251Slclee 		(void) fprintf(stderr,
3519*251Slclee 		    "DEBUG: Error seeking to backup label at byte %d\n",
3520*251Slclee 		    seek_byte);
3521*251Slclee 		return;
35220Sstevel@tonic-gate 	} else {
3523*251Slclee 		(void) fprintf(stderr, "DEBUG: Successful lseek() to byte %d\n",
35240Sstevel@tonic-gate 		    seek_byte);
35250Sstevel@tonic-gate 	}
35260Sstevel@tonic-gate 
35270Sstevel@tonic-gate 	bytes = read(Dev, &read_label, sizeof (struct dk_label));
35280Sstevel@tonic-gate 
35290Sstevel@tonic-gate 	if (bytes != sizeof (struct dk_label)) {
3530*251Slclee 		(void) fprintf(stderr,
3531*251Slclee 		    "DEBUG: Warning: only %d bytes read of backup label\n",
3532*251Slclee 		    bytes);
35330Sstevel@tonic-gate 	}
35340Sstevel@tonic-gate 
35350Sstevel@tonic-gate 	if (memcmp(&disk_label, &read_label, sizeof (struct dk_label)) != 0) {
3536*251Slclee 		(void) fprintf(stderr,
3537*251Slclee 		    "DEBUG: Warning: disk_label and read_label differ!!!\n");
35380Sstevel@tonic-gate 	} else {
3539*251Slclee 		(void) fprintf(stderr,
3540*251Slclee 		    "DEBUG: Good compare of disk_label and backup "
35410Sstevel@tonic-gate 		    "read_label\n");
35420Sstevel@tonic-gate 	}
35430Sstevel@tonic-gate #endif /* DEBUG */
35440Sstevel@tonic-gate 
35450Sstevel@tonic-gate 		backup_block += 2;
35460Sstevel@tonic-gate 	}
35470Sstevel@tonic-gate }
35480Sstevel@tonic-gate 
35490Sstevel@tonic-gate #define	FDISK_STANDARD_LECTURE \
35500Sstevel@tonic-gate 	"Fdisk is normally used with the device that " \
35510Sstevel@tonic-gate 	"represents the entire fixed disk.\n" \
35520Sstevel@tonic-gate 	"(For example, /dev/rdsk/c0d0p0 on x86 or " \
35530Sstevel@tonic-gate 	"/dev/rdsk/c0t5d0s2 on sparc).\n"
35540Sstevel@tonic-gate 
35550Sstevel@tonic-gate #define	FDISK_LECTURE_NOT_SECTOR_ZERO \
35560Sstevel@tonic-gate 	"The device does not appear to include absolute\n" \
35570Sstevel@tonic-gate 	"sector 0 of the PHYSICAL disk " \
35580Sstevel@tonic-gate 	"(the normal location for an fdisk table).\n"
35590Sstevel@tonic-gate 
35600Sstevel@tonic-gate #define	FDISK_LECTURE_NOT_FULL \
35610Sstevel@tonic-gate 	"The device does not appear to encompass the entire PHYSICAL disk.\n"
35620Sstevel@tonic-gate 
35630Sstevel@tonic-gate #define	FDISK_LECTURE_NO_VTOC \
35640Sstevel@tonic-gate 	"Unable to find a volume table of contents.\n" \
35650Sstevel@tonic-gate 	"Cannot verify the device encompasses the full PHYSICAL disk.\n"
35660Sstevel@tonic-gate 
35670Sstevel@tonic-gate #define	FDISK_LECTURE_NO_GEOM \
35680Sstevel@tonic-gate 	"Unable to get geometry from device.\n" \
35690Sstevel@tonic-gate 	"Cannot verify the device encompasses the full PHYSICAL disk.\n"
35700Sstevel@tonic-gate 
35710Sstevel@tonic-gate #define	FDISK_SHALL_I_CONTINUE \
35720Sstevel@tonic-gate 	"Are you sure you want to continue? (y/n) "
35730Sstevel@tonic-gate 
35740Sstevel@tonic-gate /*
35750Sstevel@tonic-gate  *  lecture_and_query
35760Sstevel@tonic-gate  *	Called when a sanity check fails.  This routine gives a warning
35770Sstevel@tonic-gate  *	specific to the check that fails, followed by a generic lecture
35780Sstevel@tonic-gate  *	about the "right" device to supply as input.  Then, if appropriate,
35790Sstevel@tonic-gate  *	it will prompt the user on whether or not they want to continue.
35800Sstevel@tonic-gate  *	Inappropriate times for prompting are when the user has selected
35810Sstevel@tonic-gate  *	non-interactive mode or read-only mode.
35820Sstevel@tonic-gate  */
3583*251Slclee static int
35840Sstevel@tonic-gate lecture_and_query(char *warning, char *devname)
35850Sstevel@tonic-gate {
35860Sstevel@tonic-gate 	if (io_nifdisk)
35870Sstevel@tonic-gate 		return (0);
35880Sstevel@tonic-gate 
3589*251Slclee 	(void) fprintf(stderr, "WARNING: Device %s: \n", devname);
3590*251Slclee 	(void) fprintf(stderr, "%s", warning);
3591*251Slclee 	(void) fprintf(stderr, FDISK_STANDARD_LECTURE);
3592*251Slclee 	(void) fprintf(stderr, FDISK_SHALL_I_CONTINUE);
35930Sstevel@tonic-gate 
35940Sstevel@tonic-gate 	return (yesno());
35950Sstevel@tonic-gate }
35960Sstevel@tonic-gate 
3597*251Slclee static void
35980Sstevel@tonic-gate sanity_check_provided_device(char *devname, int fd)
35990Sstevel@tonic-gate {
36000Sstevel@tonic-gate 	struct vtoc v;
36010Sstevel@tonic-gate 	struct dk_geom d;
36020Sstevel@tonic-gate 	struct part_info pi;
36030Sstevel@tonic-gate 	long totsize;
36040Sstevel@tonic-gate 	int idx = -1;
36050Sstevel@tonic-gate 
36060Sstevel@tonic-gate 	/*
36070Sstevel@tonic-gate 	 *  First try the PARTINFO ioctl.  If it works, we will be able
36080Sstevel@tonic-gate 	 *  to tell if they've specified the full disk partition by checking
36090Sstevel@tonic-gate 	 *  to see if they've specified a partition that starts at sector 0.
36100Sstevel@tonic-gate 	 */
36110Sstevel@tonic-gate 	if (ioctl(fd, DKIOCPARTINFO, &pi) != -1) {
36120Sstevel@tonic-gate 		if (pi.p_start != 0) {
36130Sstevel@tonic-gate 			if (!lecture_and_query(FDISK_LECTURE_NOT_SECTOR_ZERO,
36140Sstevel@tonic-gate 			    devname)) {
36150Sstevel@tonic-gate 				(void) close(fd);
36160Sstevel@tonic-gate 				exit(1);
36170Sstevel@tonic-gate 			}
36180Sstevel@tonic-gate 		}
36190Sstevel@tonic-gate 	} else {
36200Sstevel@tonic-gate 		if ((idx = read_vtoc(fd, &v)) < 0) {
36210Sstevel@tonic-gate 			if (!lecture_and_query(FDISK_LECTURE_NO_VTOC,
36220Sstevel@tonic-gate 			    devname)) {
36230Sstevel@tonic-gate 				(void) close(fd);
36240Sstevel@tonic-gate 				exit(1);
36250Sstevel@tonic-gate 			}
36260Sstevel@tonic-gate 			return;
36270Sstevel@tonic-gate 		}
36280Sstevel@tonic-gate 		if (ioctl(fd, DKIOCGGEOM, &d) == -1) {
36290Sstevel@tonic-gate 			perror(devname);
36300Sstevel@tonic-gate 			if (!lecture_and_query(FDISK_LECTURE_NO_GEOM,
36310Sstevel@tonic-gate 			    devname)) {
36320Sstevel@tonic-gate 				(void) close(fd);
36330Sstevel@tonic-gate 				exit(1);
36340Sstevel@tonic-gate 			}
36350Sstevel@tonic-gate 			return;
36360Sstevel@tonic-gate 		}
36370Sstevel@tonic-gate 		totsize = d.dkg_ncyl * d.dkg_nhead * d.dkg_nsect;
36380Sstevel@tonic-gate 		if (v.v_part[idx].p_size != totsize) {
36390Sstevel@tonic-gate 			if (!lecture_and_query(FDISK_LECTURE_NOT_FULL,
36400Sstevel@tonic-gate 			    devname)) {
36410Sstevel@tonic-gate 				(void) close(fd);
36420Sstevel@tonic-gate 				exit(1);
36430Sstevel@tonic-gate 			}
36440Sstevel@tonic-gate 		}
36450Sstevel@tonic-gate 	}
36460Sstevel@tonic-gate }
36470Sstevel@tonic-gate 
36480Sstevel@tonic-gate 
36490Sstevel@tonic-gate /*
36500Sstevel@tonic-gate  * get_node
36510Sstevel@tonic-gate  * Called from main to construct the name of the device node to open.
36520Sstevel@tonic-gate  * Initially tries to stat the node exactly as provided, if that fails
36530Sstevel@tonic-gate  * we prepend the default path (/dev/rdsk/).
36540Sstevel@tonic-gate  */
36550Sstevel@tonic-gate static char *
36560Sstevel@tonic-gate get_node(char *devname)
36570Sstevel@tonic-gate {
36580Sstevel@tonic-gate 	char *node;
36590Sstevel@tonic-gate 	struct stat statbuf;
36600Sstevel@tonic-gate 	size_t space;
36610Sstevel@tonic-gate 
36620Sstevel@tonic-gate 	/* Don't do anything if we are skipping device checks */
36630Sstevel@tonic-gate 	if (io_image)
36640Sstevel@tonic-gate 		return (devname);
36650Sstevel@tonic-gate 
36660Sstevel@tonic-gate 	node = devname;
36670Sstevel@tonic-gate 
36680Sstevel@tonic-gate 	/* Try the node as provided first */
36690Sstevel@tonic-gate 	if (stat(node, (struct stat *)&statbuf) == -1) {
36700Sstevel@tonic-gate 		/*
36710Sstevel@tonic-gate 		 * Copy the passed in string to a new buffer, prepend the
36720Sstevel@tonic-gate 		 * default path and try again.
36730Sstevel@tonic-gate 		 */
36740Sstevel@tonic-gate 		space = strlen(DEFAULT_PATH) + strlen(devname) + 1;
36750Sstevel@tonic-gate 
36760Sstevel@tonic-gate 		if ((node = malloc(space)) == NULL) {
3677*251Slclee 			(void) fprintf(stderr, "fdisk: Unable to obtain memory "
36780Sstevel@tonic-gate 			    "for device node.\n");
36790Sstevel@tonic-gate 			exit(1);
36800Sstevel@tonic-gate 		}
36810Sstevel@tonic-gate 
36820Sstevel@tonic-gate 		/* Copy over the default path and the provided node */
36830Sstevel@tonic-gate 		(void) strncpy(node, DEFAULT_PATH, strlen(DEFAULT_PATH));
36840Sstevel@tonic-gate 		space -= strlen(DEFAULT_PATH);
36850Sstevel@tonic-gate 		(void) strlcpy(node + strlen(DEFAULT_PATH), devname, space);
36860Sstevel@tonic-gate 
36870Sstevel@tonic-gate 		/* Try to stat it again */
36880Sstevel@tonic-gate 		if (stat(node, (struct stat *)&statbuf) == -1) {
36890Sstevel@tonic-gate 			/* Failed all options, give up */
3690*251Slclee 			(void) fprintf(stderr,
3691*251Slclee 			    "fdisk: Cannot stat device %s.\n",
36920Sstevel@tonic-gate 			    devname);
36930Sstevel@tonic-gate 			exit(1);
36940Sstevel@tonic-gate 		}
36950Sstevel@tonic-gate 	}
36960Sstevel@tonic-gate 
36970Sstevel@tonic-gate 	/* Make sure the device specified is the raw device */
36980Sstevel@tonic-gate 	if ((statbuf.st_mode & S_IFMT) != S_IFCHR) {
3699*251Slclee 		(void) fprintf(stderr,
3700*251Slclee 		    "fdisk: %s must be a raw device.\n", node);
37010Sstevel@tonic-gate 		exit(1);
37020Sstevel@tonic-gate 	}
37030Sstevel@tonic-gate 
37040Sstevel@tonic-gate 	return (node);
37050Sstevel@tonic-gate }
3706