xref: /illumos-gate/usr/src/cmd/fdisk/fdisk.c (revision aa1b14e7)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51237e847Slclee  * Common Development and Distribution License (the "License").
61237e847Slclee  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
211237e847Slclee 
227c478bd9Sstevel@tonic-gate /*
232f8ec719SBarry Harding  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
287c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
297c478bd9Sstevel@tonic-gate /*	  All Rights Reserved	*/
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
327c478bd9Sstevel@tonic-gate /*	  All Rights Reserved	*/
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate  * PROGRAM: fdisk(1M)
367c478bd9Sstevel@tonic-gate  * This program reads the partition table on the specified device and
377c478bd9Sstevel@tonic-gate  * also reads the drive parameters. The user can perform various
387c478bd9Sstevel@tonic-gate  * operations from a supplied menu or from the command line. Diagnostic
397c478bd9Sstevel@tonic-gate  * options are also available.
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate #include <stdio.h>
427c478bd9Sstevel@tonic-gate #include <stdlib.h>
437c478bd9Sstevel@tonic-gate #include <string.h>
447c478bd9Sstevel@tonic-gate #include <unistd.h>
457c478bd9Sstevel@tonic-gate #include <errno.h>
467c478bd9Sstevel@tonic-gate #include <fcntl.h>
477c478bd9Sstevel@tonic-gate #include <ctype.h>
487c478bd9Sstevel@tonic-gate #include <sys/stat.h>
497c478bd9Sstevel@tonic-gate #include <sys/types.h>
50342440ecSPrasad Singamsetty #include <limits.h>
517c478bd9Sstevel@tonic-gate #include <sys/param.h>
527c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
537c478bd9Sstevel@tonic-gate #include <sys/efi_partition.h>
547c478bd9Sstevel@tonic-gate #include <sys/byteorder.h>
557c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
587c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
597c478bd9Sstevel@tonic-gate #include <sys/vtoc.h>
60*aa1b14e7SSheshadri Vasudevan #ifdef i386
61*aa1b14e7SSheshadri Vasudevan #include <sys/tty.h>
62*aa1b14e7SSheshadri Vasudevan #include <libfdisk.h>
63*aa1b14e7SSheshadri Vasudevan #endif
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #define	CLR_SCR ""
667c478bd9Sstevel@tonic-gate #define	CLR_LIN ""
677c478bd9Sstevel@tonic-gate #define	HOME "" \
687c478bd9Sstevel@tonic-gate 	""
697c478bd9Sstevel@tonic-gate #define	Q_LINE ""
70*aa1b14e7SSheshadri Vasudevan 
71*aa1b14e7SSheshadri Vasudevan #ifdef i386
72*aa1b14e7SSheshadri Vasudevan #define	W_LINE ""
73*aa1b14e7SSheshadri Vasudevan #else
747c478bd9Sstevel@tonic-gate #define	W_LINE ""
75*aa1b14e7SSheshadri Vasudevan #endif
76*aa1b14e7SSheshadri Vasudevan 
777c478bd9Sstevel@tonic-gate #define	E_LINE ""
78*aa1b14e7SSheshadri Vasudevan 
79*aa1b14e7SSheshadri Vasudevan #ifdef i386
80*aa1b14e7SSheshadri Vasudevan #define	M_LINE "" \
81*aa1b14e7SSheshadri Vasudevan 	""
82*aa1b14e7SSheshadri Vasudevan #else
837c478bd9Sstevel@tonic-gate #define	M_LINE "" \
847c478bd9Sstevel@tonic-gate 	""
85*aa1b14e7SSheshadri Vasudevan #endif
86*aa1b14e7SSheshadri Vasudevan 
877c478bd9Sstevel@tonic-gate #define	T_LINE ""
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate #define	DEFAULT_PATH	"/dev/rdsk/"
907c478bd9Sstevel@tonic-gate 
91f85c7842SSuhasini Peddada /* XXX - should be in fdisk.h, used by sd as well */
92f85c7842SSuhasini Peddada 
93f85c7842SSuhasini Peddada /*
94f85c7842SSuhasini Peddada  * the MAX values are the maximum usable values for BIOS chs values
95f85c7842SSuhasini Peddada  * The MAX_CYL value of 1022 is the maximum usable value
96f85c7842SSuhasini Peddada  *   the value of 1023 is a fence value,
97f85c7842SSuhasini Peddada  *   indicating no CHS geometry exists for the corresponding LBA value.
98f85c7842SSuhasini Peddada  * HEAD range [ 0 .. MAX_HEAD ], so number of heads is (MAX_HEAD + 1)
99f85c7842SSuhasini Peddada  * SECT range [ 1 .. MAX_SECT ], so number of sectors is (MAX_SECT)
100f85c7842SSuhasini Peddada  */
101f85c7842SSuhasini Peddada #define	MAX_SECT	(63)
102f85c7842SSuhasini Peddada #define	MAX_CYL		(1022)
103f85c7842SSuhasini Peddada #define	MAX_HEAD	(254)
104f85c7842SSuhasini Peddada 
105342440ecSPrasad Singamsetty #define	DK_MAX_2TB	UINT32_MAX	/* Max # of sectors in 2TB */
106342440ecSPrasad Singamsetty 
1077c478bd9Sstevel@tonic-gate /* for clear_vtoc() */
1087c478bd9Sstevel@tonic-gate #define	OLD		0
1097c478bd9Sstevel@tonic-gate #define	NEW		1
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate /* readvtoc/writevtoc return codes */
1127c478bd9Sstevel@tonic-gate #define	VTOC_OK		0	/* Good VTOC */
1137c478bd9Sstevel@tonic-gate #define	VTOC_INVAL	1	/* invalid VTOC */
1147c478bd9Sstevel@tonic-gate #define	VTOC_NOTSUP	2	/* operation not supported - EFI label */
1157c478bd9Sstevel@tonic-gate #define	VTOC_RWERR	3	/* couldn't read or write VTOC */
1167c478bd9Sstevel@tonic-gate 
117f85c7842SSuhasini Peddada /*
118f85c7842SSuhasini Peddada  * Support for fdisk(1M) on the SPARC platform
119f85c7842SSuhasini Peddada  *	In order to convert little endian values to big endian for SPARC,
120f85c7842SSuhasini Peddada  *	byte/short and long values must be swapped.
121f85c7842SSuhasini Peddada  *	These swapping macros will be used to access information in the
122f85c7842SSuhasini Peddada  *	mboot and ipart structures.
123f85c7842SSuhasini Peddada  */
124f85c7842SSuhasini Peddada 
125f85c7842SSuhasini Peddada #ifdef sparc
126f85c7842SSuhasini Peddada #define	les(val)	((((val)&0xFF)<<8)|(((val)>>8)&0xFF))
127f85c7842SSuhasini Peddada #define	lel(val)	(((unsigned)(les((val)&0x0000FFFF))<<16) | \
128f85c7842SSuhasini Peddada 			    (les((unsigned)((val)&0xffff0000)>>16)))
129f85c7842SSuhasini Peddada #else
130f85c7842SSuhasini Peddada #define	les(val)	(val)
131f85c7842SSuhasini Peddada #define	lel(val)	(val)
132f85c7842SSuhasini Peddada #endif
133f85c7842SSuhasini Peddada 
1347c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
1359d5d1945Sbharding #define	VTOC_OFFSET	1
1367c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_8)
1377c478bd9Sstevel@tonic-gate #define	VTOC_OFFSET	0
1387c478bd9Sstevel@tonic-gate #else
1397c478bd9Sstevel@tonic-gate #error No VTOC format defined.
1407c478bd9Sstevel@tonic-gate #endif
1417c478bd9Sstevel@tonic-gate 
142*aa1b14e7SSheshadri Vasudevan #ifdef i386
143*aa1b14e7SSheshadri Vasudevan #define	FDISK_KB	(1024)
144*aa1b14e7SSheshadri Vasudevan #define	FDISK_MB	(FDISK_KB * 1024)
145*aa1b14e7SSheshadri Vasudevan #define	FDISK_GB	(FDISK_MB * 1024)
146*aa1b14e7SSheshadri Vasudevan #define	TRUE	1
147*aa1b14e7SSheshadri Vasudevan 
148*aa1b14e7SSheshadri Vasudevan #define	FDISK_MAX_VALID_PART_ID	255
149*aa1b14e7SSheshadri Vasudevan #define	FDISK_MAX_VALID_PART_NUM_DIGITS	2
150*aa1b14e7SSheshadri Vasudevan #define	FDISK_MAX_VALID_PART_ID_DIGITS	3
151*aa1b14e7SSheshadri Vasudevan 
152*aa1b14e7SSheshadri Vasudevan /* Maximum number of digits for a valid partition size */
153*aa1b14e7SSheshadri Vasudevan #define	FDISK_MAX_VALID_CYL_NUM_DIGITS	10
154*aa1b14e7SSheshadri Vasudevan 
155*aa1b14e7SSheshadri Vasudevan /* Minimum partition size in cylinders */
156*aa1b14e7SSheshadri Vasudevan #define	FDISK_MIN_PART_SIZE	1
157*aa1b14e7SSheshadri Vasudevan #endif
158*aa1b14e7SSheshadri Vasudevan 
159bb16350dSlclee static char Usage[] = "Usage: fdisk\n"
1607c478bd9Sstevel@tonic-gate "[ -A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n"
1617c478bd9Sstevel@tonic-gate "[ -b masterboot ]\n"
1627c478bd9Sstevel@tonic-gate "[ -D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n"
1637c478bd9Sstevel@tonic-gate "[ -F fdisk_file ] [ -h ] [ -o offset ] [ -P fill_patt ] [ -s size ]\n"
1647c478bd9Sstevel@tonic-gate "[ -S geom_file ] [ [ -v ] -W { creat_fdisk_file | - } ]\n"
1657c478bd9Sstevel@tonic-gate "[ -w | r | d | n | I | B | E | g | G | R | t | T ] rdevice";
1667c478bd9Sstevel@tonic-gate 
167bb16350dSlclee static char Usage1[] = "    Partition options:\n"
1687c478bd9Sstevel@tonic-gate "	-A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n"
1697c478bd9Sstevel@tonic-gate "		Create a partition with specific attributes:\n"
1707c478bd9Sstevel@tonic-gate "		id      = system id number (fdisk.h) for the partition type\n"
1717c478bd9Sstevel@tonic-gate "		act     = active partition flag (0 is off and 128 is on)\n"
1727c478bd9Sstevel@tonic-gate "		bhead   = beginning head for start of partition\n"
1737c478bd9Sstevel@tonic-gate "		bsect   = beginning sector for start of partition\n"
1747c478bd9Sstevel@tonic-gate "		bcyl    = beginning cylinder for start of partition\n"
1757c478bd9Sstevel@tonic-gate "		ehead   = ending head for end of partition\n"
1767c478bd9Sstevel@tonic-gate "		esect   = ending sector for end of partition\n"
1777c478bd9Sstevel@tonic-gate "		ecyl    = ending cylinder for end of partition\n"
1787c478bd9Sstevel@tonic-gate "		rsect   = sector number from start of disk for\n"
1797c478bd9Sstevel@tonic-gate "			  start of partition\n"
1807c478bd9Sstevel@tonic-gate "		numsect = partition size in sectors\n"
1817c478bd9Sstevel@tonic-gate "	-b master_boot\n"
1827c478bd9Sstevel@tonic-gate "		Use master_boot as the master boot file.\n"
1837c478bd9Sstevel@tonic-gate "	-B	Create one Solaris partition that uses the entire disk.\n"
1847c478bd9Sstevel@tonic-gate "	-E	Create one EFI partition that uses the entire disk.\n"
1857c478bd9Sstevel@tonic-gate "	-D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n"
1867c478bd9Sstevel@tonic-gate "		Delete a partition. See attribute definitions for -A.\n"
1877c478bd9Sstevel@tonic-gate "	-F fdisk_file\n"
1887c478bd9Sstevel@tonic-gate "		Use fdisk_file to initialize on-line fdisk table.\n"
1897c478bd9Sstevel@tonic-gate "	-I	Forego device checks. Generate a file image of what would go\n"
1907c478bd9Sstevel@tonic-gate "		on a disk using the geometry specified with the -S option.\n"
1917c478bd9Sstevel@tonic-gate "	-n	Do not run in interactive mode.\n"
1927c478bd9Sstevel@tonic-gate "	-R	Open the disk device as read-only.\n"
1937c478bd9Sstevel@tonic-gate "	-t	Check and adjust VTOC to be consistent with fdisk table.\n"
1947c478bd9Sstevel@tonic-gate "		VTOC slices exceeding the partition size will be truncated.\n"
1957c478bd9Sstevel@tonic-gate "	-T	Check and adjust VTOC to be consistent with fdisk table.\n"
1967c478bd9Sstevel@tonic-gate "		VTOC slices exceeding the partition size will be removed.\n"
1977c478bd9Sstevel@tonic-gate "	-W fdisk_file\n"
1987c478bd9Sstevel@tonic-gate "		Write on-disk table to fdisk_file.\n"
1997c478bd9Sstevel@tonic-gate "	-W -	Write on-disk table to standard output.\n"
2007c478bd9Sstevel@tonic-gate "	-v	Display virtual geometry. Must be used with the -W option.\n"
2017c478bd9Sstevel@tonic-gate "    Diagnostic options:\n"
2027c478bd9Sstevel@tonic-gate "	-d	Activate debug information about progress.\n"
2037c478bd9Sstevel@tonic-gate "	-g	Write label geometry to standard output:\n"
2047c478bd9Sstevel@tonic-gate "		PCYL		number of physical cylinders\n"
2057c478bd9Sstevel@tonic-gate "		NCYL		number of usable cylinders\n"
2067c478bd9Sstevel@tonic-gate "		ACYL		number of alternate cylinders\n"
2077c478bd9Sstevel@tonic-gate "		BCYL		cylinder offset\n"
2087c478bd9Sstevel@tonic-gate "		NHEADS		number of heads\n"
2097c478bd9Sstevel@tonic-gate "		NSECTORS	number of sectors per track\n"
2107c478bd9Sstevel@tonic-gate "		SECTSIZ		size of a sector in bytes\n"
2117c478bd9Sstevel@tonic-gate "	-G	Write physical geometry to standard output (see -g).\n"
2127c478bd9Sstevel@tonic-gate "	-h	Issue this verbose help message.\n"
2137c478bd9Sstevel@tonic-gate "	-o offset\n"
2147c478bd9Sstevel@tonic-gate "		Block offset from start of disk (default 0). Ignored if\n"
2157c478bd9Sstevel@tonic-gate "		-P # specified.\n"
2167c478bd9Sstevel@tonic-gate "	-P fill_patt\n"
2177c478bd9Sstevel@tonic-gate "		Fill disk with pattern fill_patt. fill_patt can be decimal or\n"
2187c478bd9Sstevel@tonic-gate "		hexadecimal and is used as number for constant long word\n"
2197c478bd9Sstevel@tonic-gate "		pattern. If fill_patt is \"#\" then pattern of block #\n"
2207c478bd9Sstevel@tonic-gate "		for each block. Pattern is put in each block as long words\n"
2217c478bd9Sstevel@tonic-gate "		and fills each block (see -o and -s).\n"
2227c478bd9Sstevel@tonic-gate "	-r	Read from a disk to stdout (see -o and -s).\n"
2237c478bd9Sstevel@tonic-gate "	-s size	Number of blocks on which to perform operation (see -o).\n"
2247c478bd9Sstevel@tonic-gate "	-S geom_file\n"
2257c478bd9Sstevel@tonic-gate "		Use geom_file to set the label geometry (see -g).\n"
2267c478bd9Sstevel@tonic-gate "	-w	Write to a disk from stdin (see -o and -s).";
2277c478bd9Sstevel@tonic-gate 
228bb16350dSlclee static char Ostr[] = "Other OS";
229bb16350dSlclee static char Dstr[] = "DOS12";
230bb16350dSlclee static char D16str[] = "DOS16";
231bb16350dSlclee static char DDstr[] = "DOS-DATA";
232bb16350dSlclee static char EDstr[] = "EXT-DOS";
233bb16350dSlclee static char DBstr[] = "DOS-BIG";
234bb16350dSlclee static char PCstr[] = "PCIX";
235bb16350dSlclee static char Ustr[] = "UNIX System";
236bb16350dSlclee static char SUstr[] = "Solaris";
237bb16350dSlclee static char SU2str[] = "Solaris2";
238bb16350dSlclee static char X86str[] = "x86 Boot";
239bb16350dSlclee static char DIAGstr[] = "Diagnostic";
240bb16350dSlclee static char IFSstr[] = "IFS: NTFS";
241bb16350dSlclee static char AIXstr[] = "AIX Boot";
242bb16350dSlclee static char AIXDstr[] = "AIX Data";
243bb16350dSlclee static char OS2str[] = "OS/2 Boot";
244bb16350dSlclee static char WINstr[] = "Win95 FAT32";
245bb16350dSlclee static char EWINstr[] = "Ext Win95";
246bb16350dSlclee static char FAT95str[] = "FAT16 LBA";
247bb16350dSlclee static char EXTLstr[] = "EXT LBA";
248bb16350dSlclee static char LINUXstr[] = "Linux";
249bb16350dSlclee static char CPMstr[] = "CP/M";
250*aa1b14e7SSheshadri Vasudevan static char NOV2str[] = "Netware 286";
251bb16350dSlclee static char NOVstr[] = "Netware 3.x+";
252bb16350dSlclee static char QNXstr[] = "QNX 4.x";
253bb16350dSlclee static char QNX2str[] = "QNX part 2";
254bb16350dSlclee static char QNX3str[] = "QNX part 3";
255bb16350dSlclee static char LINNATstr[] = "Linux native";
256bb16350dSlclee static char NTFSVOL1str[] = "NT volset 1";
257bb16350dSlclee static char NTFSVOL2str[] = "NT volset 2";
258bb16350dSlclee static char BSDstr[] = "BSD OS";
259bb16350dSlclee static char NEXTSTEPstr[] = "NeXTSTEP";
260bb16350dSlclee static char BSDIFSstr[] = "BSDI FS";
261bb16350dSlclee static char BSDISWAPstr[] = "BSDI swap";
262bb16350dSlclee static char Actvstr[] = "Active";
263bb16350dSlclee static char EFIstr[] = "EFI";
264bb16350dSlclee static char NAstr[] = "      ";
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate /* All the user options and flags */
267bb16350dSlclee static char *Dfltdev;			/* name of fixed disk drive */
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate /* Diagnostic options */
270bb16350dSlclee static int	io_wrt = 0;		/* write stdin to disk (-w) */
271bb16350dSlclee static int	io_rd = 0;		/* read disk and write stdout (-r) */
272bb16350dSlclee static char	*io_fatt;		/* user supplied pattern (-P pattern) */
273bb16350dSlclee static int	io_patt = 0;		/* write pattern to disk (-P pattern) */
274bb16350dSlclee static int	io_lgeom = 0;		/* get label geometry (-g) */
275bb16350dSlclee static int	io_pgeom = 0;		/* get drive physical geometry (-G) */
276bb16350dSlclee static char	*io_sgeom = 0;		/* set label geometry (-S geom_file) */
277bb16350dSlclee static int	io_readonly = 0;	/* do not write to disk (-R) */
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate /* The -o offset and -s size options specify the area of the disk on */
2807c478bd9Sstevel@tonic-gate /* which to perform the particular operation; i.e., -P, -r, or -w. */
2819d5d1945Sbharding static off_t	io_offset = 0;		/* offset sector (-o offset) */
2829d5d1945Sbharding static off_t	io_size = 0;		/* size in sectors (-s size) */
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate /* Partition table flags */
285bb16350dSlclee static int	v_flag = 0;		/* virtual geometry-HBA flag (-v) */
286bb16350dSlclee static int 	stdo_flag = 0;		/* stdout flag (-W -) */
287bb16350dSlclee static int	io_fdisk = 0;		/* do fdisk operation */
288bb16350dSlclee static int	io_ifdisk = 0;		/* interactive partition */
289bb16350dSlclee static int	io_nifdisk = 0;		/* non-interactive partition (-n) */
290bb16350dSlclee 
291bb16350dSlclee static int	io_adjt = 0;		/* check/adjust VTOC (truncate (-t)) */
292bb16350dSlclee static int	io_ADJT = 0;		/* check/adjust VTOC (delete (-T)) */
293bb16350dSlclee static char	*io_ffdisk = 0;		/* input fdisk file name (-F file) */
294bb16350dSlclee static char	*io_Wfdisk = 0;		/* output fdisk file name (-W file) */
295bb16350dSlclee static char	*io_Afdisk = 0;		/* add entry to partition table (-A) */
296bb16350dSlclee static char	*io_Dfdisk = 0;		/* delete entry from part. table (-D) */
297bb16350dSlclee 
298bb16350dSlclee static char	*io_mboot = 0;		/* master boot record (-b boot_file) */
299bb16350dSlclee 
300bb16350dSlclee static struct mboot BootCod;		/* buffer for master boot record */
301bb16350dSlclee 
302bb16350dSlclee static int	io_wholedisk = 0;	/* use whole disk for Solaris (-B) */
303bb16350dSlclee static int	io_EFIdisk = 0;		/* use whole disk for EFI (-E) */
304bb16350dSlclee static int	io_debug = 0;		/* activate verbose mode (-d) */
305bb16350dSlclee static int	io_image = 0;		/* create image using geometry (-I) */
306bb16350dSlclee 
307bb16350dSlclee static struct mboot *Bootblk;		/* pointer to cut/paste sector zero */
308bb16350dSlclee static char	*Bootsect;		/* pointer to sector zero buffer */
309bb16350dSlclee static char	*Nullsect;
310342440ecSPrasad Singamsetty static struct extvtoc	disk_vtoc;	/* verify VTOC table */
311bb16350dSlclee static int	vt_inval = 0;
312bb16350dSlclee static int	no_virtgeom_ioctl = 0;	/* ioctl for virtual geometry failed */
313bb16350dSlclee static int	no_physgeom_ioctl = 0;	/* ioctl for physical geometry failed */
314bb16350dSlclee 
315bb16350dSlclee static struct ipart	Table[FD_NUMPART];
316bb16350dSlclee static struct ipart	Old_Table[FD_NUMPART];
3172f8ec719SBarry Harding static int		skip_verify[FD_NUMPART]; /* special case skip sz chk */
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate /* Disk geometry information */
3201237e847Slclee static struct dk_minfo	minfo;
321bb16350dSlclee static struct dk_geom	disk_geom;
3227c478bd9Sstevel@tonic-gate 
323342440ecSPrasad Singamsetty static int Dev;			/* fd for open device */
324342440ecSPrasad Singamsetty 
3251237e847Slclee static diskaddr_t	dev_capacity;	/* number of blocks on device */
326342440ecSPrasad Singamsetty static diskaddr_t	chs_capacity;	/* Numcyl_usable * heads * sectors */
327342440ecSPrasad Singamsetty 
328342440ecSPrasad Singamsetty static int		Numcyl_usable;	/* Number of usable cylinders */
329342440ecSPrasad Singamsetty 					/*  used to limit fdisk to 2TB */
3301237e847Slclee 
3317c478bd9Sstevel@tonic-gate /* Physical geometry for the drive */
332bb16350dSlclee static int	Numcyl;			/* number of cylinders */
333bb16350dSlclee static int	heads;			/* number of heads */
334bb16350dSlclee static int	sectors;		/* number of sectors per track */
335bb16350dSlclee static int	acyl;			/* number of alternate sectors */
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate /* HBA (virtual) geometry for the drive */
338bb16350dSlclee static int	hba_Numcyl;		/* number of cylinders */
339bb16350dSlclee static int	hba_heads;		/* number of heads */
340bb16350dSlclee static int	hba_sectors;		/* number of sectors per track */
3417c478bd9Sstevel@tonic-gate 
342bb16350dSlclee static int	sectsiz;		/* sector size */
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate /* Load functions for fdisk table modification */
3457c478bd9Sstevel@tonic-gate #define	LOADFILE	0	/* load fdisk from file */
3467c478bd9Sstevel@tonic-gate #define	LOADDEL		1	/* delete an fdisk entry */
3477c478bd9Sstevel@tonic-gate #define	LOADADD		2	/* add an fdisk entry */
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate #define	CBUFLEN 80
350bb16350dSlclee static char s[CBUFLEN];
351bb16350dSlclee 
352*aa1b14e7SSheshadri Vasudevan #ifdef i386
353*aa1b14e7SSheshadri Vasudevan /*
354*aa1b14e7SSheshadri Vasudevan  * Complete list of all the 255 partition types. Some are unknown types
355*aa1b14e7SSheshadri Vasudevan  * and some entries are known to be unused.
356*aa1b14e7SSheshadri Vasudevan  *
357*aa1b14e7SSheshadri Vasudevan  * Courtesy of http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
358*aa1b14e7SSheshadri Vasudevan  */
359*aa1b14e7SSheshadri Vasudevan char *fdisk_part_types[] = {
360*aa1b14e7SSheshadri Vasudevan 	"Empty",				/* 0 */
361*aa1b14e7SSheshadri Vasudevan 	"FAT12",				/* 1 */
362*aa1b14e7SSheshadri Vasudevan 	"XENIX /",				/* 2 */
363*aa1b14e7SSheshadri Vasudevan 	"XENIX /usr",				/* 3 */
364*aa1b14e7SSheshadri Vasudevan 	"FAT16 (Upto 32M)",			/* 4 */
365*aa1b14e7SSheshadri Vasudevan 	"DOS Extended",				/* 5 */
366*aa1b14e7SSheshadri Vasudevan 	"FAT16 (>32M, HUGEDOS)",		/* 6 */
367*aa1b14e7SSheshadri Vasudevan 	"IFS: NTFS",				/* 7 */
368*aa1b14e7SSheshadri Vasudevan 	"AIX Boot/QNX(qny)",			/* 8 */
369*aa1b14e7SSheshadri Vasudevan 	"AIX Data/QNX(qnz)",			/* 9 */
370*aa1b14e7SSheshadri Vasudevan 	"OS/2 Boot/Coherent swap",		/* 10 */
371*aa1b14e7SSheshadri Vasudevan 	"WIN95 FAT32(Upto 2047GB)",		/* 11 */
372*aa1b14e7SSheshadri Vasudevan 	"WIN95 FAT32(LBA)",			/* 12 */
373*aa1b14e7SSheshadri Vasudevan 	"Unused",				/* 13 */
374*aa1b14e7SSheshadri Vasudevan 	"WIN95 FAT16(LBA)",			/* 14 */
375*aa1b14e7SSheshadri Vasudevan 	"WIN95 Extended(LBA)",			/* 15 */
376*aa1b14e7SSheshadri Vasudevan 	"OPUS",					/* 16 */
377*aa1b14e7SSheshadri Vasudevan 	"Hidden FAT12",				/* 17 */
378*aa1b14e7SSheshadri Vasudevan 	"Diagnostic",				/* 18 */
379*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 19 */
380*aa1b14e7SSheshadri Vasudevan 	"Hidden FAT16(Upto 32M)",		/* 20 */
381*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 21 */
382*aa1b14e7SSheshadri Vasudevan 	"Hidden FAT16(>=32M)",			/* 22 */
383*aa1b14e7SSheshadri Vasudevan 	"Hidden IFS: HPFS",			/* 23 */
384*aa1b14e7SSheshadri Vasudevan 	"AST SmartSleep Partition",		/* 24 */
385*aa1b14e7SSheshadri Vasudevan 	"Unused/Willowtech Photon",		/* 25 */
386*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 26 */
387*aa1b14e7SSheshadri Vasudevan 	"Hidden FAT32",				/* 27 */
388*aa1b14e7SSheshadri Vasudevan 	"Hidden FAT32(LBA)",			/* 28 */
389*aa1b14e7SSheshadri Vasudevan 	"Unused",				/* 29 */
390*aa1b14e7SSheshadri Vasudevan 	"Hidden FAT16(LBA)",			/* 30 */
391*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 31 */
392*aa1b14e7SSheshadri Vasudevan 	"Unused/OSF1",				/* 32 */
393*aa1b14e7SSheshadri Vasudevan 	"Reserved/FSo2(Oxygen FS)",		/* 33 */
394*aa1b14e7SSheshadri Vasudevan 	"Unused/(Oxygen EXT)",			/* 34 */
395*aa1b14e7SSheshadri Vasudevan 	"Reserved",				/* 35 */
396*aa1b14e7SSheshadri Vasudevan 	"NEC DOS 3.x",				/* 36 */
397*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 37 */
398*aa1b14e7SSheshadri Vasudevan 	"Reserved",				/* 38 */
399*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 39 */
400*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 40 */
401*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 41 */
402*aa1b14e7SSheshadri Vasudevan 	"AtheOS File System",			/* 42 */
403*aa1b14e7SSheshadri Vasudevan 	"SyllableSecure",			/* 43 */
404*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 44 */
405*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 45 */
406*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 46 */
407*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 47 */
408*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 48 */
409*aa1b14e7SSheshadri Vasudevan 	"Reserved",				/* 49 */
410*aa1b14e7SSheshadri Vasudevan 	"NOS",					/* 50 */
411*aa1b14e7SSheshadri Vasudevan 	"Reserved",				/* 51 */
412*aa1b14e7SSheshadri Vasudevan 	"Reserved",				/* 52 */
413*aa1b14e7SSheshadri Vasudevan 	"JFS on OS/2",				/* 53 */
414*aa1b14e7SSheshadri Vasudevan 	"Reserved",				/* 54 */
415*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 55 */
416*aa1b14e7SSheshadri Vasudevan 	"THEOS 3.2 2GB",			/* 56 */
417*aa1b14e7SSheshadri Vasudevan 	"Plan9/THEOS 4",			/* 57 */
418*aa1b14e7SSheshadri Vasudevan 	"THEOS 4 4GB",				/* 58 */
419*aa1b14e7SSheshadri Vasudevan 	"THEOS 4 Extended",			/* 59 */
420*aa1b14e7SSheshadri Vasudevan 	"PartitionMagic Recovery",		/* 60 */
421*aa1b14e7SSheshadri Vasudevan 	"Hidden NetWare",			/* 61 */
422*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 62 */
423*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 63 */
424*aa1b14e7SSheshadri Vasudevan 	"Venix 80286",				/* 64 */
425*aa1b14e7SSheshadri Vasudevan 	"MINIX/PPC PReP Boot",			/* 65 */
426*aa1b14e7SSheshadri Vasudevan 	"Win2K Dynamic Disk/SFS(DOS)",		/* 66 */
427*aa1b14e7SSheshadri Vasudevan 	"Linux+DRDOS shared",			/* 67 */
428*aa1b14e7SSheshadri Vasudevan 	"GoBack partition",			/* 68 */
429*aa1b14e7SSheshadri Vasudevan 	"Boot-US boot manager",			/* 69 */
430*aa1b14e7SSheshadri Vasudevan 	"EUMEL/Elan",				/* 70 */
431*aa1b14e7SSheshadri Vasudevan 	"EUMEL/Elan",				/* 71 */
432*aa1b14e7SSheshadri Vasudevan 	"EUMEL/Elan",				/* 72 */
433*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 73 */
434*aa1b14e7SSheshadri Vasudevan 	"ALFS/THIN FS for DOS",			/* 74 */
435*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 75 */
436*aa1b14e7SSheshadri Vasudevan 	"Oberon partition",			/* 76 */
437*aa1b14e7SSheshadri Vasudevan 	"QNX 4,x",				/* 77 */
438*aa1b14e7SSheshadri Vasudevan 	"QNX 4,x 2nd Part",			/* 78 */
439*aa1b14e7SSheshadri Vasudevan 	"QNX 4,x 3rd Part",			/* 79 */
440*aa1b14e7SSheshadri Vasudevan 	"OnTrack DM R/O, Lynx RTOS",		/* 80 */
441*aa1b14e7SSheshadri Vasudevan 	"OnTrack DM R/W, Novell",		/* 81 */
442*aa1b14e7SSheshadri Vasudevan 	"CP/M",					/* 82 */
443*aa1b14e7SSheshadri Vasudevan 	"Disk Manager 6.0 Aux3",		/* 83 */
444*aa1b14e7SSheshadri Vasudevan 	"Disk Manager 6.0 DDO",			/* 84 */
445*aa1b14e7SSheshadri Vasudevan 	"EZ-Drive",				/* 85 */
446*aa1b14e7SSheshadri Vasudevan 	"Golden Bow VFeature/AT&T MS-DOS",	/* 86 */
447*aa1b14e7SSheshadri Vasudevan 	"DrivePro",				/* 87 */
448*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 88 */
449*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 89 */
450*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 90 */
451*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 91 */
452*aa1b14e7SSheshadri Vasudevan 	"Priam EDisk",				/* 92 */
453*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 93 */
454*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 94 */
455*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 95 */
456*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 96 */
457*aa1b14e7SSheshadri Vasudevan 	"SpeedStor",				/* 97 */
458*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 98 */
459*aa1b14e7SSheshadri Vasudevan 	"Unix SysV, Mach, GNU Hurd",		/* 99 */
460*aa1b14e7SSheshadri Vasudevan 	"PC-ARMOUR, Netware 286",		/* 100 */
461*aa1b14e7SSheshadri Vasudevan 	"Netware 386",				/* 101 */
462*aa1b14e7SSheshadri Vasudevan 	"Netware SMS",				/* 102 */
463*aa1b14e7SSheshadri Vasudevan 	"Novell",				/* 103 */
464*aa1b14e7SSheshadri Vasudevan 	"Novell",				/* 104 */
465*aa1b14e7SSheshadri Vasudevan 	"Netware NSS",				/* 105 */
466*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 106 */
467*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 107 */
468*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 108 */
469*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 109 */
470*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 110 */
471*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 111 */
472*aa1b14e7SSheshadri Vasudevan 	"DiskSecure Multi-Boot",		/* 112 */
473*aa1b14e7SSheshadri Vasudevan 	"Reserved",				/* 113 */
474*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 114 */
475*aa1b14e7SSheshadri Vasudevan 	"Reserved",				/* 115 */
476*aa1b14e7SSheshadri Vasudevan 	"Scramdisk partition",			/* 116 */
477*aa1b14e7SSheshadri Vasudevan 	"IBM PC/IX",				/* 117 */
478*aa1b14e7SSheshadri Vasudevan 	"Reserved",				/* 118 */
479*aa1b14e7SSheshadri Vasudevan 	"M2FS/M2CS,Netware VNDI",		/* 119 */
480*aa1b14e7SSheshadri Vasudevan 	"XOSL FS",				/* 120 */
481*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 121 */
482*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 122 */
483*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 123 */
484*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 124 */
485*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 125 */
486*aa1b14e7SSheshadri Vasudevan 	"Unused",				/* 126 */
487*aa1b14e7SSheshadri Vasudevan 	"Unused",				/* 127 */
488*aa1b14e7SSheshadri Vasudevan 	"MINIX until 1.4a",			/* 128 */
489*aa1b14e7SSheshadri Vasudevan 	"MINIX since 1.4b, early Linux",	/* 129 */
490*aa1b14e7SSheshadri Vasudevan 	"Solaris/Linux swap",			/* 130 */
491*aa1b14e7SSheshadri Vasudevan 	"Linux native",				/* 131 */
492*aa1b14e7SSheshadri Vasudevan 	"OS/2 hidden,Win Hibernation",		/* 132 */
493*aa1b14e7SSheshadri Vasudevan 	"Linux extended",			/* 133 */
494*aa1b14e7SSheshadri Vasudevan 	"Old Linux RAID,NT FAT16 RAID",		/* 134 */
495*aa1b14e7SSheshadri Vasudevan 	"NTFS volume set",			/* 135 */
496*aa1b14e7SSheshadri Vasudevan 	"Linux plaintext part table",		/* 136 */
497*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 137 */
498*aa1b14e7SSheshadri Vasudevan 	"Linux Kernel Partition",		/* 138 */
499*aa1b14e7SSheshadri Vasudevan 	"Fault Tolerant FAT32 volume",		/* 139 */
500*aa1b14e7SSheshadri Vasudevan 	"Fault Tolerant FAT32 volume",		/* 140 */
501*aa1b14e7SSheshadri Vasudevan 	"Free FDISK hidden PDOS FAT12",		/* 141 */
502*aa1b14e7SSheshadri Vasudevan 	"Linux LVM partition",			/* 142 */
503*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 143 */
504*aa1b14e7SSheshadri Vasudevan 	"Free FDISK hidden PDOS FAT16",		/* 144 */
505*aa1b14e7SSheshadri Vasudevan 	"Free FDISK hidden DOS EXT",		/* 145 */
506*aa1b14e7SSheshadri Vasudevan 	"Free FDISK hidden FAT16 Large",	/* 146 */
507*aa1b14e7SSheshadri Vasudevan 	"Hidden Linux native, Amoeba",		/* 147 */
508*aa1b14e7SSheshadri Vasudevan 	"Amoeba Bad Block Table",		/* 148 */
509*aa1b14e7SSheshadri Vasudevan 	"MIT EXOPC Native",			/* 149 */
510*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 150 */
511*aa1b14e7SSheshadri Vasudevan 	"Free FDISK hidden PDOS FAT32",		/* 151 */
512*aa1b14e7SSheshadri Vasudevan 	"Free FDISK hidden FAT32 LBA",		/* 152 */
513*aa1b14e7SSheshadri Vasudevan 	"DCE376 logical drive",			/* 153 */
514*aa1b14e7SSheshadri Vasudevan 	"Free FDISK hidden FAT16 LBA",		/* 154 */
515*aa1b14e7SSheshadri Vasudevan 	"Free FDISK hidden DOS EXT",		/* 155 */
516*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 156 */
517*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 157 */
518*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 158 */
519*aa1b14e7SSheshadri Vasudevan 	"BSD/OS",				/* 159 */
520*aa1b14e7SSheshadri Vasudevan 	"Laptop hibernation",			/* 160 */
521*aa1b14e7SSheshadri Vasudevan 	"Laptop hibernate,HP SpeedStor",	/* 161 */
522*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 162 */
523*aa1b14e7SSheshadri Vasudevan 	"HP SpeedStor",				/* 163 */
524*aa1b14e7SSheshadri Vasudevan 	"HP SpeedStor",				/* 164 */
525*aa1b14e7SSheshadri Vasudevan 	"BSD/386,386BSD,NetBSD,FreeBSD",	/* 165 */
526*aa1b14e7SSheshadri Vasudevan 	"OpenBSD,HP SpeedStor",			/* 166 */
527*aa1b14e7SSheshadri Vasudevan 	"NeXTStep",				/* 167 */
528*aa1b14e7SSheshadri Vasudevan 	"Mac OS-X",				/* 168 */
529*aa1b14e7SSheshadri Vasudevan 	"NetBSD",				/* 169 */
530*aa1b14e7SSheshadri Vasudevan 	"Olivetti FAT12 1.44MB Service",	/* 170 */
531*aa1b14e7SSheshadri Vasudevan 	"Mac OS-X Boot",			/* 171 */
532*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 172 */
533*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 173 */
534*aa1b14e7SSheshadri Vasudevan 	"ShagOS filesystem",			/* 174 */
535*aa1b14e7SSheshadri Vasudevan 	"ShagOS swap",				/* 175 */
536*aa1b14e7SSheshadri Vasudevan 	"BootStar Dummy",			/* 176 */
537*aa1b14e7SSheshadri Vasudevan 	"HP SpeedStor",				/* 177 */
538*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 178 */
539*aa1b14e7SSheshadri Vasudevan 	"HP SpeedStor",				/* 179 */
540*aa1b14e7SSheshadri Vasudevan 	"HP SpeedStor",				/* 180 */
541*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 181 */
542*aa1b14e7SSheshadri Vasudevan 	"Corrupted FAT16 NT Mirror Set",	/* 182 */
543*aa1b14e7SSheshadri Vasudevan 	"Corrupted NTFS NT Mirror Set",		/* 183 */
544*aa1b14e7SSheshadri Vasudevan 	"Old BSDI BSD/386 swap",		/* 184 */
545*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 185 */
546*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 186 */
547*aa1b14e7SSheshadri Vasudevan 	"Boot Wizard hidden",			/* 187 */
548*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 188 */
549*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 189 */
550*aa1b14e7SSheshadri Vasudevan 	"Solaris x86 boot",			/* 190 */
551*aa1b14e7SSheshadri Vasudevan 	"Solaris2",				/* 191 */
552*aa1b14e7SSheshadri Vasudevan 	"REAL/32 or Novell DOS secured",	/* 192 */
553*aa1b14e7SSheshadri Vasudevan 	"DRDOS/secured(FAT12)",			/* 193 */
554*aa1b14e7SSheshadri Vasudevan 	"Hidden Linux",				/* 194 */
555*aa1b14e7SSheshadri Vasudevan 	"Hidden Linux swap",			/* 195 */
556*aa1b14e7SSheshadri Vasudevan 	"DRDOS/secured(FAT16,< 32M)",		/* 196 */
557*aa1b14e7SSheshadri Vasudevan 	"DRDOS/secured(Extended)",		/* 197 */
558*aa1b14e7SSheshadri Vasudevan 	"NT corrupted FAT16 volume",		/* 198 */
559*aa1b14e7SSheshadri Vasudevan 	"NT corrupted NTFS volume",		/* 199 */
560*aa1b14e7SSheshadri Vasudevan 	"DRDOS8.0+",				/* 200 */
561*aa1b14e7SSheshadri Vasudevan 	"DRDOS8.0+",				/* 201 */
562*aa1b14e7SSheshadri Vasudevan 	"DRDOS8.0+",				/* 202 */
563*aa1b14e7SSheshadri Vasudevan 	"DRDOS7.04+ secured FAT32(CHS)",	/* 203 */
564*aa1b14e7SSheshadri Vasudevan 	"DRDOS7.04+ secured FAT32(LBA)",	/* 204 */
565*aa1b14e7SSheshadri Vasudevan 	"CTOS Memdump",				/* 205 */
566*aa1b14e7SSheshadri Vasudevan 	"DRDOS7.04+ FAT16X(LBA)",		/* 206 */
567*aa1b14e7SSheshadri Vasudevan 	"DRDOS7.04+ secure EXT DOS(LBA)",	/* 207 */
568*aa1b14e7SSheshadri Vasudevan 	"REAL/32 secure big, MDOS",		/* 208 */
569*aa1b14e7SSheshadri Vasudevan 	"Old MDOS secure FAT12",		/* 209 */
570*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 210 */
571*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 211 */
572*aa1b14e7SSheshadri Vasudevan 	"Old MDOS secure FAT16 <32M",		/* 212 */
573*aa1b14e7SSheshadri Vasudevan 	"Old MDOS secure EXT",			/* 213 */
574*aa1b14e7SSheshadri Vasudevan 	"Old MDOS secure FAT16 >=32M",		/* 214 */
575*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 215 */
576*aa1b14e7SSheshadri Vasudevan 	"CP/M-86",				/* 216 */
577*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 217 */
578*aa1b14e7SSheshadri Vasudevan 	"Non-FS Data",				/* 218 */
579*aa1b14e7SSheshadri Vasudevan 	"CP/M,Concurrent DOS,CTOS",		/* 219 */
580*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 220 */
581*aa1b14e7SSheshadri Vasudevan 	"Hidden CTOS memdump",			/* 221 */
582*aa1b14e7SSheshadri Vasudevan 	"Dell PowerEdge utilities(FAT)",	/* 222 */
583*aa1b14e7SSheshadri Vasudevan 	"DG/UX virtual disk manager",		/* 223 */
584*aa1b14e7SSheshadri Vasudevan 	"ST AVFS(STMicroelectronics)",		/* 224 */
585*aa1b14e7SSheshadri Vasudevan 	"SpeedStor 12-bit FAT EXT",		/* 225 */
586*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 226 */
587*aa1b14e7SSheshadri Vasudevan 	"SpeedStor",				/* 227 */
588*aa1b14e7SSheshadri Vasudevan 	"SpeedStor 16-bit FAT EXT",		/* 228 */
589*aa1b14e7SSheshadri Vasudevan 	"Tandy MSDOS",				/* 229 */
590*aa1b14e7SSheshadri Vasudevan 	"Storage Dimensions SpeedStor",		/* 230 */
591*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 231 */
592*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 232 */
593*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 233 */
594*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 234 */
595*aa1b14e7SSheshadri Vasudevan 	"BeOS BFS",				/* 235 */
596*aa1b14e7SSheshadri Vasudevan 	"SkyOS SkyFS",				/* 236 */
597*aa1b14e7SSheshadri Vasudevan 	"Unused",				/* 237 */
598*aa1b14e7SSheshadri Vasudevan 	"EFI Header Indicator",			/* 238 */
599*aa1b14e7SSheshadri Vasudevan 	"EFI Filesystem",			/* 239 */
600*aa1b14e7SSheshadri Vasudevan 	"Linux/PA-RISC boot loader",		/* 240 */
601*aa1b14e7SSheshadri Vasudevan 	"SpeedStor",				/* 241 */
602*aa1b14e7SSheshadri Vasudevan 	"DOS 3.3+ secondary",			/* 242 */
603*aa1b14e7SSheshadri Vasudevan 	"SpeedStor Reserved",			/* 243 */
604*aa1b14e7SSheshadri Vasudevan 	"SpeedStor Large",			/* 244 */
605*aa1b14e7SSheshadri Vasudevan 	"Prologue multi-volume",		/* 245 */
606*aa1b14e7SSheshadri Vasudevan 	"SpeedStor",				/* 246 */
607*aa1b14e7SSheshadri Vasudevan 	"Unused",				/* 247 */
608*aa1b14e7SSheshadri Vasudevan 	"Unknown",				/* 248 */
609*aa1b14e7SSheshadri Vasudevan 	"pCache",				/* 249 */
610*aa1b14e7SSheshadri Vasudevan 	"Bochs",				/* 250 */
611*aa1b14e7SSheshadri Vasudevan 	"VMware File System",			/* 251 */
612*aa1b14e7SSheshadri Vasudevan 	"VMware swap",				/* 252 */
613*aa1b14e7SSheshadri Vasudevan 	"Linux raid autodetect",		/* 253 */
614*aa1b14e7SSheshadri Vasudevan 	"NT Disk Administrator hidden",		/* 254 */
615*aa1b14e7SSheshadri Vasudevan 	"Xenix Bad Block Table"			/* 255 */
616*aa1b14e7SSheshadri Vasudevan };
617*aa1b14e7SSheshadri Vasudevan 
618*aa1b14e7SSheshadri Vasudevan /* Allowed extended partition menu options */
619*aa1b14e7SSheshadri Vasudevan static char ext_part_menu_opts[] = "adhipr";
620*aa1b14e7SSheshadri Vasudevan 
621*aa1b14e7SSheshadri Vasudevan /*
622*aa1b14e7SSheshadri Vasudevan  * Structure holding all information about the extended partition
623*aa1b14e7SSheshadri Vasudevan  * NOTE : As of now, there will be just one instance of ext_part_t, since most
624*aa1b14e7SSheshadri Vasudevan  * known systems allow only one extended dos partition per disk.
625*aa1b14e7SSheshadri Vasudevan  */
626*aa1b14e7SSheshadri Vasudevan static ext_part_t *epp;
627*aa1b14e7SSheshadri Vasudevan #endif
628*aa1b14e7SSheshadri Vasudevan 
629bb16350dSlclee static void update_disk_and_exit(boolean_t table_changed);
630bb16350dSlclee int main(int argc, char *argv[]);
631bb16350dSlclee static int read_geom(char *sgeom);
632bb16350dSlclee static void dev_mboot_read(void);
6339d5d1945Sbharding static void dev_mboot_write(off_t sect, char *buff, int bootsiz);
634bb16350dSlclee static void mboot_read(void);
635bb16350dSlclee static void fill_patt(void);
636bb16350dSlclee static void abs_read(void);
637bb16350dSlclee static void abs_write(void);
638bb16350dSlclee static void load(int funct, char *file);
639bb16350dSlclee static void Set_Table_CHS_Values(int ti);
640bb16350dSlclee static int insert_tbl(int id, int act,
641bb16350dSlclee     int bhead, int bsect, int bcyl,
642bb16350dSlclee     int ehead, int esect, int ecyl,
643342440ecSPrasad Singamsetty     uint32_t rsect, uint32_t numsect);
6442f8ec719SBarry Harding static int entry_from_old_table(int id, int act,
6452f8ec719SBarry Harding     int bhead, int bsect, int bcyl,
6462f8ec719SBarry Harding     int ehead, int esect, int ecyl,
6472f8ec719SBarry Harding     uint32_t rsect, uint32_t numsect);
648bb16350dSlclee static int verify_tbl(void);
649bb16350dSlclee static int pars_fdisk(char *line,
650bb16350dSlclee     int *id, int *act,
651bb16350dSlclee     int *bhead, int *bsect, int *bcyl,
652bb16350dSlclee     int *ehead, int *esect, int *ecyl,
653342440ecSPrasad Singamsetty     uint32_t *rsect, uint32_t *numsect);
654342440ecSPrasad Singamsetty static int validate_part(int id, uint32_t rsect, uint32_t numsect);
655bb16350dSlclee static void stage0(void);
656bb16350dSlclee static int pcreate(void);
657bb16350dSlclee static int specify(uchar_t tsystid);
658bb16350dSlclee static void dispmenu(void);
659bb16350dSlclee static int pchange(void);
660bb16350dSlclee static int ppartid(void);
661bb16350dSlclee static char pdelete(void);
662bb16350dSlclee static void rm_blanks(char *s);
663bb16350dSlclee static int getcyl(void);
664bb16350dSlclee static void disptbl(void);
665bb16350dSlclee static void print_Table(void);
666bb16350dSlclee static void copy_Table_to_Old_Table(void);
667bb16350dSlclee static void nulltbl(void);
668bb16350dSlclee static void copy_Bootblk_to_Table(void);
669bb16350dSlclee static void fill_ipart(char *bootptr, struct ipart *partp);
670bb16350dSlclee #ifdef sparc
671bb16350dSlclee uchar_t getbyte(char **bp);
672bb16350dSlclee uint32_t getlong(char **bp);
673bb16350dSlclee #endif
674bb16350dSlclee static void copy_Table_to_Bootblk(void);
675bb16350dSlclee static int TableChanged(void);
676bb16350dSlclee static void ffile_write(char *file);
677bb16350dSlclee static void fix_slice(void);
678bb16350dSlclee static int yesno(void);
679bb16350dSlclee static int readvtoc(void);
680bb16350dSlclee static int writevtoc(void);
681bb16350dSlclee static int efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc);
682bb16350dSlclee static int clear_efi(void);
683bb16350dSlclee static void clear_vtoc(int table, int part);
684bb16350dSlclee static int lecture_and_query(char *warning, char *devname);
685bb16350dSlclee static void sanity_check_provided_device(char *devname, int fd);
686bb16350dSlclee static char *get_node(char *devname);
6877c478bd9Sstevel@tonic-gate 
688*aa1b14e7SSheshadri Vasudevan #ifdef i386
689*aa1b14e7SSheshadri Vasudevan static void id_to_name(uchar_t sysid, char *buffer);
690*aa1b14e7SSheshadri Vasudevan static void ext_read_input(char *buf);
691*aa1b14e7SSheshadri Vasudevan static int ext_read_options(char *buf);
692*aa1b14e7SSheshadri Vasudevan static int ext_invalid_option(char ch);
693*aa1b14e7SSheshadri Vasudevan static void ext_read_valid_part_num(int *pno);
694*aa1b14e7SSheshadri Vasudevan static void ext_read_valid_part_id(uchar_t *partid);
695*aa1b14e7SSheshadri Vasudevan static int ext_read_valid_partition_start(uint32_t *begsec);
696*aa1b14e7SSheshadri Vasudevan static void ext_read_valid_partition_size(uint32_t begsec, uint32_t *endsec);
697*aa1b14e7SSheshadri Vasudevan static void ext_part_menu();
698*aa1b14e7SSheshadri Vasudevan static int is_linux_swap(uint32_t part_start, off_t *lsm_offset);
699*aa1b14e7SSheshadri Vasudevan static void add_logical_drive();
700*aa1b14e7SSheshadri Vasudevan static void delete_logical_drive();
701*aa1b14e7SSheshadri Vasudevan static void ext_print_help_menu();
702*aa1b14e7SSheshadri Vasudevan static void ext_change_logical_drive_id();
703*aa1b14e7SSheshadri Vasudevan static void ext_print_part_types();
704*aa1b14e7SSheshadri Vasudevan static void ext_print_logical_drive_layout();
705*aa1b14e7SSheshadri Vasudevan static void preach_and_continue();
706*aa1b14e7SSheshadri Vasudevan #ifdef DEBUG
707*aa1b14e7SSheshadri Vasudevan static void ext_print_logdrive_layout_debug();
708*aa1b14e7SSheshadri Vasudevan #endif	/* DEBUG */
709*aa1b14e7SSheshadri Vasudevan #endif	/* i386 */
710*aa1b14e7SSheshadri Vasudevan 
711*aa1b14e7SSheshadri Vasudevan /*
712*aa1b14e7SSheshadri Vasudevan  * This function is called only during the non-interactive mode.
713*aa1b14e7SSheshadri Vasudevan  * It is touchy and does not tolerate any errors. If there are
714*aa1b14e7SSheshadri Vasudevan  * mounted logical drives, changes to the partition table
715*aa1b14e7SSheshadri Vasudevan  * is disallowed.
716*aa1b14e7SSheshadri Vasudevan  */
7177c478bd9Sstevel@tonic-gate static void
7187c478bd9Sstevel@tonic-gate update_disk_and_exit(boolean_t table_changed)
7197c478bd9Sstevel@tonic-gate {
720*aa1b14e7SSheshadri Vasudevan #ifdef i386
721*aa1b14e7SSheshadri Vasudevan 	int rval;
722*aa1b14e7SSheshadri Vasudevan #endif
7237c478bd9Sstevel@tonic-gate 	if (table_changed) {
7247c478bd9Sstevel@tonic-gate 		/*
7257c478bd9Sstevel@tonic-gate 		 * Copy the new table back to the sector buffer
7267c478bd9Sstevel@tonic-gate 		 * and write it to disk
7277c478bd9Sstevel@tonic-gate 		 */
7287c478bd9Sstevel@tonic-gate 		copy_Table_to_Bootblk();
7297c478bd9Sstevel@tonic-gate 		dev_mboot_write(0, Bootsect, sectsiz);
7307c478bd9Sstevel@tonic-gate 	}
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 	/* If the VTOC table is wrong fix it (truncation only) */
7337c478bd9Sstevel@tonic-gate 	if (io_adjt)
7347c478bd9Sstevel@tonic-gate 		fix_slice();
7357c478bd9Sstevel@tonic-gate 
736*aa1b14e7SSheshadri Vasudevan #ifdef i386
737*aa1b14e7SSheshadri Vasudevan 	if (!io_readonly) {
738*aa1b14e7SSheshadri Vasudevan 		rval = fdisk_commit_ext_part(epp);
739*aa1b14e7SSheshadri Vasudevan 		switch (rval) {
740*aa1b14e7SSheshadri Vasudevan 			case FDISK_SUCCESS:
741*aa1b14e7SSheshadri Vasudevan 				/* Success */
742*aa1b14e7SSheshadri Vasudevan 				break;
743*aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOEXTPART:
744*aa1b14e7SSheshadri Vasudevan 				/* Nothing to do */
745*aa1b14e7SSheshadri Vasudevan 				break;
746*aa1b14e7SSheshadri Vasudevan 			default:
747*aa1b14e7SSheshadri Vasudevan 				fprintf(stderr, "Error in"
748*aa1b14e7SSheshadri Vasudevan 				    " fdisk_commit_ext_part\n");
749*aa1b14e7SSheshadri Vasudevan 				exit(rval);
750*aa1b14e7SSheshadri Vasudevan 		}
751*aa1b14e7SSheshadri Vasudevan 	}
752*aa1b14e7SSheshadri Vasudevan 	libfdisk_fini(&epp);
753*aa1b14e7SSheshadri Vasudevan #endif
7547c478bd9Sstevel@tonic-gate 	exit(0);
7557c478bd9Sstevel@tonic-gate }
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate /*
7587c478bd9Sstevel@tonic-gate  * main
7597c478bd9Sstevel@tonic-gate  * Process command-line options.
7607c478bd9Sstevel@tonic-gate  */
761bb16350dSlclee int
7627c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
7637c478bd9Sstevel@tonic-gate {
764bb16350dSlclee 	int c, i;
7657c478bd9Sstevel@tonic-gate 	extern	int optind;
7667c478bd9Sstevel@tonic-gate 	extern	char *optarg;
7677c478bd9Sstevel@tonic-gate 	int	errflg = 0;
7687c478bd9Sstevel@tonic-gate 	int	diag_cnt = 0;
7697c478bd9Sstevel@tonic-gate 	int openmode;
770*aa1b14e7SSheshadri Vasudevan #ifdef i386
771*aa1b14e7SSheshadri Vasudevan 	int rval;
772*aa1b14e7SSheshadri Vasudevan 	int lf_op_flag = 0;
773*aa1b14e7SSheshadri Vasudevan #endif
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	setbuf(stderr, 0);	/* so all output gets out on exit */
7767c478bd9Sstevel@tonic-gate 	setbuf(stdout, 0);
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	/* Process the options. */
7797c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "o:s:P:F:b:A:D:W:S:tTIhwvrndgGRBE"))
7807c478bd9Sstevel@tonic-gate 	    != EOF) {
7817c478bd9Sstevel@tonic-gate 		switch (c) {
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 			case 'o':
7849d5d1945Sbharding 				io_offset = (off_t)strtoull(optarg, 0, 0);
7857c478bd9Sstevel@tonic-gate 				continue;
7867c478bd9Sstevel@tonic-gate 			case 's':
7879d5d1945Sbharding 				io_size = (off_t)strtoull(optarg, 0, 0);
7887c478bd9Sstevel@tonic-gate 				continue;
7897c478bd9Sstevel@tonic-gate 			case 'P':
7907c478bd9Sstevel@tonic-gate 				diag_cnt++;
7917c478bd9Sstevel@tonic-gate 				io_patt++;
7927c478bd9Sstevel@tonic-gate 				io_fatt = optarg;
7937c478bd9Sstevel@tonic-gate 				continue;
7947c478bd9Sstevel@tonic-gate 			case 'w':
7957c478bd9Sstevel@tonic-gate 				diag_cnt++;
7967c478bd9Sstevel@tonic-gate 				io_wrt++;
7977c478bd9Sstevel@tonic-gate 				continue;
7987c478bd9Sstevel@tonic-gate 			case 'r':
7997c478bd9Sstevel@tonic-gate 				diag_cnt++;
8007c478bd9Sstevel@tonic-gate 				io_rd++;
8017c478bd9Sstevel@tonic-gate 				continue;
8027c478bd9Sstevel@tonic-gate 			case 'd':
8037c478bd9Sstevel@tonic-gate 				io_debug++;
8047c478bd9Sstevel@tonic-gate 				continue;
8057c478bd9Sstevel@tonic-gate 			case 'I':
8067c478bd9Sstevel@tonic-gate 				io_image++;
8077c478bd9Sstevel@tonic-gate 				continue;
8087c478bd9Sstevel@tonic-gate 			case 'R':
8097c478bd9Sstevel@tonic-gate 				io_readonly++;
8107c478bd9Sstevel@tonic-gate 				continue;
8117c478bd9Sstevel@tonic-gate 			case 'S':
8127c478bd9Sstevel@tonic-gate 				diag_cnt++;
8137c478bd9Sstevel@tonic-gate 				io_sgeom = optarg;
8147c478bd9Sstevel@tonic-gate 				continue;
8157c478bd9Sstevel@tonic-gate 			case 'T':
8167c478bd9Sstevel@tonic-gate 				io_ADJT++;
817bb16350dSlclee 				/* FALLTHRU */
8187c478bd9Sstevel@tonic-gate 			case 't':
8197c478bd9Sstevel@tonic-gate 				io_adjt++;
8207c478bd9Sstevel@tonic-gate 				continue;
8217c478bd9Sstevel@tonic-gate 			case 'B':
8227c478bd9Sstevel@tonic-gate 				io_wholedisk++;
8237c478bd9Sstevel@tonic-gate 				io_fdisk++;
8247c478bd9Sstevel@tonic-gate 				continue;
8257c478bd9Sstevel@tonic-gate 			case 'E':
8267c478bd9Sstevel@tonic-gate 				io_EFIdisk++;
8277c478bd9Sstevel@tonic-gate 				io_fdisk++;
8287c478bd9Sstevel@tonic-gate 				continue;
8297c478bd9Sstevel@tonic-gate 			case 'g':
8307c478bd9Sstevel@tonic-gate 				diag_cnt++;
8317c478bd9Sstevel@tonic-gate 				io_lgeom++;
8327c478bd9Sstevel@tonic-gate 				continue;
8337c478bd9Sstevel@tonic-gate 			case 'G':
8347c478bd9Sstevel@tonic-gate 				diag_cnt++;
8357c478bd9Sstevel@tonic-gate 				io_pgeom++;
8367c478bd9Sstevel@tonic-gate 				continue;
8377c478bd9Sstevel@tonic-gate 			case 'n':
8387c478bd9Sstevel@tonic-gate 				io_nifdisk++;
8397c478bd9Sstevel@tonic-gate 				io_fdisk++;
8407c478bd9Sstevel@tonic-gate 				continue;
8417c478bd9Sstevel@tonic-gate 			case 'F':
8427c478bd9Sstevel@tonic-gate 				io_fdisk++;
8437c478bd9Sstevel@tonic-gate 				io_ffdisk = optarg;
8447c478bd9Sstevel@tonic-gate 				continue;
8457c478bd9Sstevel@tonic-gate 			case 'b':
8467c478bd9Sstevel@tonic-gate 				io_mboot = optarg;
8477c478bd9Sstevel@tonic-gate 				continue;
8487c478bd9Sstevel@tonic-gate 			case 'W':
8497c478bd9Sstevel@tonic-gate 				/*
8507c478bd9Sstevel@tonic-gate 				 * If '-' is the -W argument, then write
8517c478bd9Sstevel@tonic-gate 				 * to standard output, otherwise write
8527c478bd9Sstevel@tonic-gate 				 * to the specified file.
8537c478bd9Sstevel@tonic-gate 				 */
8547c478bd9Sstevel@tonic-gate 				if (strncmp(optarg, "-", 1) == 0)
8557c478bd9Sstevel@tonic-gate 					stdo_flag = 1;
8567c478bd9Sstevel@tonic-gate 				else
8577c478bd9Sstevel@tonic-gate 					io_Wfdisk = optarg;
8587c478bd9Sstevel@tonic-gate 				io_fdisk++;
8597c478bd9Sstevel@tonic-gate 				continue;
8607c478bd9Sstevel@tonic-gate 			case 'A':
8617c478bd9Sstevel@tonic-gate 				io_fdisk++;
8627c478bd9Sstevel@tonic-gate 				io_Afdisk = optarg;
8637c478bd9Sstevel@tonic-gate 				continue;
8647c478bd9Sstevel@tonic-gate 			case 'D':
8657c478bd9Sstevel@tonic-gate 				io_fdisk++;
8667c478bd9Sstevel@tonic-gate 				io_Dfdisk = optarg;
8677c478bd9Sstevel@tonic-gate 				continue;
8687c478bd9Sstevel@tonic-gate 			case 'h':
869bb16350dSlclee 				(void) fprintf(stderr, "%s\n", Usage);
870bb16350dSlclee 				(void) fprintf(stderr, "%s\n", Usage1);
8717c478bd9Sstevel@tonic-gate 				exit(0);
872bb16350dSlclee 				/* FALLTHRU */
8737c478bd9Sstevel@tonic-gate 			case 'v':
8747c478bd9Sstevel@tonic-gate 				v_flag = 1;
8757c478bd9Sstevel@tonic-gate 				continue;
8767c478bd9Sstevel@tonic-gate 			case '?':
8777c478bd9Sstevel@tonic-gate 				errflg++;
8787c478bd9Sstevel@tonic-gate 				break;
8797c478bd9Sstevel@tonic-gate 		}
8807c478bd9Sstevel@tonic-gate 		break;
8817c478bd9Sstevel@tonic-gate 	}
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 	if (io_image && io_sgeom && diag_cnt == 1) {
8847c478bd9Sstevel@tonic-gate 		diag_cnt = 0;
8857c478bd9Sstevel@tonic-gate 	}
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	/* User option checking */
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate 	/* By default, run in interactive mode */
8907c478bd9Sstevel@tonic-gate 	if (!io_fdisk && !diag_cnt && !io_nifdisk) {
8917c478bd9Sstevel@tonic-gate 		io_ifdisk++;
8927c478bd9Sstevel@tonic-gate 		io_fdisk++;
8937c478bd9Sstevel@tonic-gate 	}
8947c478bd9Sstevel@tonic-gate 	if (((io_fdisk || io_adjt) && diag_cnt) || (diag_cnt > 1)) {
8957c478bd9Sstevel@tonic-gate 		errflg++;
8967c478bd9Sstevel@tonic-gate 	}
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 	/* Was any error detected? */
8997c478bd9Sstevel@tonic-gate 	if (errflg || argc == optind) {
900bb16350dSlclee 		(void) fprintf(stderr, "%s\n", Usage);
901bb16350dSlclee 		(void) fprintf(stderr,
9027c478bd9Sstevel@tonic-gate 		    "\nDetailed help is available with the -h option.\n");
9037c478bd9Sstevel@tonic-gate 		exit(2);
9047c478bd9Sstevel@tonic-gate 	}
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 	/* Figure out the correct device node to open */
9087c478bd9Sstevel@tonic-gate 	Dfltdev = get_node(argv[optind]);
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate 	if (io_readonly)
9117c478bd9Sstevel@tonic-gate 		openmode = O_RDONLY;
9127c478bd9Sstevel@tonic-gate 	else
9137c478bd9Sstevel@tonic-gate 		openmode = O_RDWR|O_CREAT;
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 	if ((Dev = open(Dfltdev, openmode, 0666)) == -1) {
916bb16350dSlclee 		(void) fprintf(stderr,
917bb16350dSlclee 		    "fdisk: Cannot open device %s.\n",
918bb16350dSlclee 		    Dfltdev);
9197c478bd9Sstevel@tonic-gate 		exit(1);
9207c478bd9Sstevel@tonic-gate 	}
9211237e847Slclee 	/*
9221237e847Slclee 	 * not all disk (or disklike) drivers support DKIOCGMEDIAINFO
9231237e847Slclee 	 * in that case leave the minfo structure zeroed
9241237e847Slclee 	 */
9251237e847Slclee 	if (ioctl(Dev, DKIOCGMEDIAINFO, &minfo)) {
92665908c77Syu, larry liu - Sun Microsystems - Beijing China 		(void) memset(&minfo, 0, sizeof (minfo));
9271237e847Slclee 	}
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 	/* Get the disk geometry */
9307c478bd9Sstevel@tonic-gate 	if (!io_image) {
9317c478bd9Sstevel@tonic-gate 		/* Get disk's HBA (virtual) geometry */
9327c478bd9Sstevel@tonic-gate 		errno = 0;
9337c478bd9Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCG_VIRTGEOM, &disk_geom)) {
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 			/*
9367c478bd9Sstevel@tonic-gate 			 * If ioctl isn't implemented on this platform, then
9377c478bd9Sstevel@tonic-gate 			 * turn off flag to print out virtual geometry (-v),
9387c478bd9Sstevel@tonic-gate 			 * otherwise use the virtual geometry.
9397c478bd9Sstevel@tonic-gate 			 */
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 			if (errno == ENOTTY) {
9427c478bd9Sstevel@tonic-gate 				v_flag = 0;
9437c478bd9Sstevel@tonic-gate 				no_virtgeom_ioctl = 1;
9447c478bd9Sstevel@tonic-gate 			} else if (errno == EINVAL) {
9457c478bd9Sstevel@tonic-gate 				/*
9467c478bd9Sstevel@tonic-gate 				 * This means that the ioctl exists, but
9477c478bd9Sstevel@tonic-gate 				 * is invalid for this disk, meaning the
9487c478bd9Sstevel@tonic-gate 				 * disk doesn't have an HBA geometry
9497c478bd9Sstevel@tonic-gate 				 * (like, say, it's larger than 8GB).
9507c478bd9Sstevel@tonic-gate 				 */
9517c478bd9Sstevel@tonic-gate 				v_flag = 0;
9527c478bd9Sstevel@tonic-gate 				hba_Numcyl = hba_heads = hba_sectors = 0;
9537c478bd9Sstevel@tonic-gate 			} else {
9547c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
9557c478bd9Sstevel@tonic-gate 				    "%s: Cannot get virtual disk geometry.\n",
9567c478bd9Sstevel@tonic-gate 				    argv[optind]);
9577c478bd9Sstevel@tonic-gate 				exit(1);
9587c478bd9Sstevel@tonic-gate 			}
9597c478bd9Sstevel@tonic-gate 		} else {
9607c478bd9Sstevel@tonic-gate 			/* save virtual geometry values obtained by ioctl */
9617c478bd9Sstevel@tonic-gate 			hba_Numcyl = disk_geom.dkg_ncyl;
9627c478bd9Sstevel@tonic-gate 			hba_heads = disk_geom.dkg_nhead;
9637c478bd9Sstevel@tonic-gate 			hba_sectors = disk_geom.dkg_nsect;
9647c478bd9Sstevel@tonic-gate 		}
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 		errno = 0;
9677c478bd9Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCG_PHYGEOM, &disk_geom)) {
9687c478bd9Sstevel@tonic-gate 			if (errno == ENOTTY) {
9697c478bd9Sstevel@tonic-gate 				no_physgeom_ioctl = 1;
9707c478bd9Sstevel@tonic-gate 			} else {
9717c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
9727c478bd9Sstevel@tonic-gate 				    "%s: Cannot get physical disk geometry.\n",
9737c478bd9Sstevel@tonic-gate 				    argv[optind]);
9747c478bd9Sstevel@tonic-gate 				exit(1);
9757c478bd9Sstevel@tonic-gate 			}
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 		}
9787c478bd9Sstevel@tonic-gate 		/*
9797c478bd9Sstevel@tonic-gate 		 * Call DKIOCGGEOM if the ioctls for physical and virtual
9807c478bd9Sstevel@tonic-gate 		 * geometry fail. Get both from this generic call.
9817c478bd9Sstevel@tonic-gate 		 */
9827c478bd9Sstevel@tonic-gate 		if (no_virtgeom_ioctl && no_physgeom_ioctl) {
9837c478bd9Sstevel@tonic-gate 			errno = 0;
9847c478bd9Sstevel@tonic-gate 			if (ioctl(Dev, DKIOCGGEOM, &disk_geom)) {
9857c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
9867c478bd9Sstevel@tonic-gate 				    "%s: Cannot get disk label geometry.\n",
9877c478bd9Sstevel@tonic-gate 				    argv[optind]);
9887c478bd9Sstevel@tonic-gate 				exit(1);
9897c478bd9Sstevel@tonic-gate 			}
9907c478bd9Sstevel@tonic-gate 		}
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate 		Numcyl = disk_geom.dkg_ncyl;
9937c478bd9Sstevel@tonic-gate 		heads = disk_geom.dkg_nhead;
9947c478bd9Sstevel@tonic-gate 		sectors = disk_geom.dkg_nsect;
99565908c77Syu, larry liu - Sun Microsystems - Beijing China 
99665908c77Syu, larry liu - Sun Microsystems - Beijing China 		if (minfo.dki_lbsize != 0)
99765908c77Syu, larry liu - Sun Microsystems - Beijing China 			sectsiz = minfo.dki_lbsize;
99865908c77Syu, larry liu - Sun Microsystems - Beijing China 		else
99965908c77Syu, larry liu - Sun Microsystems - Beijing China 			sectsiz = 512;
100065908c77Syu, larry liu - Sun Microsystems - Beijing China 
10017c478bd9Sstevel@tonic-gate 		acyl = disk_geom.dkg_acyl;
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 		/*
10047c478bd9Sstevel@tonic-gate 		 * if hba geometry was not set by DKIOC_VIRTGEOM
10057c478bd9Sstevel@tonic-gate 		 * or we got an invalid hba geometry
10067c478bd9Sstevel@tonic-gate 		 * then set hba geometry based on max values
10077c478bd9Sstevel@tonic-gate 		 */
10087c478bd9Sstevel@tonic-gate 		if (no_virtgeom_ioctl ||
1009bb16350dSlclee 		    disk_geom.dkg_ncyl == 0 ||
1010bb16350dSlclee 		    disk_geom.dkg_nhead == 0 ||
1011bb16350dSlclee 		    disk_geom.dkg_nsect == 0 ||
10127c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_ncyl > MAX_CYL ||
10137c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_nhead > MAX_HEAD ||
10147c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_nsect > MAX_SECT) {
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 			/*
10177c478bd9Sstevel@tonic-gate 			 * turn off flag to print out virtual geometry (-v)
10187c478bd9Sstevel@tonic-gate 			 */
10197c478bd9Sstevel@tonic-gate 			v_flag = 0;
10207c478bd9Sstevel@tonic-gate 			hba_sectors	= MAX_SECT;
10217c478bd9Sstevel@tonic-gate 			hba_heads	= MAX_HEAD + 1;
10227c478bd9Sstevel@tonic-gate 			hba_Numcyl	= (Numcyl * heads * sectors) /
10237c478bd9Sstevel@tonic-gate 			    (hba_sectors * hba_heads);
10247c478bd9Sstevel@tonic-gate 		}
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate 		if (io_debug) {
1027bb16350dSlclee 			(void) fprintf(stderr, "Physical Geometry:\n");
1028bb16350dSlclee 			(void) fprintf(stderr,
10297c478bd9Sstevel@tonic-gate 			    "  cylinders[%d] heads[%d] sectors[%d]\n"
10307c478bd9Sstevel@tonic-gate 			    "  sector size[%d] blocks[%d] mbytes[%d]\n",
10317c478bd9Sstevel@tonic-gate 			    Numcyl,
10327c478bd9Sstevel@tonic-gate 			    heads,
10337c478bd9Sstevel@tonic-gate 			    sectors,
10347c478bd9Sstevel@tonic-gate 			    sectsiz,
1035bb16350dSlclee 			    Numcyl * heads * sectors,
1036bb16350dSlclee 			    (Numcyl * heads * sectors * sectsiz) / 1048576);
1037bb16350dSlclee 			(void) fprintf(stderr, "Virtual (HBA) Geometry:\n");
1038bb16350dSlclee 			(void) fprintf(stderr,
10397c478bd9Sstevel@tonic-gate 			    "  cylinders[%d] heads[%d] sectors[%d]\n"
10407c478bd9Sstevel@tonic-gate 			    "  sector size[%d] blocks[%d] mbytes[%d]\n",
10417c478bd9Sstevel@tonic-gate 			    hba_Numcyl,
10427c478bd9Sstevel@tonic-gate 			    hba_heads,
10437c478bd9Sstevel@tonic-gate 			    hba_sectors,
10447c478bd9Sstevel@tonic-gate 			    sectsiz,
1045bb16350dSlclee 			    hba_Numcyl * hba_heads * hba_sectors,
1046bb16350dSlclee 			    (hba_Numcyl * hba_heads * hba_sectors * sectsiz) /
1047bb16350dSlclee 			    1048576);
10487c478bd9Sstevel@tonic-gate 		}
10497c478bd9Sstevel@tonic-gate 	}
10507c478bd9Sstevel@tonic-gate 
10517c478bd9Sstevel@tonic-gate 	/* If user has requested a geometry report just do it and exit */
10527c478bd9Sstevel@tonic-gate 	if (io_lgeom) {
10537c478bd9Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCGGEOM, &disk_geom)) {
10547c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
10557c478bd9Sstevel@tonic-gate 			    "%s: Cannot get disk label geometry.\n",
10567c478bd9Sstevel@tonic-gate 			    argv[optind]);
10577c478bd9Sstevel@tonic-gate 			exit(1);
10587c478bd9Sstevel@tonic-gate 		}
10597c478bd9Sstevel@tonic-gate 		Numcyl = disk_geom.dkg_ncyl;
10607c478bd9Sstevel@tonic-gate 		heads = disk_geom.dkg_nhead;
10617c478bd9Sstevel@tonic-gate 		sectors = disk_geom.dkg_nsect;
106265908c77Syu, larry liu - Sun Microsystems - Beijing China 		if (minfo.dki_lbsize != 0)
106365908c77Syu, larry liu - Sun Microsystems - Beijing China 			sectsiz = minfo.dki_lbsize;
106465908c77Syu, larry liu - Sun Microsystems - Beijing China 		else
106565908c77Syu, larry liu - Sun Microsystems - Beijing China 			sectsiz = 512;
106665908c77Syu, larry liu - Sun Microsystems - Beijing China 
10677c478bd9Sstevel@tonic-gate 		acyl = disk_geom.dkg_acyl;
1068bb16350dSlclee 		(void) printf("* Label geometry for device %s\n", Dfltdev);
1069bb16350dSlclee 		(void) printf(
1070bb16350dSlclee 		    "* PCYL     NCYL     ACYL     BCYL     NHEAD NSECT"
10717c478bd9Sstevel@tonic-gate 		    " SECSIZ\n");
1072bb16350dSlclee 		(void) printf("  %-8d %-8d %-8d %-8d %-5d %-5d %-6d\n",
10737c478bd9Sstevel@tonic-gate 		    Numcyl,
10747c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_ncyl,
10757c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_acyl,
10767c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_bcyl,
10777c478bd9Sstevel@tonic-gate 		    heads,
10787c478bd9Sstevel@tonic-gate 		    sectors,
10797c478bd9Sstevel@tonic-gate 		    sectsiz);
10807c478bd9Sstevel@tonic-gate 		exit(0);
10817c478bd9Sstevel@tonic-gate 	} else if (io_pgeom) {
10827c478bd9Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCG_PHYGEOM, &disk_geom)) {
10837c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
10847c478bd9Sstevel@tonic-gate 			    "%s: Cannot get physical disk geometry.\n",
10857c478bd9Sstevel@tonic-gate 			    argv[optind]);
10867c478bd9Sstevel@tonic-gate 			exit(1);
10877c478bd9Sstevel@tonic-gate 		}
1088bb16350dSlclee 		(void) printf("* Physical geometry for device %s\n", Dfltdev);
1089bb16350dSlclee 		(void) printf(
1090bb16350dSlclee 		    "* PCYL     NCYL     ACYL     BCYL     NHEAD NSECT"
10917c478bd9Sstevel@tonic-gate 		    " SECSIZ\n");
1092bb16350dSlclee 		(void) printf("  %-8d %-8d %-8d %-8d %-5d %-5d %-6d\n",
10937c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_pcyl,
10947c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_ncyl,
10957c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_acyl,
10967c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_bcyl,
10977c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_nhead,
10987c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_nsect,
10997c478bd9Sstevel@tonic-gate 		    sectsiz);
11007c478bd9Sstevel@tonic-gate 		exit(0);
11017c478bd9Sstevel@tonic-gate 	} else if (io_sgeom) {
11027c478bd9Sstevel@tonic-gate 		if (read_geom(io_sgeom)) {
11037c478bd9Sstevel@tonic-gate 			exit(1);
11047c478bd9Sstevel@tonic-gate 		} else if (!io_image) {
11057c478bd9Sstevel@tonic-gate 			exit(0);
11067c478bd9Sstevel@tonic-gate 		}
11077c478bd9Sstevel@tonic-gate 	}
11087c478bd9Sstevel@tonic-gate 
11091237e847Slclee 	/*
11101237e847Slclee 	 * some drivers may not support DKIOCGMEDIAINFO
11111237e847Slclee 	 * in that case use CHS
11121237e847Slclee 	 */
1113342440ecSPrasad Singamsetty 	chs_capacity = (diskaddr_t)Numcyl * heads * sectors;
11141237e847Slclee 	dev_capacity = chs_capacity;
1115342440ecSPrasad Singamsetty 	Numcyl_usable = Numcyl;
1116342440ecSPrasad Singamsetty 
1117342440ecSPrasad Singamsetty 	if (chs_capacity > DK_MAX_2TB) {
1118342440ecSPrasad Singamsetty 		/* limit to 2TB */
1119342440ecSPrasad Singamsetty 		Numcyl_usable = DK_MAX_2TB / (heads * sectors);
1120342440ecSPrasad Singamsetty 		chs_capacity = (diskaddr_t)Numcyl_usable * heads * sectors;
1121342440ecSPrasad Singamsetty 	}
1122342440ecSPrasad Singamsetty 
11231237e847Slclee 	if (minfo.dki_capacity > 0)
11241237e847Slclee 		dev_capacity = minfo.dki_capacity;
11251237e847Slclee 
11267c478bd9Sstevel@tonic-gate 	/* Allocate memory to hold three complete sectors */
112765908c77Syu, larry liu - Sun Microsystems - Beijing China 	Bootsect = (char *)calloc(3 * sectsiz, 1);
11287c478bd9Sstevel@tonic-gate 	if (Bootsect == NULL) {
1129bb16350dSlclee 		(void) fprintf(stderr,
11307c478bd9Sstevel@tonic-gate 		    "fdisk: Unable to obtain enough buffer memory"
11317c478bd9Sstevel@tonic-gate 		    " (%d bytes).\n",
1132bb16350dSlclee 		    3 * sectsiz);
11337c478bd9Sstevel@tonic-gate 		exit(1);
11347c478bd9Sstevel@tonic-gate 	}
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate 	Nullsect = Bootsect + sectsiz;
11377c478bd9Sstevel@tonic-gate 	/* Zero out the "NULL" sector */
11387c478bd9Sstevel@tonic-gate 	for (i = 0; i < sectsiz; i++) {
11397c478bd9Sstevel@tonic-gate 		Nullsect[i] = 0;
11407c478bd9Sstevel@tonic-gate 	}
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate 	/* Find out what the user wants done */
11437c478bd9Sstevel@tonic-gate 	if (io_rd) {		/* abs disk read */
11447c478bd9Sstevel@tonic-gate 		abs_read();	/* will not return */
11457c478bd9Sstevel@tonic-gate 	} else if (io_wrt && !io_readonly) {
11467c478bd9Sstevel@tonic-gate 		abs_write();	/* will not return */
11477c478bd9Sstevel@tonic-gate 	} else if (io_patt && !io_readonly) {
11487c478bd9Sstevel@tonic-gate 		fill_patt();	/* will not return */
11497c478bd9Sstevel@tonic-gate 	}
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate 	/* This is the fdisk edit, the real reason for the program.	*/
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate 	sanity_check_provided_device(Dfltdev, Dev);
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate 	/* Get the new BOOT program in case we write a new fdisk table */
11577c478bd9Sstevel@tonic-gate 	mboot_read();
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate 	/* Read from disk master boot */
11607c478bd9Sstevel@tonic-gate 	dev_mboot_read();
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 	/*
11637c478bd9Sstevel@tonic-gate 	 * Verify and copy the device's fdisk table. This will be used
11647c478bd9Sstevel@tonic-gate 	 * as the prototype mboot if the device's mboot looks invalid.
11657c478bd9Sstevel@tonic-gate 	 */
11667c478bd9Sstevel@tonic-gate 	Bootblk = (struct mboot *)Bootsect;
11677c478bd9Sstevel@tonic-gate 	copy_Bootblk_to_Table();
11687c478bd9Sstevel@tonic-gate 
11697c478bd9Sstevel@tonic-gate 	/* save away a copy of Table in Old_Table for sensing changes */
11707c478bd9Sstevel@tonic-gate 	copy_Table_to_Old_Table();
11717c478bd9Sstevel@tonic-gate 
1172*aa1b14e7SSheshadri Vasudevan #ifdef i386
1173*aa1b14e7SSheshadri Vasudevan 	/*
1174*aa1b14e7SSheshadri Vasudevan 	 * Read extended partition only when the fdisk table is not
1175*aa1b14e7SSheshadri Vasudevan 	 * supplied from a file
1176*aa1b14e7SSheshadri Vasudevan 	 */
1177*aa1b14e7SSheshadri Vasudevan 	if (!io_ffdisk) {
1178*aa1b14e7SSheshadri Vasudevan 		lf_op_flag |= FDISK_READ_DISK;
1179*aa1b14e7SSheshadri Vasudevan 	}
1180*aa1b14e7SSheshadri Vasudevan 	if ((rval = libfdisk_init(&epp, Dfltdev, &Table[0], lf_op_flag))
1181*aa1b14e7SSheshadri Vasudevan 	    != FDISK_SUCCESS) {
1182*aa1b14e7SSheshadri Vasudevan 		switch (rval) {
1183*aa1b14e7SSheshadri Vasudevan 			/*
1184*aa1b14e7SSheshadri Vasudevan 			 * FDISK_EBADLOGDRIVE and FDISK_ENOLOGDRIVE can
1185*aa1b14e7SSheshadri Vasudevan 			 * be considered as soft errors and hence
1186*aa1b14e7SSheshadri Vasudevan 			 * we do not exit
1187*aa1b14e7SSheshadri Vasudevan 			 */
1188*aa1b14e7SSheshadri Vasudevan 			case FDISK_EBADLOGDRIVE:
1189*aa1b14e7SSheshadri Vasudevan 				break;
1190*aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOLOGDRIVE:
1191*aa1b14e7SSheshadri Vasudevan 				break;
1192*aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOVGEOM:
1193*aa1b14e7SSheshadri Vasudevan 				fprintf(stderr, "Could not get virtual"
1194*aa1b14e7SSheshadri Vasudevan 				    " geometry for this device\n");
1195*aa1b14e7SSheshadri Vasudevan 				exit(1);
1196*aa1b14e7SSheshadri Vasudevan 				break;
1197*aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOPGEOM:
1198*aa1b14e7SSheshadri Vasudevan 				fprintf(stderr, "Could not get physical"
1199*aa1b14e7SSheshadri Vasudevan 				    " geometry for this device\n");
1200*aa1b14e7SSheshadri Vasudevan 				exit(1);
1201*aa1b14e7SSheshadri Vasudevan 				break;
1202*aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOLGEOM:
1203*aa1b14e7SSheshadri Vasudevan 				fprintf(stderr, "Could not get label"
1204*aa1b14e7SSheshadri Vasudevan 				    " geometry for this device\n");
1205*aa1b14e7SSheshadri Vasudevan 				exit(1);
1206*aa1b14e7SSheshadri Vasudevan 				break;
1207*aa1b14e7SSheshadri Vasudevan 			default:
1208*aa1b14e7SSheshadri Vasudevan 				perror("Failed to initialise libfdisk.\n");
1209*aa1b14e7SSheshadri Vasudevan 				exit(1);
1210*aa1b14e7SSheshadri Vasudevan 				break;
1211*aa1b14e7SSheshadri Vasudevan 		}
1212*aa1b14e7SSheshadri Vasudevan 	}
1213*aa1b14e7SSheshadri Vasudevan #endif
1214*aa1b14e7SSheshadri Vasudevan 
12157c478bd9Sstevel@tonic-gate 	/* Load fdisk table from specified file (-F fdisk_file) */
12167c478bd9Sstevel@tonic-gate 	if (io_ffdisk) {
12177c478bd9Sstevel@tonic-gate 		/* Load and verify user-specified table parameters */
12187c478bd9Sstevel@tonic-gate 		load(LOADFILE, io_ffdisk);
12197c478bd9Sstevel@tonic-gate 	}
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate 	/* Does user want to delete or add an entry? */
12227c478bd9Sstevel@tonic-gate 	if (io_Dfdisk) {
12237c478bd9Sstevel@tonic-gate 		load(LOADDEL, io_Dfdisk);
12247c478bd9Sstevel@tonic-gate 	}
12257c478bd9Sstevel@tonic-gate 	if (io_Afdisk) {
12267c478bd9Sstevel@tonic-gate 		load(LOADADD, io_Afdisk);
12277c478bd9Sstevel@tonic-gate 	}
12287c478bd9Sstevel@tonic-gate 
12297c478bd9Sstevel@tonic-gate 	if (!io_ffdisk && !io_Afdisk && !io_Dfdisk) {
12307c478bd9Sstevel@tonic-gate 		/* Check if there is no fdisk table */
12317c478bd9Sstevel@tonic-gate 		if (Table[0].systid == UNUSED || io_wholedisk || io_EFIdisk) {
12327c478bd9Sstevel@tonic-gate 			if (io_ifdisk && !io_wholedisk && !io_EFIdisk) {
1233bb16350dSlclee 				(void) printf(
1234bb16350dSlclee 				    "No fdisk table exists. The default"
1235bb16350dSlclee 				    " partition for the disk is:\n\n"
1236bb16350dSlclee 				    "  a 100%% \"SOLARIS System\" "
1237bb16350dSlclee 				    "partition\n\n"
1238bb16350dSlclee 				    "Type \"y\" to accept the default "
12397c478bd9Sstevel@tonic-gate 				    "partition,  otherwise type \"n\" to "
12407c478bd9Sstevel@tonic-gate 				    "edit the\n partition table.\n");
1241342440ecSPrasad Singamsetty 
1242342440ecSPrasad Singamsetty 				if (Numcyl > Numcyl_usable)
1243342440ecSPrasad Singamsetty 					(void) printf("WARNING: Disk is larger"
1244342440ecSPrasad Singamsetty 					    " than 2TB. Solaris partition will"
1245342440ecSPrasad Singamsetty 					    " be limited to 2 TB.\n");
12467c478bd9Sstevel@tonic-gate 			}
12477c478bd9Sstevel@tonic-gate 
12487c478bd9Sstevel@tonic-gate 			/* Edit the partition table as directed */
12497c478bd9Sstevel@tonic-gate 			if (io_wholedisk ||(io_ifdisk && yesno())) {
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 				/* Default scenario */
12527c478bd9Sstevel@tonic-gate 				nulltbl();
12537c478bd9Sstevel@tonic-gate 				/* now set up UNIX System partition */
12547c478bd9Sstevel@tonic-gate 				Table[0].bootid = ACTIVE;
1255*aa1b14e7SSheshadri Vasudevan 				Table[0].relsect = LE_32(heads * sectors);
1256342440ecSPrasad Singamsetty 
1257342440ecSPrasad Singamsetty 				Table[0].numsect =
1258*aa1b14e7SSheshadri Vasudevan 				    LE_32((ulong_t)((Numcyl_usable - 1) *
12597c478bd9Sstevel@tonic-gate 				    heads * sectors));
1260342440ecSPrasad Singamsetty 
12617c478bd9Sstevel@tonic-gate 				Table[0].systid = SUNIXOS2;   /* Solaris */
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate 				/* calculate CHS values for table entry 0 */
12647c478bd9Sstevel@tonic-gate 				Set_Table_CHS_Values(0);
12657c478bd9Sstevel@tonic-gate 				update_disk_and_exit(B_TRUE);
12667c478bd9Sstevel@tonic-gate 			} else if (io_EFIdisk) {
12677c478bd9Sstevel@tonic-gate 				/* create an EFI partition for the whole disk */
12687c478bd9Sstevel@tonic-gate 				nulltbl();
12697c478bd9Sstevel@tonic-gate 				i = insert_tbl(EFI_PMBR, 0, 0, 0, 0, 0, 0, 0, 1,
1270342440ecSPrasad Singamsetty 				    (dev_capacity > DK_MAX_2TB) ? DK_MAX_2TB :
1271342440ecSPrasad Singamsetty 				    (dev_capacity - 1));
12727c478bd9Sstevel@tonic-gate 				if (i != 0) {
1273bb16350dSlclee 					(void) fprintf(stderr,
1274bb16350dSlclee 					    "Error creating EFI partition\n");
12757c478bd9Sstevel@tonic-gate 					exit(1);
12767c478bd9Sstevel@tonic-gate 				}
12777c478bd9Sstevel@tonic-gate 				update_disk_and_exit(B_TRUE);
12787c478bd9Sstevel@tonic-gate 			}
12797c478bd9Sstevel@tonic-gate 		}
12807c478bd9Sstevel@tonic-gate 	}
12817c478bd9Sstevel@tonic-gate 
12827c478bd9Sstevel@tonic-gate 	/* Display complete fdisk table entries for debugging purposes */
12837c478bd9Sstevel@tonic-gate 	if (io_debug) {
1284bb16350dSlclee 		(void) fprintf(stderr, "Partition Table Entry Values:\n");
12857c478bd9Sstevel@tonic-gate 		print_Table();
12867c478bd9Sstevel@tonic-gate 		if (io_ifdisk) {
1287bb16350dSlclee 			(void) fprintf(stderr, "\n");
1288bb16350dSlclee 			(void) fprintf(stderr, "Press Enter to continue.\n");
1289933c1499SBarry Harding 			(void) fgets(s, sizeof (s), stdin);
12907c478bd9Sstevel@tonic-gate 		}
12917c478bd9Sstevel@tonic-gate 	}
12927c478bd9Sstevel@tonic-gate 
12937c478bd9Sstevel@tonic-gate 	/* Interactive fdisk mode */
12947c478bd9Sstevel@tonic-gate 	if (io_ifdisk) {
1295bb16350dSlclee 		(void) printf(CLR_SCR);
12967c478bd9Sstevel@tonic-gate 		disptbl();
1297bb16350dSlclee 		for (;;) {
1298bb16350dSlclee 			stage0();
12997c478bd9Sstevel@tonic-gate 			copy_Bootblk_to_Table();
13007c478bd9Sstevel@tonic-gate 			disptbl();
13017c478bd9Sstevel@tonic-gate 		}
13027c478bd9Sstevel@tonic-gate 	}
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 	/* If user wants to write the table to a file, do it */
13057c478bd9Sstevel@tonic-gate 	if (io_Wfdisk)
13067c478bd9Sstevel@tonic-gate 		ffile_write(io_Wfdisk);
13077c478bd9Sstevel@tonic-gate 	else if (stdo_flag)
13087c478bd9Sstevel@tonic-gate 		ffile_write((char *)stdout);
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 	update_disk_and_exit(TableChanged() == 1);
1311bb16350dSlclee 	return (0);
13127c478bd9Sstevel@tonic-gate }
13137c478bd9Sstevel@tonic-gate 
13147c478bd9Sstevel@tonic-gate /*
13157c478bd9Sstevel@tonic-gate  * read_geom
13167c478bd9Sstevel@tonic-gate  * Read geometry from specified file (-S).
13177c478bd9Sstevel@tonic-gate  */
13187c478bd9Sstevel@tonic-gate 
1319bb16350dSlclee static int
1320bb16350dSlclee read_geom(char *sgeom)
13217c478bd9Sstevel@tonic-gate {
13227c478bd9Sstevel@tonic-gate 	char	line[256];
13237c478bd9Sstevel@tonic-gate 	FILE *fp;
13247c478bd9Sstevel@tonic-gate 
13257c478bd9Sstevel@tonic-gate 	/* open the prototype file */
13267c478bd9Sstevel@tonic-gate 	if ((fp = fopen(sgeom, "r")) == NULL) {
13277c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "fdisk: Cannot open file %s.\n",
13287c478bd9Sstevel@tonic-gate 		    io_sgeom);
13297c478bd9Sstevel@tonic-gate 		return (1);
13307c478bd9Sstevel@tonic-gate 	}
13317c478bd9Sstevel@tonic-gate 
13327c478bd9Sstevel@tonic-gate 	/* Read a line from the file */
13337c478bd9Sstevel@tonic-gate 	while (fgets(line, sizeof (line) - 1, fp)) {
13347c478bd9Sstevel@tonic-gate 		if (line[0] == '\0' || line[0] == '\n' || line[0] == '*')
13357c478bd9Sstevel@tonic-gate 			continue;
13367c478bd9Sstevel@tonic-gate 		else {
13377c478bd9Sstevel@tonic-gate 			line[strlen(line)] = '\0';
1338bb16350dSlclee 			if (sscanf(line, "%hu %hu %hu %hu %hu %hu %d",
13397c478bd9Sstevel@tonic-gate 			    &disk_geom.dkg_pcyl,
13407c478bd9Sstevel@tonic-gate 			    &disk_geom.dkg_ncyl,
13417c478bd9Sstevel@tonic-gate 			    &disk_geom.dkg_acyl,
13427c478bd9Sstevel@tonic-gate 			    &disk_geom.dkg_bcyl,
13437c478bd9Sstevel@tonic-gate 			    &disk_geom.dkg_nhead,
13447c478bd9Sstevel@tonic-gate 			    &disk_geom.dkg_nsect,
13457c478bd9Sstevel@tonic-gate 			    &sectsiz) != 7) {
13467c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
13477c478bd9Sstevel@tonic-gate 				    "Syntax error:\n	\"%s\".\n",
13487c478bd9Sstevel@tonic-gate 				    line);
13497c478bd9Sstevel@tonic-gate 				return (1);
13507c478bd9Sstevel@tonic-gate 			}
13517c478bd9Sstevel@tonic-gate 			break;
13527c478bd9Sstevel@tonic-gate 		} /* else */
13537c478bd9Sstevel@tonic-gate 	} /* while (fgets(line, sizeof (line) - 1, fp)) */
13547c478bd9Sstevel@tonic-gate 
13557c478bd9Sstevel@tonic-gate 	if (!io_image) {
13567c478bd9Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCSGEOM, &disk_geom)) {
13577c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
13587c478bd9Sstevel@tonic-gate 			    "fdisk: Cannot set label geometry.\n");
13597c478bd9Sstevel@tonic-gate 			return (1);
13607c478bd9Sstevel@tonic-gate 		}
13617c478bd9Sstevel@tonic-gate 	} else {
13627c478bd9Sstevel@tonic-gate 		Numcyl = hba_Numcyl = disk_geom.dkg_ncyl;
13637c478bd9Sstevel@tonic-gate 		heads = hba_heads = disk_geom.dkg_nhead;
13647c478bd9Sstevel@tonic-gate 		sectors = hba_sectors = disk_geom.dkg_nsect;
13657c478bd9Sstevel@tonic-gate 		acyl = disk_geom.dkg_acyl;
13667c478bd9Sstevel@tonic-gate 	}
13677c478bd9Sstevel@tonic-gate 
1368bb16350dSlclee 	(void) fclose(fp);
13697c478bd9Sstevel@tonic-gate 	return (0);
13707c478bd9Sstevel@tonic-gate }
13717c478bd9Sstevel@tonic-gate 
13727c478bd9Sstevel@tonic-gate /*
13737c478bd9Sstevel@tonic-gate  * dev_mboot_read
13747c478bd9Sstevel@tonic-gate  * Read the master boot sector from the device.
13757c478bd9Sstevel@tonic-gate  */
1376bb16350dSlclee static void
1377bb16350dSlclee dev_mboot_read(void)
13787c478bd9Sstevel@tonic-gate {
13797c478bd9Sstevel@tonic-gate 	if ((ioctl(Dev, DKIOCGMBOOT, Bootsect) < 0) && (errno != ENOTTY)) {
13807c478bd9Sstevel@tonic-gate 		perror("Error in ioctl DKIOCGMBOOT");
13817c478bd9Sstevel@tonic-gate 	}
13827c478bd9Sstevel@tonic-gate 	if (errno == 0)
13837c478bd9Sstevel@tonic-gate 		return;
13847c478bd9Sstevel@tonic-gate 	if (lseek(Dev, 0, SEEK_SET) == -1) {
1385bb16350dSlclee 		(void) fprintf(stderr,
13867c478bd9Sstevel@tonic-gate 		    "fdisk: Error seeking to partition table on %s.\n",
13877c478bd9Sstevel@tonic-gate 		    Dfltdev);
13887c478bd9Sstevel@tonic-gate 		if (!io_image)
13897c478bd9Sstevel@tonic-gate 			exit(1);
13907c478bd9Sstevel@tonic-gate 	}
13917c478bd9Sstevel@tonic-gate 	if (read(Dev, Bootsect, sectsiz) != sectsiz) {
1392bb16350dSlclee 		(void) fprintf(stderr,
13937c478bd9Sstevel@tonic-gate 		    "fdisk: Error reading partition table from %s.\n",
13947c478bd9Sstevel@tonic-gate 		    Dfltdev);
13957c478bd9Sstevel@tonic-gate 		if (!io_image)
13967c478bd9Sstevel@tonic-gate 			exit(1);
13977c478bd9Sstevel@tonic-gate 	}
13987c478bd9Sstevel@tonic-gate }
13997c478bd9Sstevel@tonic-gate 
14007c478bd9Sstevel@tonic-gate /*
14017c478bd9Sstevel@tonic-gate  * dev_mboot_write
14027c478bd9Sstevel@tonic-gate  * Write the master boot sector to the device.
14037c478bd9Sstevel@tonic-gate  */
1404bb16350dSlclee static void
14059d5d1945Sbharding dev_mboot_write(off_t sect, char *buff, int bootsiz)
14067c478bd9Sstevel@tonic-gate {
14077c478bd9Sstevel@tonic-gate 	int 	new_pt, old_pt, error;
1408a4a653edSbharding 	int	clr_efi = -1;
14097c478bd9Sstevel@tonic-gate 
14107c478bd9Sstevel@tonic-gate 	if (io_readonly)
1411bb16350dSlclee 		return;
14127c478bd9Sstevel@tonic-gate 
14137c478bd9Sstevel@tonic-gate 	if (io_debug) {
1414bb16350dSlclee 		(void) fprintf(stderr, "About to write fdisk table:\n");
14157c478bd9Sstevel@tonic-gate 		print_Table();
14167c478bd9Sstevel@tonic-gate 		if (io_ifdisk) {
1417bb16350dSlclee 			(void) fprintf(stderr, "Press Enter to continue.\n");
1418933c1499SBarry Harding 			(void) fgets(s, sizeof (s), stdin);
14197c478bd9Sstevel@tonic-gate 		}
14207c478bd9Sstevel@tonic-gate 	}
14217c478bd9Sstevel@tonic-gate 
1422a4a653edSbharding 	/*
1423a4a653edSbharding 	 * If the new table has any Solaris partitions and the old
1424a4a653edSbharding 	 * table does not have an entry that describes it
1425a4a653edSbharding 	 * exactly then clear the old vtoc (if any).
1426a4a653edSbharding 	 */
14277c478bd9Sstevel@tonic-gate 	for (new_pt = 0; new_pt < FD_NUMPART; new_pt++) {
14287c478bd9Sstevel@tonic-gate 
1429a4a653edSbharding 		/* We only care about potential Solaris parts. */
14307c478bd9Sstevel@tonic-gate 		if (Table[new_pt].systid != SUNIXOS &&
14317c478bd9Sstevel@tonic-gate 		    Table[new_pt].systid != SUNIXOS2)
14327c478bd9Sstevel@tonic-gate 			continue;
14337c478bd9Sstevel@tonic-gate 
1434*aa1b14e7SSheshadri Vasudevan #ifdef i386
1435*aa1b14e7SSheshadri Vasudevan 
1436*aa1b14e7SSheshadri Vasudevan 		/*
1437*aa1b14e7SSheshadri Vasudevan 		 * Check if a solaris old partition is there in the new table.
1438*aa1b14e7SSheshadri Vasudevan 		 * If so, this could potentially have been a linux swap.
1439*aa1b14e7SSheshadri Vasudevan 		 * Check to see if the linux swap magic is there, and destroy
1440*aa1b14e7SSheshadri Vasudevan 		 * the magic if there is one.
1441*aa1b14e7SSheshadri Vasudevan 		 */
1442*aa1b14e7SSheshadri Vasudevan 		if (Table[new_pt].systid == SUNIXOS) {
1443*aa1b14e7SSheshadri Vasudevan 			off_t lsmo;
1444*aa1b14e7SSheshadri Vasudevan 			char *lsm_buf;
1445*aa1b14e7SSheshadri Vasudevan 
1446*aa1b14e7SSheshadri Vasudevan 			if ((lsm_buf = calloc(1, sectsiz)) == NULL) {
1447*aa1b14e7SSheshadri Vasudevan 				fprintf(stderr, "Could not allocate memory\n");
1448*aa1b14e7SSheshadri Vasudevan 				exit(1);
1449*aa1b14e7SSheshadri Vasudevan 			}
1450*aa1b14e7SSheshadri Vasudevan 
1451*aa1b14e7SSheshadri Vasudevan 			if (is_linux_swap(Table[new_pt].relsect, &lsmo) == 0) {
1452*aa1b14e7SSheshadri Vasudevan 				if (lseek(Dev, lsmo, SEEK_SET) < 0) {
1453*aa1b14e7SSheshadri Vasudevan 					fprintf(stderr, "Error seeking on "
1454*aa1b14e7SSheshadri Vasudevan 					    "%s\n", Dfltdev);
1455*aa1b14e7SSheshadri Vasudevan 					exit(1);
1456*aa1b14e7SSheshadri Vasudevan 				}
1457*aa1b14e7SSheshadri Vasudevan 
1458*aa1b14e7SSheshadri Vasudevan 				if (read(Dev, lsm_buf, sectsiz) < sectsiz) {
1459*aa1b14e7SSheshadri Vasudevan 					fprintf(stderr, "Error reading on "
1460*aa1b14e7SSheshadri Vasudevan 					    "%s\n", Dfltdev);
1461*aa1b14e7SSheshadri Vasudevan 					exit(1);
1462*aa1b14e7SSheshadri Vasudevan 				}
1463*aa1b14e7SSheshadri Vasudevan 
1464*aa1b14e7SSheshadri Vasudevan 				bzero(lsm_buf + sectsiz -
1465*aa1b14e7SSheshadri Vasudevan 				    LINUX_SWAP_MAGIC_LENGTH,
1466*aa1b14e7SSheshadri Vasudevan 				    LINUX_SWAP_MAGIC_LENGTH);
1467*aa1b14e7SSheshadri Vasudevan 
1468*aa1b14e7SSheshadri Vasudevan 				if (lseek(Dev, lsmo, SEEK_SET) < 0) {
1469*aa1b14e7SSheshadri Vasudevan 					fprintf(stderr, "Error seeking on "
1470*aa1b14e7SSheshadri Vasudevan 					    "%s\n", Dfltdev);
1471*aa1b14e7SSheshadri Vasudevan 					exit(1);
1472*aa1b14e7SSheshadri Vasudevan 				}
1473*aa1b14e7SSheshadri Vasudevan 
1474*aa1b14e7SSheshadri Vasudevan 				if (write(Dev, lsm_buf, sectsiz) < sectsiz) {
1475*aa1b14e7SSheshadri Vasudevan 					fprintf(stderr, "Error writing on "
1476*aa1b14e7SSheshadri Vasudevan 					    "%s\n", Dfltdev);
1477*aa1b14e7SSheshadri Vasudevan 					exit(1);
1478*aa1b14e7SSheshadri Vasudevan 				}
1479*aa1b14e7SSheshadri Vasudevan 			}
1480*aa1b14e7SSheshadri Vasudevan 			free(lsm_buf);
1481*aa1b14e7SSheshadri Vasudevan 		}
1482*aa1b14e7SSheshadri Vasudevan 
1483*aa1b14e7SSheshadri Vasudevan #endif
1484*aa1b14e7SSheshadri Vasudevan 
1485a4a653edSbharding 		/* Does the old table have an exact entry for the new entry? */
1486a4a653edSbharding 		for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) {
1487a4a653edSbharding 
1488a4a653edSbharding 			/* We only care about old Solaris partitions. */
1489a4a653edSbharding 			if ((Old_Table[old_pt].systid == SUNIXOS) ||
1490a4a653edSbharding 			    (Old_Table[old_pt].systid == SUNIXOS2)) {
1491a4a653edSbharding 
1492a4a653edSbharding 				/* Is this old one the same as a new one? */
1493a4a653edSbharding 				if ((Old_Table[old_pt].relsect ==
1494a4a653edSbharding 				    Table[new_pt].relsect) &&
1495a4a653edSbharding 				    (Old_Table[old_pt].numsect ==
1496a4a653edSbharding 				    Table[new_pt].numsect))
1497a4a653edSbharding 					break; /* Yes */
1498a4a653edSbharding 			}
1499a4a653edSbharding 		}
1500a4a653edSbharding 
1501a4a653edSbharding 		/* Did a solaris partition change location or size? */
1502a4a653edSbharding 		if (old_pt >= FD_NUMPART) {
1503a4a653edSbharding 			/* Yes clear old vtoc */
1504a4a653edSbharding 			if (io_debug) {
1505a4a653edSbharding 				(void) fprintf(stderr,
1506a4a653edSbharding 				    "Clearing VTOC labels from NEW"
1507a4a653edSbharding 				    " table\n");
1508a4a653edSbharding 			}
1509a4a653edSbharding 			clear_vtoc(NEW, new_pt);
1510a4a653edSbharding 		}
1511a4a653edSbharding 	}
1512a4a653edSbharding 
1513a4a653edSbharding 
1514a4a653edSbharding 	/* see if the old table had EFI */
1515a4a653edSbharding 	for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) {
1516a4a653edSbharding 		if (Old_Table[old_pt].systid == EFI_PMBR) {
1517a4a653edSbharding 			clr_efi = old_pt;
15187c478bd9Sstevel@tonic-gate 		}
15197c478bd9Sstevel@tonic-gate 	}
15207c478bd9Sstevel@tonic-gate 
15217c478bd9Sstevel@tonic-gate 	/* look to see if a EFI partition changed in relsect/numsect */
15227c478bd9Sstevel@tonic-gate 	for (new_pt = 0; new_pt < FD_NUMPART; new_pt++) {
15237c478bd9Sstevel@tonic-gate 		if (Table[new_pt].systid != EFI_PMBR)
15247c478bd9Sstevel@tonic-gate 			continue;
15257c478bd9Sstevel@tonic-gate 		for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) {
15261237e847Slclee 			if ((Old_Table[old_pt].systid ==
15271237e847Slclee 			    Table[new_pt].systid) &&
15281237e847Slclee 			    (Old_Table[old_pt].relsect ==
15291237e847Slclee 			    Table[new_pt].relsect) &&
15301237e847Slclee 			    (Old_Table[old_pt].numsect ==
15311237e847Slclee 			    Table[new_pt].numsect))
15321237e847Slclee 				break;
15337c478bd9Sstevel@tonic-gate 		}
15347c478bd9Sstevel@tonic-gate 
15357c478bd9Sstevel@tonic-gate 		/*
15367c478bd9Sstevel@tonic-gate 		 * if EFI partition changed, set the flag to clear
15377c478bd9Sstevel@tonic-gate 		 * the EFI GPT
15387c478bd9Sstevel@tonic-gate 		 */
15397c478bd9Sstevel@tonic-gate 		if (old_pt == FD_NUMPART && Table[new_pt].begcyl != 0) {
15407c478bd9Sstevel@tonic-gate 			clr_efi = 0;
15417c478bd9Sstevel@tonic-gate 		}
15427c478bd9Sstevel@tonic-gate 		break;
15437c478bd9Sstevel@tonic-gate 	}
15447c478bd9Sstevel@tonic-gate 
15457c478bd9Sstevel@tonic-gate 	/* clear labels if necessary */
15467c478bd9Sstevel@tonic-gate 	if (clr_efi >= 0) {
15477c478bd9Sstevel@tonic-gate 		if (io_debug) {
1548bb16350dSlclee 			(void) fprintf(stderr, "Clearing EFI labels\n");
15497c478bd9Sstevel@tonic-gate 		}
15507c478bd9Sstevel@tonic-gate 		if ((error = clear_efi()) != 0) {
15517c478bd9Sstevel@tonic-gate 			if (io_debug) {
1552bb16350dSlclee 				(void) fprintf(stderr,
1553bb16350dSlclee 				    "\tError %d clearing EFI labels"
15547c478bd9Sstevel@tonic-gate 				    " (probably no EFI labels exist)\n",
15557c478bd9Sstevel@tonic-gate 				    error);
15567c478bd9Sstevel@tonic-gate 			}
15577c478bd9Sstevel@tonic-gate 		}
15587c478bd9Sstevel@tonic-gate 	}
15597c478bd9Sstevel@tonic-gate 
15607c478bd9Sstevel@tonic-gate 	if ((ioctl(Dev, DKIOCSMBOOT, buff) == -1) && (errno != ENOTTY)) {
1561bb16350dSlclee 		(void) fprintf(stderr,
15627c478bd9Sstevel@tonic-gate 		    "fdisk: Error in ioctl DKIOCSMBOOT on %s.\n",
15637c478bd9Sstevel@tonic-gate 		    Dfltdev);
15647c478bd9Sstevel@tonic-gate 	}
15657c478bd9Sstevel@tonic-gate 	if (errno == 0)
15667c478bd9Sstevel@tonic-gate 		return;
15677c478bd9Sstevel@tonic-gate 
15687c478bd9Sstevel@tonic-gate 	/* write to disk drive */
15697c478bd9Sstevel@tonic-gate 	if (lseek(Dev, sect, SEEK_SET) == -1) {
1570bb16350dSlclee 		(void) fprintf(stderr,
15717c478bd9Sstevel@tonic-gate 		    "fdisk: Error seeking to master boot record on %s.\n",
15727c478bd9Sstevel@tonic-gate 		    Dfltdev);
15737c478bd9Sstevel@tonic-gate 		exit(1);
15747c478bd9Sstevel@tonic-gate 	}
15757c478bd9Sstevel@tonic-gate 	if (write(Dev, buff, bootsiz) != bootsiz) {
1576bb16350dSlclee 		(void) fprintf(stderr,
15777c478bd9Sstevel@tonic-gate 		    "fdisk: Error writing master boot record to %s.\n",
15787c478bd9Sstevel@tonic-gate 		    Dfltdev);
15797c478bd9Sstevel@tonic-gate 		exit(1);
15807c478bd9Sstevel@tonic-gate 	}
15817c478bd9Sstevel@tonic-gate }
15827c478bd9Sstevel@tonic-gate 
15837c478bd9Sstevel@tonic-gate /*
15847c478bd9Sstevel@tonic-gate  * mboot_read
15857c478bd9Sstevel@tonic-gate  * Read the prototype boot records from the files.
15867c478bd9Sstevel@tonic-gate  */
1587bb16350dSlclee static void
1588bb16350dSlclee mboot_read(void)
15897c478bd9Sstevel@tonic-gate {
15907c478bd9Sstevel@tonic-gate 	int mDev, i;
15917c478bd9Sstevel@tonic-gate 	struct ipart *part;
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate #if defined(i386) || defined(sparc)
15947c478bd9Sstevel@tonic-gate 	/*
15957c478bd9Sstevel@tonic-gate 	 * If the master boot file hasn't been specified, use the
15967c478bd9Sstevel@tonic-gate 	 * implementation architecture name to generate the default one.
15977c478bd9Sstevel@tonic-gate 	 */
15987c478bd9Sstevel@tonic-gate 	if (io_mboot == (char *)0) {
15997c478bd9Sstevel@tonic-gate 		/*
16007c478bd9Sstevel@tonic-gate 		 * Bug ID 1249035:
16017c478bd9Sstevel@tonic-gate 		 *	The mboot file must be delivered on all platforms
16027c478bd9Sstevel@tonic-gate 		 *	and installed in a non-platform-dependent
16037c478bd9Sstevel@tonic-gate 		 *	directory; i.e., /usr/lib/fs/ufs.
16047c478bd9Sstevel@tonic-gate 		 */
16057c478bd9Sstevel@tonic-gate 		io_mboot = "/usr/lib/fs/ufs/mboot";
16067c478bd9Sstevel@tonic-gate 	}
16077c478bd9Sstevel@tonic-gate 
16087c478bd9Sstevel@tonic-gate 	/* First read in the master boot record */
16097c478bd9Sstevel@tonic-gate 
16107c478bd9Sstevel@tonic-gate 	/* Open the master boot proto file */
16117c478bd9Sstevel@tonic-gate 	if ((mDev = open(io_mboot, O_RDONLY, 0666)) == -1) {
1612bb16350dSlclee 		(void) fprintf(stderr,
16137c478bd9Sstevel@tonic-gate 		    "fdisk: Cannot open master boot file %s.\n",
16147c478bd9Sstevel@tonic-gate 		    io_mboot);
16157c478bd9Sstevel@tonic-gate 		exit(1);
16167c478bd9Sstevel@tonic-gate 	}
16177c478bd9Sstevel@tonic-gate 
16187c478bd9Sstevel@tonic-gate 	/* Read the master boot program */
16197c478bd9Sstevel@tonic-gate 	if (read(mDev, &BootCod, sizeof (struct mboot)) != sizeof
16207c478bd9Sstevel@tonic-gate 	    (struct mboot)) {
1621bb16350dSlclee 		(void) fprintf(stderr,
16227c478bd9Sstevel@tonic-gate 		    "fdisk: Cannot read master boot file %s.\n",
16237c478bd9Sstevel@tonic-gate 		    io_mboot);
16247c478bd9Sstevel@tonic-gate 		exit(1);
16257c478bd9Sstevel@tonic-gate 	}
16267c478bd9Sstevel@tonic-gate 
16277c478bd9Sstevel@tonic-gate 	/* Is this really a master boot record? */
1628*aa1b14e7SSheshadri Vasudevan 	if (LE_16(BootCod.signature) != MBB_MAGIC) {
1629bb16350dSlclee 		(void) fprintf(stderr,
16307c478bd9Sstevel@tonic-gate 		    "fdisk: Invalid master boot file %s.\n", io_mboot);
1631bb16350dSlclee 		(void) fprintf(stderr,
1632bb16350dSlclee 		    "Bad magic number: is %x, but should be %x.\n",
1633*aa1b14e7SSheshadri Vasudevan 		    LE_16(BootCod.signature), MBB_MAGIC);
16347c478bd9Sstevel@tonic-gate 		exit(1);
16357c478bd9Sstevel@tonic-gate 	}
16367c478bd9Sstevel@tonic-gate 
1637bb16350dSlclee 	(void) close(mDev);
16387c478bd9Sstevel@tonic-gate #else
16397c478bd9Sstevel@tonic-gate #error	fdisk needs to be ported to new architecture
16407c478bd9Sstevel@tonic-gate #endif
16417c478bd9Sstevel@tonic-gate 
16427c478bd9Sstevel@tonic-gate 	/* Zero out the partitions part of this record */
16437c478bd9Sstevel@tonic-gate 	part = (struct ipart *)BootCod.parts;
16447c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++, part++) {
1645bb16350dSlclee 		(void) memset(part, 0, sizeof (struct ipart));
16467c478bd9Sstevel@tonic-gate 	}
16477c478bd9Sstevel@tonic-gate 
16487c478bd9Sstevel@tonic-gate }
16497c478bd9Sstevel@tonic-gate 
16507c478bd9Sstevel@tonic-gate /*
16517c478bd9Sstevel@tonic-gate  * fill_patt
16527c478bd9Sstevel@tonic-gate  * Fill the disk with user/sector number pattern.
16537c478bd9Sstevel@tonic-gate  */
1654bb16350dSlclee static void
1655bb16350dSlclee fill_patt(void)
16567c478bd9Sstevel@tonic-gate {
1657bb16350dSlclee 	int	*buff_ptr, i;
16589d5d1945Sbharding 	off_t	*off_ptr;
16597c478bd9Sstevel@tonic-gate 	int	io_fpatt = 0;
16607c478bd9Sstevel@tonic-gate 	int	io_ipatt = 0;
16617c478bd9Sstevel@tonic-gate 
16627c478bd9Sstevel@tonic-gate 	if (strncmp(io_fatt, "#", 1) != 0) {
16637c478bd9Sstevel@tonic-gate 		io_fpatt++;
16647c478bd9Sstevel@tonic-gate 		io_ipatt = strtoul(io_fatt, 0, 0);
16657c478bd9Sstevel@tonic-gate 		buff_ptr = (int *)Bootsect;
16667c478bd9Sstevel@tonic-gate 		for (i = 0; i < sectsiz; i += 4, buff_ptr++)
16671237e847Slclee 			*buff_ptr = io_ipatt;
16687c478bd9Sstevel@tonic-gate 	}
16697c478bd9Sstevel@tonic-gate 
16707c478bd9Sstevel@tonic-gate 	/*
16717c478bd9Sstevel@tonic-gate 	 * Fill disk with pattern based on block number.
16727c478bd9Sstevel@tonic-gate 	 * Write to the disk at absolute relative block io_offset
16737c478bd9Sstevel@tonic-gate 	 * for io_size blocks.
16747c478bd9Sstevel@tonic-gate 	 */
16757c478bd9Sstevel@tonic-gate 	while (io_size--) {
16769d5d1945Sbharding 		off_ptr = (off_t *)Bootsect;
16777c478bd9Sstevel@tonic-gate 		if (!io_fpatt) {
16789d5d1945Sbharding 			for (i = 0; i < sectsiz;
16799d5d1945Sbharding 			    i += sizeof (off_t), off_ptr++)
16809d5d1945Sbharding 				*off_ptr = io_offset;
16817c478bd9Sstevel@tonic-gate 		}
16827c478bd9Sstevel@tonic-gate 		/* Write the data to disk */
16839d5d1945Sbharding 		if (lseek(Dev, (off_t)(sectsiz * io_offset++),
16849d5d1945Sbharding 		    SEEK_SET) == -1) {
1685bb16350dSlclee 			(void) fprintf(stderr, "fdisk: Error seeking on %s.\n",
16861237e847Slclee 			    Dfltdev);
16877c478bd9Sstevel@tonic-gate 			exit(1);
16887c478bd9Sstevel@tonic-gate 		}
16897c478bd9Sstevel@tonic-gate 		if (write(Dev, Bootsect, sectsiz) != sectsiz) {
1690bb16350dSlclee 			(void) fprintf(stderr, "fdisk: Error writing %s.\n",
16911237e847Slclee 			    Dfltdev);
16927c478bd9Sstevel@tonic-gate 			exit(1);
16937c478bd9Sstevel@tonic-gate 		}
16947c478bd9Sstevel@tonic-gate 	} /* while (--io_size); */
16957c478bd9Sstevel@tonic-gate }
16967c478bd9Sstevel@tonic-gate 
16977c478bd9Sstevel@tonic-gate /*
16987c478bd9Sstevel@tonic-gate  * abs_read
16997c478bd9Sstevel@tonic-gate  * Read from the disk at absolute relative block io_offset for
17007c478bd9Sstevel@tonic-gate  * io_size blocks. Write the data to standard ouput (-r).
17017c478bd9Sstevel@tonic-gate  */
1702bb16350dSlclee static void
1703bb16350dSlclee abs_read(void)
1704bb16350dSlclee {
17057c478bd9Sstevel@tonic-gate 	int c;
17067c478bd9Sstevel@tonic-gate 
17077c478bd9Sstevel@tonic-gate 	while (io_size--) {
17089d5d1945Sbharding 		if (lseek(Dev, (off_t)(sectsiz * io_offset++),
17099d5d1945Sbharding 		    SEEK_SET) == -1) {
1710bb16350dSlclee 			(void) fprintf(stderr, "fdisk: Error seeking on %s.\n",
17117c478bd9Sstevel@tonic-gate 			    Dfltdev);
17127c478bd9Sstevel@tonic-gate 			exit(1);
17137c478bd9Sstevel@tonic-gate 		}
17147c478bd9Sstevel@tonic-gate 		if (read(Dev, Bootsect, sectsiz) != sectsiz) {
1715bb16350dSlclee 			(void) fprintf(stderr, "fdisk: Error reading %s.\n",
17167c478bd9Sstevel@tonic-gate 			    Dfltdev);
17177c478bd9Sstevel@tonic-gate 			exit(1);
17187c478bd9Sstevel@tonic-gate 		}
17197c478bd9Sstevel@tonic-gate 
17207c478bd9Sstevel@tonic-gate 		/* Write to standard ouptut */
1721bb16350dSlclee 		if ((c = write(1, Bootsect, (unsigned)sectsiz)) != sectsiz) {
17227c478bd9Sstevel@tonic-gate 			if (c >= 0) {
17237c478bd9Sstevel@tonic-gate 				if (io_debug)
1724bb16350dSlclee 					(void) fprintf(stderr,
1725bb16350dSlclee 					    "fdisk: Output warning: %d of %d"
1726bb16350dSlclee 					    " characters written.\n",
1727bb16350dSlclee 					    c, sectsiz);
17287c478bd9Sstevel@tonic-gate 				exit(2);
17297c478bd9Sstevel@tonic-gate 			} else {
17307c478bd9Sstevel@tonic-gate 				perror("write error on output file.");
17317c478bd9Sstevel@tonic-gate 				exit(2);
17327c478bd9Sstevel@tonic-gate 			}
17337c478bd9Sstevel@tonic-gate 		} /* if ((c = write(1, Bootsect, (unsigned)sectsiz)) */
17347c478bd9Sstevel@tonic-gate 			/* != sectsiz) */
17357c478bd9Sstevel@tonic-gate 	} /* while (--io_size); */
17367c478bd9Sstevel@tonic-gate 	exit(0);
17377c478bd9Sstevel@tonic-gate }
17387c478bd9Sstevel@tonic-gate 
17397c478bd9Sstevel@tonic-gate /*
17407c478bd9Sstevel@tonic-gate  * abs_write
17417c478bd9Sstevel@tonic-gate  * Read the data from standard input. Write to the disk at
17427c478bd9Sstevel@tonic-gate  * absolute relative block io_offset for io_size blocks (-w).
17437c478bd9Sstevel@tonic-gate  */
1744bb16350dSlclee static void
1745bb16350dSlclee abs_write(void)
17467c478bd9Sstevel@tonic-gate {
17477c478bd9Sstevel@tonic-gate 	int c, i;
17487c478bd9Sstevel@tonic-gate 
17497c478bd9Sstevel@tonic-gate 	while (io_size--) {
17507c478bd9Sstevel@tonic-gate 		int part_exit = 0;
17517c478bd9Sstevel@tonic-gate 		/* Read from standard input */
17527c478bd9Sstevel@tonic-gate 		if ((c = read(0, Bootsect, (unsigned)sectsiz)) != sectsiz) {
17537c478bd9Sstevel@tonic-gate 			if (c >= 0) {
17547c478bd9Sstevel@tonic-gate 				if (io_debug)
1755bb16350dSlclee 				(void) fprintf(stderr,
17567c478bd9Sstevel@tonic-gate 				    "fdisk: WARNING: Incomplete read (%d of"
17577c478bd9Sstevel@tonic-gate 				    " %d characters read) on input file.\n",
17581237e847Slclee 				    c, sectsiz);
17597c478bd9Sstevel@tonic-gate 				/* Fill pattern to mark partial sector in buf */
17607c478bd9Sstevel@tonic-gate 				for (i = c; i < sectsiz; ) {
17617c478bd9Sstevel@tonic-gate 					Bootsect[i++] = 0x41;
17627c478bd9Sstevel@tonic-gate 					Bootsect[i++] = 0x62;
17637c478bd9Sstevel@tonic-gate 					Bootsect[i++] = 0x65;
17647c478bd9Sstevel@tonic-gate 					Bootsect[i++] = 0;
17657c478bd9Sstevel@tonic-gate 				}
17667c478bd9Sstevel@tonic-gate 				part_exit++;
17677c478bd9Sstevel@tonic-gate 			} else {
17687c478bd9Sstevel@tonic-gate 				perror("read error on input file.");
17697c478bd9Sstevel@tonic-gate 				exit(2);
17707c478bd9Sstevel@tonic-gate 			}
17717c478bd9Sstevel@tonic-gate 
17727c478bd9Sstevel@tonic-gate 		}
17737c478bd9Sstevel@tonic-gate 		/* Write to disk drive */
17749d5d1945Sbharding 		if (lseek(Dev, (off_t)(sectsiz * io_offset++),
17759d5d1945Sbharding 		    SEEK_SET) == -1) {
1776bb16350dSlclee 			(void) fprintf(stderr, "fdisk: Error seeking on %s.\n",
17777c478bd9Sstevel@tonic-gate 			    Dfltdev);
17787c478bd9Sstevel@tonic-gate 			exit(1);
17797c478bd9Sstevel@tonic-gate 		}
17807c478bd9Sstevel@tonic-gate 		if (write(Dev, Bootsect, sectsiz) != sectsiz) {
1781bb16350dSlclee 			(void) fprintf(stderr, "fdisk: Error writing %s.\n",
17827c478bd9Sstevel@tonic-gate 			    Dfltdev);
17837c478bd9Sstevel@tonic-gate 			exit(1);
17847c478bd9Sstevel@tonic-gate 		}
17857c478bd9Sstevel@tonic-gate 		if (part_exit)
17867c478bd9Sstevel@tonic-gate 		exit(0);
17877c478bd9Sstevel@tonic-gate 	} /* while (--io_size); */
17887c478bd9Sstevel@tonic-gate 	exit(1);
17897c478bd9Sstevel@tonic-gate }
17907c478bd9Sstevel@tonic-gate 
1791bb16350dSlclee 
17927c478bd9Sstevel@tonic-gate /*
17937c478bd9Sstevel@tonic-gate  * load
17947c478bd9Sstevel@tonic-gate  * Load will either read the fdisk table from a file or add or
17957c478bd9Sstevel@tonic-gate  * delete an entry (-A, -D, -F).
17967c478bd9Sstevel@tonic-gate  */
17977c478bd9Sstevel@tonic-gate 
1798bb16350dSlclee static void
1799bb16350dSlclee load(int funct, char *file)
18007c478bd9Sstevel@tonic-gate {
18017c478bd9Sstevel@tonic-gate 	int	id;
18027c478bd9Sstevel@tonic-gate 	int	act;
18037c478bd9Sstevel@tonic-gate 	int	bhead;
18047c478bd9Sstevel@tonic-gate 	int	bsect;
18057c478bd9Sstevel@tonic-gate 	int	bcyl;
18067c478bd9Sstevel@tonic-gate 	int	ehead;
18077c478bd9Sstevel@tonic-gate 	int	esect;
18087c478bd9Sstevel@tonic-gate 	int	ecyl;
1809342440ecSPrasad Singamsetty 	uint32_t	rsect;
1810342440ecSPrasad Singamsetty 	uint32_t	numsect;
18117c478bd9Sstevel@tonic-gate 	char	line[256];
18127c478bd9Sstevel@tonic-gate 	int	i = 0;
18137c478bd9Sstevel@tonic-gate 	int	j;
18147c478bd9Sstevel@tonic-gate 	FILE *fp;
1815*aa1b14e7SSheshadri Vasudevan #ifdef i386
1816*aa1b14e7SSheshadri Vasudevan 	int 	ext_part_present = 0;
1817*aa1b14e7SSheshadri Vasudevan 	uint32_t	begsec, endsec, relsect;
1818*aa1b14e7SSheshadri Vasudevan 	logical_drive_t *temp;
1819*aa1b14e7SSheshadri Vasudevan 	int part_count = 0, ldcnt = 0;
1820*aa1b14e7SSheshadri Vasudevan 	uint32_t ext_beg_sec, ext_end_sec;
1821*aa1b14e7SSheshadri Vasudevan 	uint32_t old_ext_beg_sec = 0, old_ext_num_sec = 0;
1822*aa1b14e7SSheshadri Vasudevan 	uint32_t new_ext_beg_sec = 0, new_ext_num_sec = 0;
1823*aa1b14e7SSheshadri Vasudevan 	int ext_part_inited = 0;
1824*aa1b14e7SSheshadri Vasudevan 	uchar_t	systid;
1825*aa1b14e7SSheshadri Vasudevan #endif
18267c478bd9Sstevel@tonic-gate 
18277c478bd9Sstevel@tonic-gate 	switch (funct) {
18287c478bd9Sstevel@tonic-gate 
18291237e847Slclee 	case LOADFILE:
18307c478bd9Sstevel@tonic-gate 
18317c478bd9Sstevel@tonic-gate 		/*
18327c478bd9Sstevel@tonic-gate 		 * Zero out the table before loading it, which will
18337c478bd9Sstevel@tonic-gate 		 * force it to be updated on disk later (-F
18347c478bd9Sstevel@tonic-gate 		 * fdisk_file).
18357c478bd9Sstevel@tonic-gate 		 */
18367c478bd9Sstevel@tonic-gate 		nulltbl();
18377c478bd9Sstevel@tonic-gate 
18387c478bd9Sstevel@tonic-gate 		/* Open the prototype file */
18397c478bd9Sstevel@tonic-gate 		if ((fp = fopen(file, "r")) == NULL) {
18407c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
18417c478bd9Sstevel@tonic-gate 			    "fdisk: Cannot open prototype partition file %s.\n",
18427c478bd9Sstevel@tonic-gate 			    file);
18437c478bd9Sstevel@tonic-gate 			exit(1);
18447c478bd9Sstevel@tonic-gate 		}
18457c478bd9Sstevel@tonic-gate 
18467c478bd9Sstevel@tonic-gate 		/* Read a line from the file */
18477c478bd9Sstevel@tonic-gate 		while (fgets(line, sizeof (line) - 1, fp)) {
18487c478bd9Sstevel@tonic-gate 			if (pars_fdisk(line, &id, &act, &bhead, &bsect,
18497c478bd9Sstevel@tonic-gate 			    &bcyl, &ehead, &esect, &ecyl, &rsect, &numsect)) {
18507c478bd9Sstevel@tonic-gate 				continue;
18517c478bd9Sstevel@tonic-gate 			}
1852*aa1b14e7SSheshadri Vasudevan #ifdef i386
1853*aa1b14e7SSheshadri Vasudevan 			part_count++;
1854*aa1b14e7SSheshadri Vasudevan 
1855*aa1b14e7SSheshadri Vasudevan 			if (fdisk_is_dos_extended((uchar_t)id)) {
1856*aa1b14e7SSheshadri Vasudevan 				if (ext_part_present) {
1857*aa1b14e7SSheshadri Vasudevan 					fprintf(stderr, "Extended partition"
1858*aa1b14e7SSheshadri Vasudevan 					    " already exists\n");
1859*aa1b14e7SSheshadri Vasudevan 					fprintf(stderr, "fdisk: Error on"
1860*aa1b14e7SSheshadri Vasudevan 					    " entry \"%s\".\n", line);
1861*aa1b14e7SSheshadri Vasudevan 					exit(1);
1862*aa1b14e7SSheshadri Vasudevan 				}
1863*aa1b14e7SSheshadri Vasudevan 				ext_part_present = 1;
1864*aa1b14e7SSheshadri Vasudevan 				/*
1865*aa1b14e7SSheshadri Vasudevan 				 * If the existing extended partition's start
1866*aa1b14e7SSheshadri Vasudevan 				 * and size matches the new one, do not
1867*aa1b14e7SSheshadri Vasudevan 				 * initialize the extended partition EBR
1868*aa1b14e7SSheshadri Vasudevan 				 * (Extended Boot Record) because there could
1869*aa1b14e7SSheshadri Vasudevan 				 * be existing logical drives.
1870*aa1b14e7SSheshadri Vasudevan 				 */
1871*aa1b14e7SSheshadri Vasudevan 				for (i = 0; i < FD_NUMPART; i++) {
1872*aa1b14e7SSheshadri Vasudevan 					systid = Old_Table[i].systid;
1873*aa1b14e7SSheshadri Vasudevan 					if (fdisk_is_dos_extended(systid)) {
1874*aa1b14e7SSheshadri Vasudevan 						old_ext_beg_sec =
1875*aa1b14e7SSheshadri Vasudevan 						    Old_Table[i].relsect;
1876*aa1b14e7SSheshadri Vasudevan 						old_ext_num_sec =
1877*aa1b14e7SSheshadri Vasudevan 						    Old_Table[i].numsect;
1878*aa1b14e7SSheshadri Vasudevan 						break;
1879*aa1b14e7SSheshadri Vasudevan 					}
1880*aa1b14e7SSheshadri Vasudevan 				}
1881*aa1b14e7SSheshadri Vasudevan 				new_ext_beg_sec = rsect;
1882*aa1b14e7SSheshadri Vasudevan 				new_ext_num_sec = numsect;
1883*aa1b14e7SSheshadri Vasudevan 				if ((old_ext_beg_sec != new_ext_beg_sec) ||
1884*aa1b14e7SSheshadri Vasudevan 				    (old_ext_num_sec != new_ext_num_sec)) {
1885*aa1b14e7SSheshadri Vasudevan 					fdisk_init_ext_part(epp,
1886*aa1b14e7SSheshadri Vasudevan 					    new_ext_beg_sec, new_ext_num_sec);
1887*aa1b14e7SSheshadri Vasudevan 					ext_part_inited = 1;
1888*aa1b14e7SSheshadri Vasudevan 				}
1889*aa1b14e7SSheshadri Vasudevan 			}
1890*aa1b14e7SSheshadri Vasudevan 
1891*aa1b14e7SSheshadri Vasudevan 			if (part_count > FD_NUMPART) {
1892*aa1b14e7SSheshadri Vasudevan 				/* This line should be logical drive info */
1893*aa1b14e7SSheshadri Vasudevan 				int offset = MAX_LOGDRIVE_OFFSET;
1894*aa1b14e7SSheshadri Vasudevan 				if (!ext_part_present) {
1895*aa1b14e7SSheshadri Vasudevan 					/* Erroneous input file */
1896*aa1b14e7SSheshadri Vasudevan 					fprintf(stderr, "More than 4 primary"
1897*aa1b14e7SSheshadri Vasudevan 					    " partitions found in input\n");
1898*aa1b14e7SSheshadri Vasudevan 					fprintf(stderr, "Exiting...\n");
1899*aa1b14e7SSheshadri Vasudevan 					exit(1);
1900*aa1b14e7SSheshadri Vasudevan 				}
1901*aa1b14e7SSheshadri Vasudevan 
1902*aa1b14e7SSheshadri Vasudevan 				if (numsect == 0) {
1903*aa1b14e7SSheshadri Vasudevan 					continue;
1904*aa1b14e7SSheshadri Vasudevan 				}
1905*aa1b14e7SSheshadri Vasudevan 
1906*aa1b14e7SSheshadri Vasudevan 				/*
1907*aa1b14e7SSheshadri Vasudevan 				 * If the start and size of the existing
1908*aa1b14e7SSheshadri Vasudevan 				 * extended partition matches the new one and
1909*aa1b14e7SSheshadri Vasudevan 				 * new logical drives are being defined via
1910*aa1b14e7SSheshadri Vasudevan 				 * the input file, initialize the EBR.
1911*aa1b14e7SSheshadri Vasudevan 				 */
1912*aa1b14e7SSheshadri Vasudevan 				if (!ext_part_inited) {
1913*aa1b14e7SSheshadri Vasudevan 					fdisk_init_ext_part(epp,
1914*aa1b14e7SSheshadri Vasudevan 					    new_ext_beg_sec, new_ext_num_sec);
1915*aa1b14e7SSheshadri Vasudevan 					ext_part_inited = 1;
1916*aa1b14e7SSheshadri Vasudevan 				}
1917*aa1b14e7SSheshadri Vasudevan 
1918*aa1b14e7SSheshadri Vasudevan 				begsec = rsect - offset;
1919*aa1b14e7SSheshadri Vasudevan 				if ((ldcnt =
1920*aa1b14e7SSheshadri Vasudevan 				    fdisk_get_logical_drive_count(epp)) == 0) {
1921*aa1b14e7SSheshadri Vasudevan 					/* Adding the first logical drive */
1922*aa1b14e7SSheshadri Vasudevan 					/*
1923*aa1b14e7SSheshadri Vasudevan 					 * Make sure that begsec doesnt wrap
1924*aa1b14e7SSheshadri Vasudevan 					 * around. This can happen if rsect is
1925*aa1b14e7SSheshadri Vasudevan 					 * less than offset.
1926*aa1b14e7SSheshadri Vasudevan 					 */
1927*aa1b14e7SSheshadri Vasudevan 					if (rsect < offset) {
1928*aa1b14e7SSheshadri Vasudevan 						fprintf(stderr, "Minimum of "
1929*aa1b14e7SSheshadri Vasudevan 						    "63 free sectors required "
1930*aa1b14e7SSheshadri Vasudevan 						    "before the beginning of "
1931*aa1b14e7SSheshadri Vasudevan 						    "a logical drive.");
1932*aa1b14e7SSheshadri Vasudevan 						exit(1);
1933*aa1b14e7SSheshadri Vasudevan 					}
1934*aa1b14e7SSheshadri Vasudevan 					/*
1935*aa1b14e7SSheshadri Vasudevan 					 * Check if the first logical drive
1936*aa1b14e7SSheshadri Vasudevan 					 * is out of order. In that case, do
1937*aa1b14e7SSheshadri Vasudevan 					 * not subtract MAX_LOGDRIVE_OFFSET
1938*aa1b14e7SSheshadri Vasudevan 					 * from the given start of partition.
1939*aa1b14e7SSheshadri Vasudevan 					 */
1940*aa1b14e7SSheshadri Vasudevan 					if (begsec != new_ext_beg_sec) {
1941*aa1b14e7SSheshadri Vasudevan 						begsec = rsect;
1942*aa1b14e7SSheshadri Vasudevan 						offset = 0;
1943*aa1b14e7SSheshadri Vasudevan 					}
1944*aa1b14e7SSheshadri Vasudevan 				}
1945*aa1b14e7SSheshadri Vasudevan 				if (ldcnt >= MAX_EXT_PARTS) {
1946*aa1b14e7SSheshadri Vasudevan 					fprintf(stderr, "\nError : Number of "
1947*aa1b14e7SSheshadri Vasudevan 					    "logical drives exceeds limit of "
1948*aa1b14e7SSheshadri Vasudevan 					    "%d.\n", MAX_EXT_PARTS);
1949*aa1b14e7SSheshadri Vasudevan 					exit(1);
1950*aa1b14e7SSheshadri Vasudevan 				}
1951*aa1b14e7SSheshadri Vasudevan 
1952*aa1b14e7SSheshadri Vasudevan 				if (id > FDISK_MAX_VALID_PART_ID) {
1953*aa1b14e7SSheshadri Vasudevan 					fprintf(stderr, "Invalid partition "
1954*aa1b14e7SSheshadri Vasudevan 					    "ID\n");
1955*aa1b14e7SSheshadri Vasudevan 					fprintf(stderr, "fdisk: Error on"
1956*aa1b14e7SSheshadri Vasudevan 					    " entry \"%s\".\n", line);
1957*aa1b14e7SSheshadri Vasudevan 					exit(1);
1958*aa1b14e7SSheshadri Vasudevan 				}
1959*aa1b14e7SSheshadri Vasudevan 
1960*aa1b14e7SSheshadri Vasudevan 				endsec = rsect + numsect - 1;
1961*aa1b14e7SSheshadri Vasudevan 				if (fdisk_validate_logical_drive(epp,
1962*aa1b14e7SSheshadri Vasudevan 				    begsec, offset, numsect) == 0) {
1963*aa1b14e7SSheshadri Vasudevan 					if (id == EFI_PMBR) {
1964*aa1b14e7SSheshadri Vasudevan 						fprintf(stderr, "EFI "
1965*aa1b14e7SSheshadri Vasudevan 						    "partitions not supported "
1966*aa1b14e7SSheshadri Vasudevan 						    "inside extended "
1967*aa1b14e7SSheshadri Vasudevan 						    "partition\n");
1968*aa1b14e7SSheshadri Vasudevan 						exit(1);
1969*aa1b14e7SSheshadri Vasudevan 					}
1970*aa1b14e7SSheshadri Vasudevan 					fdisk_add_logical_drive(epp, begsec,
1971*aa1b14e7SSheshadri Vasudevan 					    endsec, id);
1972*aa1b14e7SSheshadri Vasudevan 					continue;
1973*aa1b14e7SSheshadri Vasudevan 				} else {
1974*aa1b14e7SSheshadri Vasudevan 					fprintf(stderr, "fdisk: Error on"
1975*aa1b14e7SSheshadri Vasudevan 					    " entry \"%s\".\n", line);
1976*aa1b14e7SSheshadri Vasudevan 					exit(1);
1977*aa1b14e7SSheshadri Vasudevan 				}
1978*aa1b14e7SSheshadri Vasudevan 			}
1979*aa1b14e7SSheshadri Vasudevan #endif
19807c478bd9Sstevel@tonic-gate 
19817c478bd9Sstevel@tonic-gate 			/*
19827c478bd9Sstevel@tonic-gate 			 * Validate the partition. It cannot start at sector
19837c478bd9Sstevel@tonic-gate 			 * 0 unless it is UNUSED or already exists
19847c478bd9Sstevel@tonic-gate 			 */
19857c478bd9Sstevel@tonic-gate 			if (validate_part(id, rsect, numsect) < 0) {
19867c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
19877c478bd9Sstevel@tonic-gate 				    "fdisk: Error on entry \"%s\".\n",
19887c478bd9Sstevel@tonic-gate 				    line);
19897c478bd9Sstevel@tonic-gate 				exit(1);
19907c478bd9Sstevel@tonic-gate 			}
19912f8ec719SBarry Harding 
19922f8ec719SBarry Harding 			if (entry_from_old_table(id, act, bhead, bsect,
19932f8ec719SBarry Harding 			    bcyl, ehead, esect, ecyl, rsect, numsect)) {
19942f8ec719SBarry Harding 				/*
19952f8ec719SBarry Harding 				 * If we got here it means we copied an
19962f8ec719SBarry Harding 				 * unmodified entry. So there is no need
19972f8ec719SBarry Harding 				 * to insert it in the table or do any
19982f8ec719SBarry Harding 				 * checks against disk size.
19992f8ec719SBarry Harding 				 *
20002f8ec719SBarry Harding 				 * This is a work around on the following
20012f8ec719SBarry Harding 				 * situation (for IDE disks, at least):
20022f8ec719SBarry Harding 				 * Different operation systems calculate
20032f8ec719SBarry Harding 				 * disk size different ways, of which there
20042f8ec719SBarry Harding 				 * are two main ways.
20052f8ec719SBarry Harding 				 *
20062f8ec719SBarry Harding 				 * The first, rounds the disk size to modulo
20072f8ec719SBarry Harding 				 * cylinder size (virtual made-up cylinder
20082f8ec719SBarry Harding 				 * usually based on maximum number of heads
20092f8ec719SBarry Harding 				 * and sectors in partition table fields).
20102f8ec719SBarry Harding 				 * Our OS's (for IDE) and most other "Unix"
20112f8ec719SBarry Harding 				 * type OS's do this.
20122f8ec719SBarry Harding 				 *
20132f8ec719SBarry Harding 				 * The second, uses every single block
20142f8ec719SBarry Harding 				 * on the disk (to maximize available space).
20152f8ec719SBarry Harding 				 * Since disk manufactures do not know about
20162f8ec719SBarry Harding 				 * "virtual cylinders", there are some number
20172f8ec719SBarry Harding 				 * of blocks that make up a partial cylinder
20182f8ec719SBarry Harding 				 * at the end of the disk.
20192f8ec719SBarry Harding 				 *
20202f8ec719SBarry Harding 				 * The difference between these two methods
20212f8ec719SBarry Harding 				 * is where the problem is. When one
20222f8ec719SBarry Harding 				 * tries to install Solaris/OpenSolaris on
20232f8ec719SBarry Harding 				 * a disk that has another OS using that
20242f8ec719SBarry Harding 				 * "partial cylinder", install fails. It fails
20252f8ec719SBarry Harding 				 * since fdisk thinks its asked to create a
20262f8ec719SBarry Harding 				 * partition with the -F option that contains
20272f8ec719SBarry Harding 				 * a partition that runs off the end of the
20282f8ec719SBarry Harding 				 * disk.
20292f8ec719SBarry Harding 				 */
20302f8ec719SBarry Harding 				continue;
20312f8ec719SBarry Harding 			}
20322f8ec719SBarry Harding 
20337c478bd9Sstevel@tonic-gate 			/*
20347c478bd9Sstevel@tonic-gate 			 * Find an unused entry to use and put the entry
20357c478bd9Sstevel@tonic-gate 			 * in table
20367c478bd9Sstevel@tonic-gate 			 */
20377c478bd9Sstevel@tonic-gate 			if (insert_tbl(id, act, bhead, bsect, bcyl, ehead,
20387c478bd9Sstevel@tonic-gate 			    esect, ecyl, rsect, numsect) < 0) {
20397c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
20407c478bd9Sstevel@tonic-gate 				    "fdisk: Error on entry \"%s\".\n",
20417c478bd9Sstevel@tonic-gate 				    line);
20427c478bd9Sstevel@tonic-gate 				exit(1);
20437c478bd9Sstevel@tonic-gate 			}
20447c478bd9Sstevel@tonic-gate 		} /* while (fgets(line, sizeof (line) - 1, fp)) */
20457c478bd9Sstevel@tonic-gate 
20467c478bd9Sstevel@tonic-gate 		if (verify_tbl() < 0) {
2047bb16350dSlclee 			(void) fprintf(stderr,
20487c478bd9Sstevel@tonic-gate 			    "fdisk: Cannot create partition table\n");
20497c478bd9Sstevel@tonic-gate 			exit(1);
20507c478bd9Sstevel@tonic-gate 		}
20517c478bd9Sstevel@tonic-gate 
2052bb16350dSlclee 		(void) fclose(fp);
20537c478bd9Sstevel@tonic-gate 		return;
20547c478bd9Sstevel@tonic-gate 
20551237e847Slclee 	case LOADDEL:
20567c478bd9Sstevel@tonic-gate 
20577c478bd9Sstevel@tonic-gate 		/* Parse the user-supplied deletion line (-D) */
2058bb16350dSlclee 		if (pars_fdisk(file, &id, &act, &bhead, &bsect, &bcyl,
2059bb16350dSlclee 		    &ehead, &esect, &ecyl, &rsect, &numsect)) {
2060bb16350dSlclee 			(void) fprintf(stderr,
2061bb16350dSlclee 			    "fdisk: Syntax error \"%s\"\n", file);
2062bb16350dSlclee 			exit(1);
2063bb16350dSlclee 		}
20647c478bd9Sstevel@tonic-gate 
20657c478bd9Sstevel@tonic-gate 		/* Find the exact entry in the table */
20667c478bd9Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
20677c478bd9Sstevel@tonic-gate 			if (Table[i].systid == id &&
20687c478bd9Sstevel@tonic-gate 			    Table[i].bootid == act &&
20697c478bd9Sstevel@tonic-gate 			    Table[i].beghead == bhead &&
20707c478bd9Sstevel@tonic-gate 			    Table[i].begsect == ((bsect & 0x3f) |
20711237e847Slclee 			    (uchar_t)((bcyl>>2) & 0xc0)) &&
2072bb16350dSlclee 			    Table[i].begcyl == (uchar_t)(bcyl & 0xff) &&
20737c478bd9Sstevel@tonic-gate 			    Table[i].endhead == ehead &&
20747c478bd9Sstevel@tonic-gate 			    Table[i].endsect == ((esect & 0x3f) |
20751237e847Slclee 			    (uchar_t)((ecyl>>2) & 0xc0)) &&
2076bb16350dSlclee 			    Table[i].endcyl == (uchar_t)(ecyl & 0xff) &&
2077*aa1b14e7SSheshadri Vasudevan 			    Table[i].relsect == LE_32(rsect) &&
2078*aa1b14e7SSheshadri Vasudevan 			    Table[i].numsect == LE_32(numsect)) {
20797c478bd9Sstevel@tonic-gate 
20807c478bd9Sstevel@tonic-gate 				/*
20817c478bd9Sstevel@tonic-gate 				 * Found the entry. Now move rest of
20827c478bd9Sstevel@tonic-gate 				 * entries up toward the top of the
20837c478bd9Sstevel@tonic-gate 				 * table, leaving available entries at
20847c478bd9Sstevel@tonic-gate 				 * the end of the fdisk table.
20857c478bd9Sstevel@tonic-gate 				 */
2086bb16350dSlclee 				for (j = i; j < FD_NUMPART - 1; j++) {
2087bb16350dSlclee 					Table[j].systid = Table[j + 1].systid;
2088bb16350dSlclee 					Table[j].bootid = Table[j + 1].bootid;
2089bb16350dSlclee 					Table[j].beghead = Table[j + 1].beghead;
2090bb16350dSlclee 					Table[j].begsect = Table[j + 1].begsect;
2091bb16350dSlclee 					Table[j].begcyl = Table[j + 1].begcyl;
2092bb16350dSlclee 					Table[j].endhead = Table[j + 1].endhead;
2093bb16350dSlclee 					Table[j].endsect = Table[j + 1].endsect;
2094bb16350dSlclee 					Table[j].endcyl = Table[j + 1].endcyl;
2095bb16350dSlclee 					Table[j].relsect = Table[j + 1].relsect;
2096bb16350dSlclee 					Table[j].numsect = Table[j + 1].numsect;
20977c478bd9Sstevel@tonic-gate 				}
20987c478bd9Sstevel@tonic-gate 
20997c478bd9Sstevel@tonic-gate 				/*
21007c478bd9Sstevel@tonic-gate 				 * Mark the last entry as unused in case
21017c478bd9Sstevel@tonic-gate 				 * all table entries were in use prior
21027c478bd9Sstevel@tonic-gate 				 * to the deletion.
21037c478bd9Sstevel@tonic-gate 				 */
21047c478bd9Sstevel@tonic-gate 
2105bb16350dSlclee 				Table[FD_NUMPART - 1].systid = UNUSED;
2106bb16350dSlclee 				Table[FD_NUMPART - 1].bootid = 0;
2107*aa1b14e7SSheshadri Vasudevan #ifdef i386
2108*aa1b14e7SSheshadri Vasudevan 				if (fdisk_is_dos_extended(id)) {
2109*aa1b14e7SSheshadri Vasudevan 					fdisk_delete_ext_part(epp);
2110*aa1b14e7SSheshadri Vasudevan 				}
2111*aa1b14e7SSheshadri Vasudevan #endif
2112*aa1b14e7SSheshadri Vasudevan 				return;
2113*aa1b14e7SSheshadri Vasudevan 			}
2114*aa1b14e7SSheshadri Vasudevan 		}
2115*aa1b14e7SSheshadri Vasudevan 
2116*aa1b14e7SSheshadri Vasudevan #ifdef i386
2117*aa1b14e7SSheshadri Vasudevan 		ldcnt = FD_NUMPART + 1;
2118*aa1b14e7SSheshadri Vasudevan 		for (temp = fdisk_get_ld_head(epp); temp != NULL;
2119*aa1b14e7SSheshadri Vasudevan 		    temp = temp->next) {
2120*aa1b14e7SSheshadri Vasudevan 			relsect = temp->abs_secnum + temp->logdrive_offset;
2121*aa1b14e7SSheshadri Vasudevan 			if (temp->parts[0].systid == id &&
2122*aa1b14e7SSheshadri Vasudevan 			    temp->parts[0].bootid == act &&
2123*aa1b14e7SSheshadri Vasudevan 			    temp->parts[0].beghead == bhead &&
2124*aa1b14e7SSheshadri Vasudevan 			    temp->parts[0].begsect == ((bsect & 0x3f) |
2125*aa1b14e7SSheshadri Vasudevan 			    (uchar_t)((bcyl>>2) & 0xc0)) &&
2126*aa1b14e7SSheshadri Vasudevan 			    temp->parts[0].begcyl == (uchar_t)(bcyl & 0xff) &&
2127*aa1b14e7SSheshadri Vasudevan 			    temp->parts[0].endhead == ehead &&
2128*aa1b14e7SSheshadri Vasudevan 			    temp->parts[0].endsect == ((esect & 0x3f) |
2129*aa1b14e7SSheshadri Vasudevan 			    (uchar_t)((ecyl>>2) & 0xc0)) &&
2130*aa1b14e7SSheshadri Vasudevan 			    temp->parts[0].endcyl == (uchar_t)(ecyl & 0xff) &&
2131*aa1b14e7SSheshadri Vasudevan 			    relsect == LE_32(rsect) &&
2132*aa1b14e7SSheshadri Vasudevan 			    temp->parts[0].numsect == LE_32(numsect)) {
2133*aa1b14e7SSheshadri Vasudevan 				fdisk_delete_logical_drive(epp, ldcnt);
21347c478bd9Sstevel@tonic-gate 				return;
21357c478bd9Sstevel@tonic-gate 			}
2136*aa1b14e7SSheshadri Vasudevan 			ldcnt++;
21377c478bd9Sstevel@tonic-gate 		}
2138*aa1b14e7SSheshadri Vasudevan #endif
2139*aa1b14e7SSheshadri Vasudevan 
2140bb16350dSlclee 		(void) fprintf(stderr,
21417c478bd9Sstevel@tonic-gate 		    "fdisk: Entry does not match any existing partition:\n"
21427c478bd9Sstevel@tonic-gate 		    "	\"%s\"\n",
21437c478bd9Sstevel@tonic-gate 		    file);
21447c478bd9Sstevel@tonic-gate 		exit(1);
2145f85c7842SSuhasini Peddada 		/* FALLTHRU */
21467c478bd9Sstevel@tonic-gate 
21471237e847Slclee 	case LOADADD:
21487c478bd9Sstevel@tonic-gate 
21497c478bd9Sstevel@tonic-gate 		/* Parse the user-supplied addition line (-A) */
2150bb16350dSlclee 		if (pars_fdisk(file, &id, &act, &bhead, &bsect, &bcyl, &ehead,
2151bb16350dSlclee 		    &esect, &ecyl, &rsect, &numsect)) {
2152bb16350dSlclee 			(void) fprintf(stderr,
2153bb16350dSlclee 			    "fdisk: Syntax error \"%s\"\n", file);
2154bb16350dSlclee 			exit(1);
2155bb16350dSlclee 		}
21567c478bd9Sstevel@tonic-gate 
21577c478bd9Sstevel@tonic-gate 		/* Validate the partition. It cannot start at sector 0 */
21587c478bd9Sstevel@tonic-gate 		if (rsect == 0) {
21597c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
21607c478bd9Sstevel@tonic-gate 			    "fdisk: New partition cannot start at sector 0:\n"
21617c478bd9Sstevel@tonic-gate 			    "   \"%s\".\n",
21627c478bd9Sstevel@tonic-gate 			    file);
21637c478bd9Sstevel@tonic-gate 			exit(1);
21647c478bd9Sstevel@tonic-gate 		}
21657c478bd9Sstevel@tonic-gate 
21667c478bd9Sstevel@tonic-gate 		/*
21677c478bd9Sstevel@tonic-gate 		 * if the user wishes to add an EFI partition, we need
21687c478bd9Sstevel@tonic-gate 		 * more extensive validation.  rsect should be 1, and
21697c478bd9Sstevel@tonic-gate 		 * numsect should equal the entire disk capacity - 1
21707c478bd9Sstevel@tonic-gate 		 */
21717c478bd9Sstevel@tonic-gate 
21727c478bd9Sstevel@tonic-gate 		if (id == EFI_PMBR) {
21737c478bd9Sstevel@tonic-gate 			if (rsect != 1) {
21747c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
21757c478bd9Sstevel@tonic-gate 				    "fdisk: EFI partitions must start at sector"
21767c478bd9Sstevel@tonic-gate 				    " 1 (input rsect = %d)\n", rsect);
21777c478bd9Sstevel@tonic-gate 				exit(1);
21787c478bd9Sstevel@tonic-gate 			}
21797c478bd9Sstevel@tonic-gate 
2180342440ecSPrasad Singamsetty 
2181342440ecSPrasad Singamsetty 			if (dev_capacity > DK_MAX_2TB) {
2182342440ecSPrasad Singamsetty 				if (numsect != DK_MAX_2TB) {
2183342440ecSPrasad Singamsetty 					(void) fprintf(stderr,
2184342440ecSPrasad Singamsetty 					    "fdisk: EFI partitions must "
2185342440ecSPrasad Singamsetty 					    "encompass the entire maximum 2 TB "
2186342440ecSPrasad Singamsetty 					    "(input numsect: %u - max: %llu)\n",
2187342440ecSPrasad Singamsetty 					    numsect, (diskaddr_t)DK_MAX_2TB);
2188342440ecSPrasad Singamsetty 				exit(1);
2189342440ecSPrasad Singamsetty 				}
2190342440ecSPrasad Singamsetty 			} else if (numsect != dev_capacity - 1) {
21917c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
21927c478bd9Sstevel@tonic-gate 				    "fdisk: EFI partitions must encompass the "
2193bb16350dSlclee 				    "entire disk\n"
2194342440ecSPrasad Singamsetty 				    "(input numsect: %u - avail: %llu)\n",
2195bb16350dSlclee 				    numsect,
21961237e847Slclee 				    dev_capacity - 1);
21977c478bd9Sstevel@tonic-gate 				exit(1);
21987c478bd9Sstevel@tonic-gate 			}
21997c478bd9Sstevel@tonic-gate 		}
22007c478bd9Sstevel@tonic-gate 
2201*aa1b14e7SSheshadri Vasudevan #ifdef i386
2202*aa1b14e7SSheshadri Vasudevan 		if (id > FDISK_MAX_VALID_PART_ID) {
2203*aa1b14e7SSheshadri Vasudevan 			printf("Invalid partition ID\n");
2204*aa1b14e7SSheshadri Vasudevan 			exit(1);
2205*aa1b14e7SSheshadri Vasudevan 		}
2206*aa1b14e7SSheshadri Vasudevan 
2207*aa1b14e7SSheshadri Vasudevan 		if ((fdisk_ext_part_exists(epp)) &&
2208*aa1b14e7SSheshadri Vasudevan 		    (fdisk_is_dos_extended(id))) {
2209*aa1b14e7SSheshadri Vasudevan 			(void) fprintf(stderr,
2210*aa1b14e7SSheshadri Vasudevan 			    "Extended partition already exists.\n");
2211*aa1b14e7SSheshadri Vasudevan 			(void) fprintf(stderr,
2212*aa1b14e7SSheshadri Vasudevan 			    "fdisk: Invalid entry could not be "
2213*aa1b14e7SSheshadri Vasudevan 			    "inserted:\n        \"%s\"\n", file);
2214*aa1b14e7SSheshadri Vasudevan 			exit(1);
2215*aa1b14e7SSheshadri Vasudevan 		}
2216*aa1b14e7SSheshadri Vasudevan 
2217*aa1b14e7SSheshadri Vasudevan 		if (fdisk_ext_part_exists(epp) &&
2218*aa1b14e7SSheshadri Vasudevan 		    (rsect >= (ext_beg_sec = fdisk_get_ext_beg_sec(epp))) &&
2219*aa1b14e7SSheshadri Vasudevan 		    (rsect <= (ext_end_sec = fdisk_get_ext_end_sec(epp)))) {
2220*aa1b14e7SSheshadri Vasudevan 			int offset = MAX_LOGDRIVE_OFFSET;
2221*aa1b14e7SSheshadri Vasudevan 
2222*aa1b14e7SSheshadri Vasudevan 			/*
2223*aa1b14e7SSheshadri Vasudevan 			 * Make sure that begsec doesnt wrap around.
2224*aa1b14e7SSheshadri Vasudevan 			 * This can happen if rsect is less than offset
2225*aa1b14e7SSheshadri Vasudevan 			 */
2226*aa1b14e7SSheshadri Vasudevan 			if (rsect < offset) {
2227*aa1b14e7SSheshadri Vasudevan 				return;
2228*aa1b14e7SSheshadri Vasudevan 			}
2229*aa1b14e7SSheshadri Vasudevan 			begsec = rsect - offset;
2230*aa1b14e7SSheshadri Vasudevan 			if ((ldcnt = fdisk_get_logical_drive_count(epp)) == 0) {
2231*aa1b14e7SSheshadri Vasudevan 				/*
2232*aa1b14e7SSheshadri Vasudevan 				 * Adding the first logical drive
2233*aa1b14e7SSheshadri Vasudevan 				 * Check if the first logical drive
2234*aa1b14e7SSheshadri Vasudevan 				 * is out of order. In that case, do
2235*aa1b14e7SSheshadri Vasudevan 				 * not subtract MAX_LOGDRIVE_OFFSET
2236*aa1b14e7SSheshadri Vasudevan 				 * from the given start of partition.
2237*aa1b14e7SSheshadri Vasudevan 				 */
2238*aa1b14e7SSheshadri Vasudevan 				if (begsec != ext_beg_sec) {
2239*aa1b14e7SSheshadri Vasudevan 					begsec = rsect;
2240*aa1b14e7SSheshadri Vasudevan 					offset = 0;
2241*aa1b14e7SSheshadri Vasudevan 				}
2242*aa1b14e7SSheshadri Vasudevan 			}
2243*aa1b14e7SSheshadri Vasudevan 
2244*aa1b14e7SSheshadri Vasudevan 			if (ldcnt >= MAX_EXT_PARTS) {
2245*aa1b14e7SSheshadri Vasudevan 				printf("\nNumber of logical drives exceeds "
2246*aa1b14e7SSheshadri Vasudevan 				    "limit of %d.\n", MAX_EXT_PARTS);
2247*aa1b14e7SSheshadri Vasudevan 				printf("Failing further additions.\n");
2248*aa1b14e7SSheshadri Vasudevan 				exit(1);
2249*aa1b14e7SSheshadri Vasudevan 			}
2250*aa1b14e7SSheshadri Vasudevan 
2251*aa1b14e7SSheshadri Vasudevan 			if (numsect == 0) {
2252*aa1b14e7SSheshadri Vasudevan 				(void) fprintf(stderr,
2253*aa1b14e7SSheshadri Vasudevan 				    "fdisk: Partition size cannot be zero:\n"
2254*aa1b14e7SSheshadri Vasudevan 				    "   \"%s\".\n",
2255*aa1b14e7SSheshadri Vasudevan 				    file);
2256*aa1b14e7SSheshadri Vasudevan 				exit(1);
2257*aa1b14e7SSheshadri Vasudevan 			}
2258*aa1b14e7SSheshadri Vasudevan 			endsec = rsect + numsect - 1;
2259*aa1b14e7SSheshadri Vasudevan 			if (fdisk_validate_logical_drive(epp, begsec,
2260*aa1b14e7SSheshadri Vasudevan 			    offset, numsect) == 0) {
2261*aa1b14e7SSheshadri Vasudevan 				/* Valid logical drive */
2262*aa1b14e7SSheshadri Vasudevan 				fdisk_add_logical_drive(epp, begsec, endsec,
2263*aa1b14e7SSheshadri Vasudevan 				    id);
2264*aa1b14e7SSheshadri Vasudevan 				return;
2265*aa1b14e7SSheshadri Vasudevan 			}
2266*aa1b14e7SSheshadri Vasudevan 		}
2267*aa1b14e7SSheshadri Vasudevan #endif
2268*aa1b14e7SSheshadri Vasudevan 
22697c478bd9Sstevel@tonic-gate 		/* Find unused entry for use and put entry in table */
22707c478bd9Sstevel@tonic-gate 		if (insert_tbl(id, act, bhead, bsect, bcyl, ehead, esect,
22717c478bd9Sstevel@tonic-gate 		    ecyl, rsect, numsect) < 0) {
22727c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
22737c478bd9Sstevel@tonic-gate 			    "fdisk: Invalid entry could not be inserted:\n"
22747c478bd9Sstevel@tonic-gate 			    "	\"%s\"\n",
22757c478bd9Sstevel@tonic-gate 			    file);
22767c478bd9Sstevel@tonic-gate 			exit(1);
22777c478bd9Sstevel@tonic-gate 		}
22787c478bd9Sstevel@tonic-gate 
22797c478bd9Sstevel@tonic-gate 		/* Make sure new entry does not overlap existing entry */
22807c478bd9Sstevel@tonic-gate 		if (verify_tbl() < 0) {
2281bb16350dSlclee 			(void) fprintf(stderr,
2282bb16350dSlclee 			    "fdisk: Cannot create partition \"%s\"\n", file);
22837c478bd9Sstevel@tonic-gate 			exit(1);
22847c478bd9Sstevel@tonic-gate 		}
22857c478bd9Sstevel@tonic-gate 	} /* switch funct */
22867c478bd9Sstevel@tonic-gate }
22877c478bd9Sstevel@tonic-gate 
22887c478bd9Sstevel@tonic-gate /*
22897c478bd9Sstevel@tonic-gate  * Set_Table_CHS_Values
22907c478bd9Sstevel@tonic-gate  *
22917c478bd9Sstevel@tonic-gate  * This will calculate the CHS values for beginning and ending CHS
22927c478bd9Sstevel@tonic-gate  * for a single partition table entry (ti) based on the relsect
22937c478bd9Sstevel@tonic-gate  * and numsect values contained in the partion table entry.
22947c478bd9Sstevel@tonic-gate  *
22957c478bd9Sstevel@tonic-gate  * hba_heads and hba_sectors contain the number of heads and sectors.
22967c478bd9Sstevel@tonic-gate  *
22977c478bd9Sstevel@tonic-gate  * If the number of cylinders exceeds the MAX_CYL,
22987c478bd9Sstevel@tonic-gate  * then maximum values will be placed in the corresponding chs entry.
22997c478bd9Sstevel@tonic-gate  */
23007c478bd9Sstevel@tonic-gate static void
23017c478bd9Sstevel@tonic-gate Set_Table_CHS_Values(int ti)
23027c478bd9Sstevel@tonic-gate {
23037c478bd9Sstevel@tonic-gate 	uint32_t	lba, cy, hd, sc;
23047c478bd9Sstevel@tonic-gate 
23057c478bd9Sstevel@tonic-gate 	lba = (uint32_t)Table[ti].relsect;
23067c478bd9Sstevel@tonic-gate 	if (lba >= hba_heads * hba_sectors * MAX_CYL) {
23077c478bd9Sstevel@tonic-gate 		/*
23087c478bd9Sstevel@tonic-gate 		 * the lba address cannot be expressed in CHS value
23097c478bd9Sstevel@tonic-gate 		 * so store the maximum CHS field values in the CHS fields.
23107c478bd9Sstevel@tonic-gate 		 */
23117c478bd9Sstevel@tonic-gate 		cy = MAX_CYL + 1;
23127c478bd9Sstevel@tonic-gate 		hd = MAX_HEAD;
23137c478bd9Sstevel@tonic-gate 		sc = MAX_SECT;
23147c478bd9Sstevel@tonic-gate 	} else {
23157c478bd9Sstevel@tonic-gate 		cy = lba / hba_sectors / hba_heads;
23167c478bd9Sstevel@tonic-gate 		hd = lba / hba_sectors % hba_heads;
23177c478bd9Sstevel@tonic-gate 		sc = lba % hba_sectors + 1;
23187c478bd9Sstevel@tonic-gate 	}
23197c478bd9Sstevel@tonic-gate 	Table[ti].begcyl = cy & 0xff;
2320bb16350dSlclee 	Table[ti].beghead = (uchar_t)hd;
2321bb16350dSlclee 	Table[ti].begsect = (uchar_t)(((cy >> 2) & 0xc0) | sc);
23227c478bd9Sstevel@tonic-gate 
23237c478bd9Sstevel@tonic-gate 	/*
23247c478bd9Sstevel@tonic-gate 	 * This code is identical to the code above
23257c478bd9Sstevel@tonic-gate 	 * except that it works on ending CHS values
23267c478bd9Sstevel@tonic-gate 	 */
23277c478bd9Sstevel@tonic-gate 	lba = (uint32_t)(Table[ti].relsect + Table[ti].numsect - 1);
23287c478bd9Sstevel@tonic-gate 	if (lba >= hba_heads * hba_sectors * MAX_CYL) {
23297c478bd9Sstevel@tonic-gate 		cy = MAX_CYL + 1;
23307c478bd9Sstevel@tonic-gate 		hd = MAX_HEAD;
23317c478bd9Sstevel@tonic-gate 		sc = MAX_SECT;
23327c478bd9Sstevel@tonic-gate 	} else {
23337c478bd9Sstevel@tonic-gate 		cy = lba / hba_sectors / hba_heads;
23347c478bd9Sstevel@tonic-gate 		hd = lba / hba_sectors % hba_heads;
23357c478bd9Sstevel@tonic-gate 		sc = lba % hba_sectors + 1;
23367c478bd9Sstevel@tonic-gate 	}
23377c478bd9Sstevel@tonic-gate 	Table[ti].endcyl = cy & 0xff;
2338bb16350dSlclee 	Table[ti].endhead = (uchar_t)hd;
2339bb16350dSlclee 	Table[ti].endsect = (uchar_t)(((cy >> 2) & 0xc0) | sc);
23407c478bd9Sstevel@tonic-gate }
23417c478bd9Sstevel@tonic-gate 
23427c478bd9Sstevel@tonic-gate /*
23437c478bd9Sstevel@tonic-gate  * insert_tbl
23447c478bd9Sstevel@tonic-gate  * 	Insert entry into fdisk table. Check all user-supplied values
23457c478bd9Sstevel@tonic-gate  *	for the entry, but not the validity relative to other table
23467c478bd9Sstevel@tonic-gate  *	entries!
23477c478bd9Sstevel@tonic-gate  */
2348bb16350dSlclee static int
2349bb16350dSlclee insert_tbl(
2350bb16350dSlclee     int id, int act,
2351bb16350dSlclee     int bhead, int bsect, int bcyl,
2352bb16350dSlclee     int ehead, int esect, int ecyl,
2353342440ecSPrasad Singamsetty     uint32_t rsect, uint32_t numsect)
23547c478bd9Sstevel@tonic-gate {
23557c478bd9Sstevel@tonic-gate 	int	i;
23567c478bd9Sstevel@tonic-gate 
23577c478bd9Sstevel@tonic-gate 	/* validate partition size */
2358342440ecSPrasad Singamsetty 	if (((diskaddr_t)rsect + numsect) > dev_capacity) {
2359bb16350dSlclee 		(void) fprintf(stderr,
23607c478bd9Sstevel@tonic-gate 		    "fdisk: Partition table exceeds the size of the disk.\n");
23617c478bd9Sstevel@tonic-gate 		return (-1);
23627c478bd9Sstevel@tonic-gate 	}
23637c478bd9Sstevel@tonic-gate 
2364342440ecSPrasad Singamsetty 
23657c478bd9Sstevel@tonic-gate 	/* find UNUSED partition table entry */
23667c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
23677c478bd9Sstevel@tonic-gate 		if (Table[i].systid == UNUSED) {
23687c478bd9Sstevel@tonic-gate 			break;
23697c478bd9Sstevel@tonic-gate 		}
23707c478bd9Sstevel@tonic-gate 	}
23717c478bd9Sstevel@tonic-gate 	if (i >= FD_NUMPART) {
2372bb16350dSlclee 		(void) fprintf(stderr, "fdisk: Partition table is full.\n");
23737c478bd9Sstevel@tonic-gate 		return (-1);
23747c478bd9Sstevel@tonic-gate 	}
23757c478bd9Sstevel@tonic-gate 
23767c478bd9Sstevel@tonic-gate 
2377bb16350dSlclee 	Table[i].systid = (uchar_t)id;
2378bb16350dSlclee 	Table[i].bootid = (uchar_t)act;
2379*aa1b14e7SSheshadri Vasudevan 	Table[i].numsect = LE_32(numsect);
2380*aa1b14e7SSheshadri Vasudevan 	Table[i].relsect = LE_32(rsect);
23817c478bd9Sstevel@tonic-gate 
23827c478bd9Sstevel@tonic-gate 	/*
23837c478bd9Sstevel@tonic-gate 	 * If we have been called with a valid geometry, use it
23847c478bd9Sstevel@tonic-gate 	 * valid means non-zero values that fit in the BIOS fields
23857c478bd9Sstevel@tonic-gate 	 */
23867c478bd9Sstevel@tonic-gate 	if (0 < bsect && bsect <= MAX_SECT &&
23877c478bd9Sstevel@tonic-gate 	    0 <= bhead && bhead <= MAX_HEAD &&
23887c478bd9Sstevel@tonic-gate 	    0 < esect && esect <= MAX_SECT &&
23897c478bd9Sstevel@tonic-gate 	    0 <= ehead && ehead <= MAX_HEAD) {
23907c478bd9Sstevel@tonic-gate 		if (bcyl > MAX_CYL)
23917c478bd9Sstevel@tonic-gate 			bcyl = MAX_CYL + 1;
23927c478bd9Sstevel@tonic-gate 		if (ecyl > MAX_CYL)
23937c478bd9Sstevel@tonic-gate 			ecyl = MAX_CYL + 1;
23947c478bd9Sstevel@tonic-gate 		Table[i].begcyl = bcyl & 0xff;
23957c478bd9Sstevel@tonic-gate 		Table[i].endcyl = ecyl & 0xff;
2396bb16350dSlclee 		Table[i].beghead = (uchar_t)bhead;
2397bb16350dSlclee 		Table[i].endhead = (uchar_t)ehead;
2398bb16350dSlclee 		Table[i].begsect = (uchar_t)(((bcyl >> 2) & 0xc0) | bsect);
23997c478bd9Sstevel@tonic-gate 		Table[i].endsect = ((ecyl >> 2) & 0xc0) | esect;
24007c478bd9Sstevel@tonic-gate 	} else {
24017c478bd9Sstevel@tonic-gate 
24027c478bd9Sstevel@tonic-gate 		/*
24037c478bd9Sstevel@tonic-gate 		 * The specified values are invalid,
24047c478bd9Sstevel@tonic-gate 		 * so calculate the values based on hba_heads, hba_sectors
24057c478bd9Sstevel@tonic-gate 		 */
24067c478bd9Sstevel@tonic-gate 		Set_Table_CHS_Values(i);
24077c478bd9Sstevel@tonic-gate 	}
24087c478bd9Sstevel@tonic-gate 
24097c478bd9Sstevel@tonic-gate 	/*
24107c478bd9Sstevel@tonic-gate 	 * return partition index
24117c478bd9Sstevel@tonic-gate 	 */
24127c478bd9Sstevel@tonic-gate 	return (i);
24137c478bd9Sstevel@tonic-gate }
24147c478bd9Sstevel@tonic-gate 
24152f8ec719SBarry Harding /*
24162f8ec719SBarry Harding  * entry_from_old_table
24172f8ec719SBarry Harding  *	If the specified entry is in the old table and is not a Solaris entry
24182f8ec719SBarry Harding  *	then insert same entry into new fdisk table. If we do this then
24192f8ec719SBarry Harding  *	all checks are skipped for that entry!
24202f8ec719SBarry Harding  */
24212f8ec719SBarry Harding static int
24222f8ec719SBarry Harding entry_from_old_table(
24232f8ec719SBarry Harding     int id, int act,
24242f8ec719SBarry Harding     int bhead, int bsect, int bcyl,
24252f8ec719SBarry Harding     int ehead, int esect, int ecyl,
24262f8ec719SBarry Harding     uint32_t rsect, uint32_t numsect)
24272f8ec719SBarry Harding {
24282f8ec719SBarry Harding 	uint32_t	i, j;
24292f8ec719SBarry Harding 
24302f8ec719SBarry Harding 	if (id == SUNIXOS || id == SUNIXOS2)
24312f8ec719SBarry Harding 		return (0);
2432d463bb94SBarry Harding 	for (i = 0; i < FD_NUMPART; i++) {
24332f8ec719SBarry Harding 		if (Old_Table[i].systid == id &&
24342f8ec719SBarry Harding 		    Old_Table[i].bootid == act &&
24352f8ec719SBarry Harding 		    Old_Table[i].beghead == bhead &&
24362f8ec719SBarry Harding 		    Old_Table[i].begsect == ((bsect & 0x3f) |
24372f8ec719SBarry Harding 		    (uchar_t)((bcyl>>2) & 0xc0)) &&
24382f8ec719SBarry Harding 		    Old_Table[i].begcyl == (uchar_t)(bcyl & 0xff) &&
24392f8ec719SBarry Harding 		    Old_Table[i].endhead == ehead &&
24402f8ec719SBarry Harding 		    Old_Table[i].endsect == ((esect & 0x3f) |
24412f8ec719SBarry Harding 		    (uchar_t)((ecyl>>2) & 0xc0)) &&
24422f8ec719SBarry Harding 		    Old_Table[i].endcyl == (uchar_t)(ecyl & 0xff) &&
24432f8ec719SBarry Harding 		    Old_Table[i].relsect == lel(rsect) &&
24442f8ec719SBarry Harding 		    Old_Table[i].numsect == lel(numsect)) {
24452f8ec719SBarry Harding 			/* find UNUSED partition table entry */
24462f8ec719SBarry Harding 			for (j = 0; j < FD_NUMPART; j++) {
24472f8ec719SBarry Harding 				if (Table[j].systid == UNUSED) {
24482f8ec719SBarry Harding 					(void) memcpy(&Table[j], &Old_Table[i],
24492f8ec719SBarry Harding 					    sizeof (Table[0]));
24502f8ec719SBarry Harding 					skip_verify[j] = 1;
24512f8ec719SBarry Harding 					return (1);
24522f8ec719SBarry Harding 
24532f8ec719SBarry Harding 				}
24542f8ec719SBarry Harding 			}
24552f8ec719SBarry Harding 			return (0);
24562f8ec719SBarry Harding 		}
24572f8ec719SBarry Harding 
24582f8ec719SBarry Harding 	}
24592f8ec719SBarry Harding 	return (0);
24602f8ec719SBarry Harding }
24612f8ec719SBarry Harding 
24627c478bd9Sstevel@tonic-gate /*
24637c478bd9Sstevel@tonic-gate  * verify_tbl
24647c478bd9Sstevel@tonic-gate  * Verify that no partition entries overlap or exceed the size of
24657c478bd9Sstevel@tonic-gate  * the disk.
24667c478bd9Sstevel@tonic-gate  */
2467bb16350dSlclee static int
2468bb16350dSlclee verify_tbl(void)
24697c478bd9Sstevel@tonic-gate {
2470342440ecSPrasad Singamsetty 	uint32_t	i, j, rsect, numsect;
24717c478bd9Sstevel@tonic-gate 	int	noMoreParts = 0;
24727c478bd9Sstevel@tonic-gate 	int	numParts = 0;
24737c478bd9Sstevel@tonic-gate 
24747c478bd9Sstevel@tonic-gate 	/* Make sure new entry does not overlap an existing entry */
2475bb16350dSlclee 	for (i = 0; i < FD_NUMPART - 1; i++) {
24767c478bd9Sstevel@tonic-gate 		if (Table[i].systid != UNUSED) {
24777c478bd9Sstevel@tonic-gate 			numParts++;
24787c478bd9Sstevel@tonic-gate 			/*
24797c478bd9Sstevel@tonic-gate 			 * No valid partitions allowed after an UNUSED  or
24807c478bd9Sstevel@tonic-gate 			 * EFI_PMBR part
24817c478bd9Sstevel@tonic-gate 			 */
24827c478bd9Sstevel@tonic-gate 			if (noMoreParts) {
24837c478bd9Sstevel@tonic-gate 				return (-1);
24847c478bd9Sstevel@tonic-gate 			}
24857c478bd9Sstevel@tonic-gate 
24867c478bd9Sstevel@tonic-gate 			/*
24877c478bd9Sstevel@tonic-gate 			 * EFI_PMBR partitions must be the only partition
24887c478bd9Sstevel@tonic-gate 			 * and must be Table entry 0
24897c478bd9Sstevel@tonic-gate 			 */
24907c478bd9Sstevel@tonic-gate 			if (Table[i].systid == EFI_PMBR) {
24917c478bd9Sstevel@tonic-gate 				if (i == 0) {
24927c478bd9Sstevel@tonic-gate 					noMoreParts = 1;
24937c478bd9Sstevel@tonic-gate 				} else {
24947c478bd9Sstevel@tonic-gate 					return (-1);
24957c478bd9Sstevel@tonic-gate 				}
24967c478bd9Sstevel@tonic-gate 
24977c478bd9Sstevel@tonic-gate 				if (Table[i].relsect != 1) {
2498bb16350dSlclee 					(void) fprintf(stderr, "ERROR: "
24997c478bd9Sstevel@tonic-gate 					    "Invalid starting sector "
25007c478bd9Sstevel@tonic-gate 					    "for EFI_PMBR partition:\n"
25017c478bd9Sstevel@tonic-gate 					    "relsect %d "
25027c478bd9Sstevel@tonic-gate 					    "(should be 1)\n",
25037c478bd9Sstevel@tonic-gate 					    Table[i].relsect);
25047c478bd9Sstevel@tonic-gate 
25057c478bd9Sstevel@tonic-gate 					return (-1);
25067c478bd9Sstevel@tonic-gate 				}
25077c478bd9Sstevel@tonic-gate 
25081237e847Slclee 				if (Table[i].numsect != dev_capacity - 1) {
2509bb16350dSlclee 					(void) fprintf(stderr, "ERROR: "
25107c478bd9Sstevel@tonic-gate 					    "EFI_PMBR partition must "
25117c478bd9Sstevel@tonic-gate 					    "encompass the entire "
2512bb16350dSlclee 					    "disk.\n numsect %d - "
25131237e847Slclee 					    "actual %llu\n",
25147c478bd9Sstevel@tonic-gate 					    Table[i].numsect,
25151237e847Slclee 					    dev_capacity - 1);
25167c478bd9Sstevel@tonic-gate 
25177c478bd9Sstevel@tonic-gate 					return (-1);
25187c478bd9Sstevel@tonic-gate 				}
25197c478bd9Sstevel@tonic-gate 			}
25207c478bd9Sstevel@tonic-gate 
25217c478bd9Sstevel@tonic-gate 			/* make sure the partition isn't larger than the disk */
2522*aa1b14e7SSheshadri Vasudevan 			rsect = LE_32(Table[i].relsect);
2523*aa1b14e7SSheshadri Vasudevan 			numsect = LE_32(Table[i].numsect);
2524342440ecSPrasad Singamsetty 
2525342440ecSPrasad Singamsetty 			if ((((diskaddr_t)rsect + numsect) > dev_capacity) ||
2526342440ecSPrasad Singamsetty 			    (((diskaddr_t)rsect + numsect) > DK_MAX_2TB)) {
25272f8ec719SBarry Harding 				if (!skip_verify[i])
25282f8ec719SBarry Harding 					return (-1);
25297c478bd9Sstevel@tonic-gate 			}
25307c478bd9Sstevel@tonic-gate 
2531bb16350dSlclee 			for (j = i + 1; j < FD_NUMPART; j++) {
25327c478bd9Sstevel@tonic-gate 				if (Table[j].systid != UNUSED) {
2533342440ecSPrasad Singamsetty 					uint32_t t_relsect =
2534*aa1b14e7SSheshadri Vasudevan 					    LE_32(Table[j].relsect);
2535342440ecSPrasad Singamsetty 					uint32_t t_numsect =
2536*aa1b14e7SSheshadri Vasudevan 					    LE_32(Table[j].numsect);
25377c478bd9Sstevel@tonic-gate 
25387c478bd9Sstevel@tonic-gate 					if (noMoreParts) {
2539bb16350dSlclee 						(void) fprintf(stderr,
25407c478bd9Sstevel@tonic-gate 						    "Cannot add partition to "
25417c478bd9Sstevel@tonic-gate 						    "table; no more partitions "
25427c478bd9Sstevel@tonic-gate 						    "allowed\n");
25437c478bd9Sstevel@tonic-gate 
25447c478bd9Sstevel@tonic-gate 						if (io_debug) {
2545bb16350dSlclee 							(void) fprintf(stderr,
25467c478bd9Sstevel@tonic-gate 							    "DEBUG: Current "
25477c478bd9Sstevel@tonic-gate 							    "partition:\t"
25487c478bd9Sstevel@tonic-gate 							    "%d:%d:%d:%d:%d:"
2549bb16350dSlclee 							    "%d:%d:%d:%d:%d\n"
25507c478bd9Sstevel@tonic-gate 							    "       Next "
25517c478bd9Sstevel@tonic-gate 							    "partition:\t\t"
25527c478bd9Sstevel@tonic-gate 							    "%d:%d:%d:%d:%d:"
2553bb16350dSlclee 							    "%d:%d:%d:%d:%d\n",
25547c478bd9Sstevel@tonic-gate 							    Table[i].systid,
25557c478bd9Sstevel@tonic-gate 							    Table[i].bootid,
25567c478bd9Sstevel@tonic-gate 							    Table[i].begcyl,
25577c478bd9Sstevel@tonic-gate 							    Table[i].beghead,
25587c478bd9Sstevel@tonic-gate 							    Table[i].begsect,
25597c478bd9Sstevel@tonic-gate 							    Table[i].endcyl,
25607c478bd9Sstevel@tonic-gate 							    Table[i].endhead,
25617c478bd9Sstevel@tonic-gate 							    Table[i].endsect,
25627c478bd9Sstevel@tonic-gate 							    Table[i].relsect,
25637c478bd9Sstevel@tonic-gate 							    Table[i].numsect,
25647c478bd9Sstevel@tonic-gate 							    Table[j].systid,
25657c478bd9Sstevel@tonic-gate 							    Table[j].bootid,
25667c478bd9Sstevel@tonic-gate 							    Table[j].begcyl,
25677c478bd9Sstevel@tonic-gate 							    Table[j].beghead,
25687c478bd9Sstevel@tonic-gate 							    Table[j].begsect,
25697c478bd9Sstevel@tonic-gate 							    Table[j].endcyl,
25707c478bd9Sstevel@tonic-gate 							    Table[j].endhead,
25717c478bd9Sstevel@tonic-gate 							    Table[j].endsect,
25727c478bd9Sstevel@tonic-gate 							    Table[j].relsect,
25737c478bd9Sstevel@tonic-gate 							    Table[j].numsect);
25747c478bd9Sstevel@tonic-gate 						}
25757c478bd9Sstevel@tonic-gate 
25767c478bd9Sstevel@tonic-gate 						return (-1);
25777c478bd9Sstevel@tonic-gate 					}
25787c478bd9Sstevel@tonic-gate 					if ((rsect >=
25797c478bd9Sstevel@tonic-gate 					    (t_relsect + t_numsect)) ||
2580bb16350dSlclee 					    ((rsect + numsect) <= t_relsect)) {
25817c478bd9Sstevel@tonic-gate 						continue;
25827c478bd9Sstevel@tonic-gate 					} else {
2583bb16350dSlclee 						(void) fprintf(stderr, "ERROR: "
25847c478bd9Sstevel@tonic-gate 						    "current partition overlaps"
25857c478bd9Sstevel@tonic-gate 						    " following partition\n");
25867c478bd9Sstevel@tonic-gate 
25877c478bd9Sstevel@tonic-gate 						return (-1);
25887c478bd9Sstevel@tonic-gate 					}
25897c478bd9Sstevel@tonic-gate 				}
25907c478bd9Sstevel@tonic-gate 			}
25917c478bd9Sstevel@tonic-gate 		} else {
25927c478bd9Sstevel@tonic-gate 			noMoreParts = 1;
25937c478bd9Sstevel@tonic-gate 		}
25947c478bd9Sstevel@tonic-gate 	}
25957c478bd9Sstevel@tonic-gate 	if (Table[i].systid != UNUSED) {
25962f8ec719SBarry Harding 		if (noMoreParts)
25972f8ec719SBarry Harding 			return (-1);
25982f8ec719SBarry Harding 		if (!skip_verify[i] &&
25992f8ec719SBarry Harding 		    ((((diskaddr_t)lel(Table[i].relsect) +
2600f85c7842SSuhasini Peddada 		    lel(Table[i].numsect)) > dev_capacity) ||
2601f85c7842SSuhasini Peddada 		    (((diskaddr_t)lel(Table[i].relsect) +
26022f8ec719SBarry Harding 		    lel(Table[i].numsect)) > DK_MAX_2TB))) {
26037c478bd9Sstevel@tonic-gate 			return (-1);
26047c478bd9Sstevel@tonic-gate 		}
26057c478bd9Sstevel@tonic-gate 	}
26067c478bd9Sstevel@tonic-gate 
26077c478bd9Sstevel@tonic-gate 	return (numParts);
26087c478bd9Sstevel@tonic-gate }
26097c478bd9Sstevel@tonic-gate 
26107c478bd9Sstevel@tonic-gate /*
26117c478bd9Sstevel@tonic-gate  * pars_fdisk
26127c478bd9Sstevel@tonic-gate  * Parse user-supplied data to set up fdisk partitions
26137c478bd9Sstevel@tonic-gate  * (-A, -D, -F).
26147c478bd9Sstevel@tonic-gate  */
2615bb16350dSlclee static int
2616bb16350dSlclee pars_fdisk(
2617bb16350dSlclee     char *line,
2618bb16350dSlclee     int *id, int *act,
2619bb16350dSlclee     int *bhead, int *bsect, int *bcyl,
2620bb16350dSlclee     int *ehead, int *esect, int *ecyl,
2621342440ecSPrasad Singamsetty     uint32_t *rsect, uint32_t *numsect)
26227c478bd9Sstevel@tonic-gate {
26237c478bd9Sstevel@tonic-gate 	int	i;
2624*aa1b14e7SSheshadri Vasudevan 	int64_t test;
2625*aa1b14e7SSheshadri Vasudevan 	char *tok, *p;
2626*aa1b14e7SSheshadri Vasudevan 	char buf[256];
2627*aa1b14e7SSheshadri Vasudevan 
26287c478bd9Sstevel@tonic-gate 	if (line[0] == '\0' || line[0] == '\n' || line[0] == '*')
26291237e847Slclee 		return (1);
26307c478bd9Sstevel@tonic-gate 	line[strlen(line)] = '\0';
26317c478bd9Sstevel@tonic-gate 	for (i = 0; i < strlen(line); i++) {
26327c478bd9Sstevel@tonic-gate 		if (line[i] == '\0') {
26337c478bd9Sstevel@tonic-gate 			break;
26347c478bd9Sstevel@tonic-gate 		} else if (line[i] == ':') {
26357c478bd9Sstevel@tonic-gate 			line[i] = ' ';
26367c478bd9Sstevel@tonic-gate 		}
26377c478bd9Sstevel@tonic-gate 	}
2638*aa1b14e7SSheshadri Vasudevan 	strncpy(buf, line, 256);
2639*aa1b14e7SSheshadri Vasudevan 	errno = 0;
2640*aa1b14e7SSheshadri Vasudevan 	tok = strtok(buf, ": \t\n");
2641*aa1b14e7SSheshadri Vasudevan 	while (tok != NULL) {
2642*aa1b14e7SSheshadri Vasudevan 		for (p = tok; *p != '\0'; p++) {
2643*aa1b14e7SSheshadri Vasudevan 			if (!isdigit(*p)) {
2644*aa1b14e7SSheshadri Vasudevan 				printf("Invalid input %s in line %s.\n",
2645*aa1b14e7SSheshadri Vasudevan 				    tok, line);
2646*aa1b14e7SSheshadri Vasudevan 				exit(1);
2647*aa1b14e7SSheshadri Vasudevan 			}
2648*aa1b14e7SSheshadri Vasudevan 		}
2649*aa1b14e7SSheshadri Vasudevan 
2650*aa1b14e7SSheshadri Vasudevan 		test = strtoll(tok, (char **)NULL, 10);
2651*aa1b14e7SSheshadri Vasudevan 		if ((test < 0) || (test > 0xFFFFFFFF) || (errno != 0)) {
2652*aa1b14e7SSheshadri Vasudevan 			printf("Invalid input %s in line %s.\n", tok, line);
2653*aa1b14e7SSheshadri Vasudevan 			exit(1);
2654*aa1b14e7SSheshadri Vasudevan 		}
2655*aa1b14e7SSheshadri Vasudevan 		tok = strtok(NULL, ": \t\n");
2656*aa1b14e7SSheshadri Vasudevan 	}
2657342440ecSPrasad Singamsetty 	if (sscanf(line, "%d %d %d %d %d %d %d %d %u %u",
26587c478bd9Sstevel@tonic-gate 	    id, act, bhead, bsect, bcyl, ehead, esect, ecyl,
26597c478bd9Sstevel@tonic-gate 	    rsect, numsect) != 10) {
26607c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Syntax error:\n	\"%s\".\n", line);
26617c478bd9Sstevel@tonic-gate 		exit(1);
26627c478bd9Sstevel@tonic-gate 	}
26637c478bd9Sstevel@tonic-gate 	return (0);
26647c478bd9Sstevel@tonic-gate }
26657c478bd9Sstevel@tonic-gate 
26667c478bd9Sstevel@tonic-gate /*
26677c478bd9Sstevel@tonic-gate  * validate_part
26687c478bd9Sstevel@tonic-gate  * Validate that a new partition does not start at sector 0. Only UNUSED
26697c478bd9Sstevel@tonic-gate  * partitions and previously existing partitions are allowed to start at 0.
26707c478bd9Sstevel@tonic-gate  */
2671bb16350dSlclee static int
2672342440ecSPrasad Singamsetty validate_part(int id, uint32_t rsect, uint32_t numsect)
26737c478bd9Sstevel@tonic-gate {
26747c478bd9Sstevel@tonic-gate 	int i;
26757c478bd9Sstevel@tonic-gate 	if ((id != UNUSED) && (rsect == 0)) {
26767c478bd9Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
26777c478bd9Sstevel@tonic-gate 			if ((Old_Table[i].systid == id) &&
2678*aa1b14e7SSheshadri Vasudevan 			    (Old_Table[i].relsect == LE_32(rsect)) &&
2679*aa1b14e7SSheshadri Vasudevan 			    (Old_Table[i].numsect == LE_32(numsect)))
26801237e847Slclee 				return (0);
26817c478bd9Sstevel@tonic-gate 		}
2682bb16350dSlclee 		(void) fprintf(stderr,
2683bb16350dSlclee 		    "New partition cannot start at sector 0\n");
26847c478bd9Sstevel@tonic-gate 		return (-1);
26857c478bd9Sstevel@tonic-gate 	}
2686*aa1b14e7SSheshadri Vasudevan #ifdef i386
2687*aa1b14e7SSheshadri Vasudevan 	if (id > FDISK_MAX_VALID_PART_ID) {
2688*aa1b14e7SSheshadri Vasudevan 		fprintf(stderr, "Invalid partition ID\n");
2689*aa1b14e7SSheshadri Vasudevan 		return (-1);
2690*aa1b14e7SSheshadri Vasudevan 	}
2691*aa1b14e7SSheshadri Vasudevan #endif
26927c478bd9Sstevel@tonic-gate 	return (0);
26937c478bd9Sstevel@tonic-gate }
26947c478bd9Sstevel@tonic-gate 
26957c478bd9Sstevel@tonic-gate /*
26967c478bd9Sstevel@tonic-gate  * stage0
26977c478bd9Sstevel@tonic-gate  * Print out interactive menu and process user input.
26987c478bd9Sstevel@tonic-gate  */
2699bb16350dSlclee static void
2700bb16350dSlclee stage0(void)
27017c478bd9Sstevel@tonic-gate {
2702*aa1b14e7SSheshadri Vasudevan #ifdef i386
2703*aa1b14e7SSheshadri Vasudevan 	int rval;
2704*aa1b14e7SSheshadri Vasudevan #endif
2705bb16350dSlclee 	dispmenu();
2706bb16350dSlclee 	for (;;) {
2707bb16350dSlclee 		(void) printf(Q_LINE);
2708bb16350dSlclee 		(void) printf("Enter Selection: ");
2709933c1499SBarry Harding 		(void) fgets(s, sizeof (s), stdin);
27107c478bd9Sstevel@tonic-gate 		rm_blanks(s);
2711*aa1b14e7SSheshadri Vasudevan #ifdef i386
2712*aa1b14e7SSheshadri Vasudevan 		while (!((s[0] > '0') && (s[0] < '8') &&
2713*aa1b14e7SSheshadri Vasudevan 		    ((s[1] == '\0') || (s[1] == '\n')))) {
2714*aa1b14e7SSheshadri Vasudevan #else
2715933c1499SBarry Harding 		while (!((s[0] > '0') && (s[0] < '7') &&
2716933c1499SBarry Harding 		    ((s[1] == '\0') || (s[1] == '\n')))) {
2717*aa1b14e7SSheshadri Vasudevan #endif
2718bb16350dSlclee 			(void) printf(E_LINE); /* Clear any previous error */
2719*aa1b14e7SSheshadri Vasudevan #ifdef i386
2720*aa1b14e7SSheshadri Vasudevan 			(void) printf(
2721*aa1b14e7SSheshadri Vasudevan 			    "Enter a one-digit number between 1 and 7.");
2722*aa1b14e7SSheshadri Vasudevan #else
2723bb16350dSlclee 			(void) printf(
2724bb16350dSlclee 			    "Enter a one-digit number between 1 and 6.");
2725*aa1b14e7SSheshadri Vasudevan #endif
2726bb16350dSlclee 			(void) printf(Q_LINE);
2727bb16350dSlclee 			(void) printf("Enter Selection: ");
2728933c1499SBarry Harding 			(void) fgets(s, sizeof (s), stdin);
27297c478bd9Sstevel@tonic-gate 			rm_blanks(s);
27307c478bd9Sstevel@tonic-gate 		}
2731bb16350dSlclee 		(void) printf(E_LINE);
27327c478bd9Sstevel@tonic-gate 		switch (s[0]) {
27337c478bd9Sstevel@tonic-gate 			case '1':
27347c478bd9Sstevel@tonic-gate 				if (pcreate() == -1)
27357c478bd9Sstevel@tonic-gate 					return;
27367c478bd9Sstevel@tonic-gate 				break;
27377c478bd9Sstevel@tonic-gate 			case '2':
27387c478bd9Sstevel@tonic-gate 				if (pchange() == -1)
27397c478bd9Sstevel@tonic-gate 					return;
27407c478bd9Sstevel@tonic-gate 				break;
27417c478bd9Sstevel@tonic-gate 			case '3':
27427c478bd9Sstevel@tonic-gate 				if (pdelete() == -1)
27437c478bd9Sstevel@tonic-gate 					return;
27447c478bd9Sstevel@tonic-gate 				break;
27457c478bd9Sstevel@tonic-gate 			case '4':
27467c478bd9Sstevel@tonic-gate 				if (ppartid() == -1)
27477c478bd9Sstevel@tonic-gate 					return;
27487c478bd9Sstevel@tonic-gate 				break;
2749*aa1b14e7SSheshadri Vasudevan #ifdef i386
2750*aa1b14e7SSheshadri Vasudevan 			case '5':
2751*aa1b14e7SSheshadri Vasudevan 				if (fdisk_ext_part_exists(epp)) {
2752*aa1b14e7SSheshadri Vasudevan 					ext_part_menu();
2753*aa1b14e7SSheshadri Vasudevan 				} else {
2754*aa1b14e7SSheshadri Vasudevan 					printf(Q_LINE);
2755*aa1b14e7SSheshadri Vasudevan 					printf("\nNo extended partition found"
2756*aa1b14e7SSheshadri Vasudevan 					    "\n");
2757*aa1b14e7SSheshadri Vasudevan 					printf("Press enter to continue\n");
2758*aa1b14e7SSheshadri Vasudevan 					ext_read_input(s);
2759*aa1b14e7SSheshadri Vasudevan 				}
2760*aa1b14e7SSheshadri Vasudevan 				break;
2761*aa1b14e7SSheshadri Vasudevan 			case '6':
2762*aa1b14e7SSheshadri Vasudevan 				/* update disk partition table, if changed */
2763*aa1b14e7SSheshadri Vasudevan 				if (TableChanged() == 1) {
2764*aa1b14e7SSheshadri Vasudevan 					copy_Table_to_Bootblk();
2765*aa1b14e7SSheshadri Vasudevan 					dev_mboot_write(0, Bootsect, sectsiz);
2766*aa1b14e7SSheshadri Vasudevan 				}
2767*aa1b14e7SSheshadri Vasudevan 
2768*aa1b14e7SSheshadri Vasudevan 				/*
2769*aa1b14e7SSheshadri Vasudevan 				 * If the VTOC table is wrong fix it
2770*aa1b14e7SSheshadri Vasudevan 				 * (truncate only)
2771*aa1b14e7SSheshadri Vasudevan 				 */
2772*aa1b14e7SSheshadri Vasudevan 				if (io_adjt) {
2773*aa1b14e7SSheshadri Vasudevan 					fix_slice();
2774*aa1b14e7SSheshadri Vasudevan 				}
2775*aa1b14e7SSheshadri Vasudevan 				if (!io_readonly) {
2776*aa1b14e7SSheshadri Vasudevan 					rval = fdisk_commit_ext_part(epp);
2777*aa1b14e7SSheshadri Vasudevan 					switch (rval) {
2778*aa1b14e7SSheshadri Vasudevan 						case FDISK_SUCCESS:
2779*aa1b14e7SSheshadri Vasudevan 							/* Success */
2780*aa1b14e7SSheshadri Vasudevan 							/* Fallthrough */
2781*aa1b14e7SSheshadri Vasudevan 						case FDISK_ENOEXTPART:
2782*aa1b14e7SSheshadri Vasudevan 							/* Nothing to do */
2783*aa1b14e7SSheshadri Vasudevan 							break;
2784*aa1b14e7SSheshadri Vasudevan 						case FDISK_EMOUNTED:
2785*aa1b14e7SSheshadri Vasudevan 							printf(Q_LINE);
2786*aa1b14e7SSheshadri Vasudevan 							preach_and_continue();
2787*aa1b14e7SSheshadri Vasudevan 							continue;
2788*aa1b14e7SSheshadri Vasudevan 						default:
2789*aa1b14e7SSheshadri Vasudevan 							perror("Commit failed");
2790*aa1b14e7SSheshadri Vasudevan 							exit(1);
2791*aa1b14e7SSheshadri Vasudevan 					}
2792*aa1b14e7SSheshadri Vasudevan 					libfdisk_fini(&epp);
2793*aa1b14e7SSheshadri Vasudevan 				}
2794*aa1b14e7SSheshadri Vasudevan 				(void) close(Dev);
2795*aa1b14e7SSheshadri Vasudevan 				exit(0);
2796*aa1b14e7SSheshadri Vasudevan #else
27977c478bd9Sstevel@tonic-gate 			case '5':
27987c478bd9Sstevel@tonic-gate 				/* update disk partition table, if changed */
27997c478bd9Sstevel@tonic-gate 				if (TableChanged() == 1) {
28007c478bd9Sstevel@tonic-gate 					copy_Table_to_Bootblk();
28017c478bd9Sstevel@tonic-gate 					dev_mboot_write(0, Bootsect, sectsiz);
28027c478bd9Sstevel@tonic-gate 				}
28037c478bd9Sstevel@tonic-gate 				/*
28047c478bd9Sstevel@tonic-gate 				 * If the VTOC table is wrong fix it
28057c478bd9Sstevel@tonic-gate 				 * (truncate only)
28067c478bd9Sstevel@tonic-gate 				 */
28077c478bd9Sstevel@tonic-gate 				if (io_adjt) {
28087c478bd9Sstevel@tonic-gate 					fix_slice();
28097c478bd9Sstevel@tonic-gate 				}
2810bb16350dSlclee 				(void) close(Dev);
28117c478bd9Sstevel@tonic-gate 				exit(0);
2812bb16350dSlclee 				/* FALLTHRU */
2813*aa1b14e7SSheshadri Vasudevan #endif
2814*aa1b14e7SSheshadri Vasudevan #ifdef i386
2815*aa1b14e7SSheshadri Vasudevan 			case '7':
2816*aa1b14e7SSheshadri Vasudevan #else
28177c478bd9Sstevel@tonic-gate 			case '6':
2818*aa1b14e7SSheshadri Vasudevan #endif
28197c478bd9Sstevel@tonic-gate 				/*
28207c478bd9Sstevel@tonic-gate 				 * If the VTOC table is wrong fix it
28217c478bd9Sstevel@tonic-gate 				 * (truncate only)
28227c478bd9Sstevel@tonic-gate 				 */
28237c478bd9Sstevel@tonic-gate 				if (io_adjt) {
28247c478bd9Sstevel@tonic-gate 					fix_slice();
28257c478bd9Sstevel@tonic-gate 				}
2826bb16350dSlclee 				(void) close(Dev);
28277c478bd9Sstevel@tonic-gate 				exit(0);
2828bb16350dSlclee 				/* FALLTHRU */
28297c478bd9Sstevel@tonic-gate 			default:
28307c478bd9Sstevel@tonic-gate 				break;
28317c478bd9Sstevel@tonic-gate 		}
28327c478bd9Sstevel@tonic-gate 		copy_Table_to_Bootblk();
28337c478bd9Sstevel@tonic-gate 		disptbl();
2834bb16350dSlclee 		dispmenu();
28357c478bd9Sstevel@tonic-gate 	}
28367c478bd9Sstevel@tonic-gate }
28377c478bd9Sstevel@tonic-gate 
28387c478bd9Sstevel@tonic-gate /*
28397c478bd9Sstevel@tonic-gate  * pcreate
28407c478bd9Sstevel@tonic-gate  * Create partition entry in the table (interactive mode).
28417c478bd9Sstevel@tonic-gate  */
2842bb16350dSlclee static int
2843bb16350dSlclee pcreate(void)
28447c478bd9Sstevel@tonic-gate {
2845bb16350dSlclee 	uchar_t tsystid = 'z';
28467c478bd9Sstevel@tonic-gate 	int i, j;
2847342440ecSPrasad Singamsetty 	uint32_t numsect;
28487c478bd9Sstevel@tonic-gate 	int retCode = 0;
2849*aa1b14e7SSheshadri Vasudevan #ifdef i386
2850*aa1b14e7SSheshadri Vasudevan 	int ext_part_present = 0;
2851*aa1b14e7SSheshadri Vasudevan #endif
28527c478bd9Sstevel@tonic-gate 
28537c478bd9Sstevel@tonic-gate 	i = 0;
2854bb16350dSlclee 	for (;;) {
28557c478bd9Sstevel@tonic-gate 		if (i == FD_NUMPART) {
2856bb16350dSlclee 			(void) printf(E_LINE);
2857bb16350dSlclee 			(void) printf(
2858bb16350dSlclee 			    "The partition table is full!\n"
2859bb16350dSlclee 			    "You must delete a partition before creating"
28607c478bd9Sstevel@tonic-gate 			    " a new one.\n");
28617c478bd9Sstevel@tonic-gate 			return (-1);
28627c478bd9Sstevel@tonic-gate 		}
28637c478bd9Sstevel@tonic-gate 		if (Table[i].systid == UNUSED) {
28647c478bd9Sstevel@tonic-gate 			break;
28657c478bd9Sstevel@tonic-gate 		}
28667c478bd9Sstevel@tonic-gate 		i++;
28677c478bd9Sstevel@tonic-gate 	}
28687c478bd9Sstevel@tonic-gate 
2869342440ecSPrasad Singamsetty 	numsect = 0;
28707c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
28717c478bd9Sstevel@tonic-gate 		if (Table[i].systid != UNUSED) {
2872*aa1b14e7SSheshadri Vasudevan 			numsect += LE_32(Table[i].numsect);
2873c26dc428SSheshadri Vasudevan 		}
2874*aa1b14e7SSheshadri Vasudevan #ifdef i386
2875*aa1b14e7SSheshadri Vasudevan 		/* Check if an extended partition already exists */
2876*aa1b14e7SSheshadri Vasudevan 		if (fdisk_is_dos_extended(Table[i].systid)) {
2877*aa1b14e7SSheshadri Vasudevan 			ext_part_present = 1;
2878*aa1b14e7SSheshadri Vasudevan 		}
2879*aa1b14e7SSheshadri Vasudevan #endif
2880342440ecSPrasad Singamsetty 		if (numsect >= chs_capacity) {
2881bb16350dSlclee 			(void) printf(E_LINE);
2882bb16350dSlclee 			(void) printf("There is no more room on the disk for"
28837c478bd9Sstevel@tonic-gate 			    " another partition.\n");
2884bb16350dSlclee 			(void) printf(
2885bb16350dSlclee 			    "You must delete a partition before creating"
28867c478bd9Sstevel@tonic-gate 			    " a new one.\n");
28877c478bd9Sstevel@tonic-gate 			return (-1);
28887c478bd9Sstevel@tonic-gate 		}
28897c478bd9Sstevel@tonic-gate 	}
28907c478bd9Sstevel@tonic-gate 	while (tsystid == 'z') {
2891342440ecSPrasad Singamsetty 
2892342440ecSPrasad Singamsetty 		/*
2893342440ecSPrasad Singamsetty 		 * The question here is expanding to more than what is
2894342440ecSPrasad Singamsetty 		 * allocated for question lines (Q_LINE) which garbles
2895342440ecSPrasad Singamsetty 		 * at least warning line. Clearing warning line as workaround
2896342440ecSPrasad Singamsetty 		 * for now.
2897342440ecSPrasad Singamsetty 		 */
2898342440ecSPrasad Singamsetty 
2899342440ecSPrasad Singamsetty 		(void) printf(W_LINE);
2900bb16350dSlclee 		(void) printf(Q_LINE);
2901bb16350dSlclee 		(void) printf(
2902bb16350dSlclee 		    "Select the partition type to create:\n"
2903bb16350dSlclee 		    "   1=SOLARIS2  2=UNIX        3=PCIXOS     4=Other\n"
2904bb16350dSlclee 		    "   5=DOS12     6=DOS16       7=DOSEXT     8=DOSBIG\n"
2905bb16350dSlclee 		    "   9=DOS16LBA  A=x86 Boot    B=Diagnostic C=FAT32\n"
2906bb16350dSlclee 		    "   D=FAT32LBA  E=DOSEXTLBA   F=EFI        0=Exit? ");
2907933c1499SBarry Harding 		(void) fgets(s, sizeof (s), stdin);
29087c478bd9Sstevel@tonic-gate 		rm_blanks(s);
2909933c1499SBarry Harding 		if ((s[1] != '\0') && (s[1] != '\n')) {
2910bb16350dSlclee 			(void) printf(E_LINE);
2911bb16350dSlclee 			(void) printf("Invalid selection, try again.");
29127c478bd9Sstevel@tonic-gate 			continue;
29137c478bd9Sstevel@tonic-gate 		}
29147c478bd9Sstevel@tonic-gate 		switch (s[0]) {
29157c478bd9Sstevel@tonic-gate 		case '0':		/* exit */
29161237e847Slclee 			(void) printf(E_LINE);
29171237e847Slclee 			return (-1);
29187c478bd9Sstevel@tonic-gate 		case '1':		/* Solaris partition */
29191237e847Slclee 			tsystid = SUNIXOS2;
29201237e847Slclee 			break;
29217c478bd9Sstevel@tonic-gate 		case '2':		/* UNIX partition */
29221237e847Slclee 			tsystid = UNIXOS;
29231237e847Slclee 			break;
29247c478bd9Sstevel@tonic-gate 		case '3':		/* PCIXOS partition */
29251237e847Slclee 			tsystid = PCIXOS;
29261237e847Slclee 			break;
29277c478bd9Sstevel@tonic-gate 		case '4':		/* OTHEROS System partition */
29281237e847Slclee 			tsystid = OTHEROS;
29291237e847Slclee 			break;
29307c478bd9Sstevel@tonic-gate 		case '5':
29311237e847Slclee 			tsystid = DOSOS12; /* DOS 12 bit fat */
29321237e847Slclee 			break;
29337c478bd9Sstevel@tonic-gate 		case '6':
29341237e847Slclee 			tsystid = DOSOS16; /* DOS 16 bit fat */
29351237e847Slclee 			break;
29367c478bd9Sstevel@tonic-gate 		case '7':
2937*aa1b14e7SSheshadri Vasudevan #ifdef i386
2938*aa1b14e7SSheshadri Vasudevan 			if (ext_part_present) {
2939*aa1b14e7SSheshadri Vasudevan 				printf(Q_LINE);
2940*aa1b14e7SSheshadri Vasudevan 				printf(E_LINE);
2941*aa1b14e7SSheshadri Vasudevan 				fprintf(stderr,
2942*aa1b14e7SSheshadri Vasudevan 				    "Extended partition already exists\n");
2943*aa1b14e7SSheshadri Vasudevan 				fprintf(stderr, "Press enter to continue\n");
2944*aa1b14e7SSheshadri Vasudevan 				ext_read_input(s);
2945*aa1b14e7SSheshadri Vasudevan 				continue;
2946*aa1b14e7SSheshadri Vasudevan 			}
2947*aa1b14e7SSheshadri Vasudevan #endif
29481237e847Slclee 			tsystid = EXTDOS;
29491237e847Slclee 			break;
29507c478bd9Sstevel@tonic-gate 		case '8':
29511237e847Slclee 			tsystid = DOSHUGE;
29521237e847Slclee 			break;
29537c478bd9Sstevel@tonic-gate 		case '9':
29541237e847Slclee 			tsystid = FDISK_FAT95;  /* FAT16, need extended int13 */
29551237e847Slclee 			break;
29567c478bd9Sstevel@tonic-gate 		case 'a':		/* x86 Boot partition */
29577c478bd9Sstevel@tonic-gate 		case 'A':
29581237e847Slclee 			tsystid = X86BOOT;
29591237e847Slclee 			break;
29607c478bd9Sstevel@tonic-gate 		case 'b':		/* Diagnostic boot partition */
29617c478bd9Sstevel@tonic-gate 		case 'B':
29621237e847Slclee 			tsystid = DIAGPART;
29631237e847Slclee 			break;
29647c478bd9Sstevel@tonic-gate 		case 'c':		/* FAT32 */
29657c478bd9Sstevel@tonic-gate 		case 'C':
29661237e847Slclee 			tsystid = FDISK_WINDOWS;
29671237e847Slclee 			break;
29687c478bd9Sstevel@tonic-gate 		case 'd':		/* FAT32 and need extended int13 */
29697c478bd9Sstevel@tonic-gate 		case 'D':
29701237e847Slclee 			tsystid = FDISK_EXT_WIN;
29711237e847Slclee 			break;
29727c478bd9Sstevel@tonic-gate 		case 'e':	/* Extended partition, need extended int13 */
29737c478bd9Sstevel@tonic-gate 		case 'E':
29741237e847Slclee 			tsystid = FDISK_EXTLBA;
29751237e847Slclee 			break;
29767c478bd9Sstevel@tonic-gate 		case 'f':
29777c478bd9Sstevel@tonic-gate 		case 'F':
29781237e847Slclee 			tsystid = EFI_PMBR;
29791237e847Slclee 			break;
29807c478bd9Sstevel@tonic-gate 		default:
29811237e847Slclee 			(void) printf(E_LINE);
29821237e847Slclee 			(void) printf("Invalid selection, try again.");
29831237e847Slclee 			continue;
29847c478bd9Sstevel@tonic-gate 		}
29857c478bd9Sstevel@tonic-gate 	}
29867c478bd9Sstevel@tonic-gate 
2987bb16350dSlclee 	(void) printf(E_LINE);
29887c478bd9Sstevel@tonic-gate 
29897c478bd9Sstevel@tonic-gate 	if (tsystid != EFI_PMBR) {
2990342440ecSPrasad Singamsetty 		(void) printf(W_LINE);
2991342440ecSPrasad Singamsetty 		if ((dev_capacity > DK_MAX_2TB))
2992342440ecSPrasad Singamsetty 			(void) printf("WARNING: Disk is larger than 2 TB. "
2993342440ecSPrasad Singamsetty 			    "Upper limit is 2 TB for non-EFI partition ID\n");
2994342440ecSPrasad Singamsetty 
29957c478bd9Sstevel@tonic-gate 		/* create the new partition */
29967c478bd9Sstevel@tonic-gate 		i = specify(tsystid);
29977c478bd9Sstevel@tonic-gate 
29987c478bd9Sstevel@tonic-gate 		if (i != -1) {
29997c478bd9Sstevel@tonic-gate 			/* see if it should be the active partition */
3000bb16350dSlclee 			(void) printf(E_LINE);
3001bb16350dSlclee 			(void) printf(Q_LINE);
30027c478bd9Sstevel@tonic-gate 
3003bb16350dSlclee 			(void) printf(
3004bb16350dSlclee 			    "Should this become the active partition? If "
3005bb16350dSlclee 			    "yes, it  will be activated\n"
3006bb16350dSlclee 			    "each time the computer is reset or turned on.\n"
3007bb16350dSlclee 			    "Please type \"y\" or \"n\". ");
30087c478bd9Sstevel@tonic-gate 
30097c478bd9Sstevel@tonic-gate 			if (yesno()) {
3010bb16350dSlclee 				(void) printf(E_LINE);
30117c478bd9Sstevel@tonic-gate 				for (j = 0; j < FD_NUMPART; j++) {
30127c478bd9Sstevel@tonic-gate 					if (j == i) {
30137c478bd9Sstevel@tonic-gate 						Table[j].bootid = ACTIVE;
3014bb16350dSlclee 						(void) printf(E_LINE);
3015bb16350dSlclee 						(void) printf(
3016bb16350dSlclee 						    "Partition %d is now "
30177c478bd9Sstevel@tonic-gate 						    "the active partition.",
3018bb16350dSlclee 						    j + 1);
30197c478bd9Sstevel@tonic-gate 					} else {
30207c478bd9Sstevel@tonic-gate 						Table[j].bootid = 0;
30217c478bd9Sstevel@tonic-gate 					}
30227c478bd9Sstevel@tonic-gate 				}
30237c478bd9Sstevel@tonic-gate 			} else {
30247c478bd9Sstevel@tonic-gate 				Table[i].bootid = 0;
30257c478bd9Sstevel@tonic-gate 			}
30267c478bd9Sstevel@tonic-gate 
3027*aa1b14e7SSheshadri Vasudevan #ifdef i386
3028*aa1b14e7SSheshadri Vasudevan 			/*
3029*aa1b14e7SSheshadri Vasudevan 			 * If partition created is an extended partition, null
3030*aa1b14e7SSheshadri Vasudevan 			 * out the first sector of the first cylinder of the
3031*aa1b14e7SSheshadri Vasudevan 			 * extended partition
3032*aa1b14e7SSheshadri Vasudevan 			 */
3033*aa1b14e7SSheshadri Vasudevan 			if (fdisk_is_dos_extended(Table[i].systid)) {
3034*aa1b14e7SSheshadri Vasudevan 				fdisk_init_ext_part(epp,
3035*aa1b14e7SSheshadri Vasudevan 				    LE_32(Table[i].relsect),
3036*aa1b14e7SSheshadri Vasudevan 				    LE_32(Table[i].numsect));
3037*aa1b14e7SSheshadri Vasudevan 			}
3038*aa1b14e7SSheshadri Vasudevan #endif
30397c478bd9Sstevel@tonic-gate 			/* set up the return code */
30407c478bd9Sstevel@tonic-gate 			i = 1;
30417c478bd9Sstevel@tonic-gate 		}
30427c478bd9Sstevel@tonic-gate 	} else {
30437c478bd9Sstevel@tonic-gate 		/*
30447c478bd9Sstevel@tonic-gate 		 * partitions of type EFI_PMBR must be the only partitions in
30457c478bd9Sstevel@tonic-gate 		 * the table
30467c478bd9Sstevel@tonic-gate 		 *
30477c478bd9Sstevel@tonic-gate 		 * First, make sure there were no errors the table is
30487c478bd9Sstevel@tonic-gate 		 * empty
30497c478bd9Sstevel@tonic-gate 		 */
30507c478bd9Sstevel@tonic-gate 		retCode = verify_tbl();
30517c478bd9Sstevel@tonic-gate 
30527c478bd9Sstevel@tonic-gate 		if (retCode < 0) {
3053bb16350dSlclee 			(void) fprintf(stderr,
30547c478bd9Sstevel@tonic-gate 			    "fdisk: Cannot create EFI partition table; \n"
30557c478bd9Sstevel@tonic-gate 			    "current partition table is invalid.\n");
30567c478bd9Sstevel@tonic-gate 			return (-1);
30577c478bd9Sstevel@tonic-gate 		} else if (retCode > 0) {
3058bb16350dSlclee 			(void) printf(
3059bb16350dSlclee 			    "An EFI partition must be the only partition on "
3060bb16350dSlclee 			    "disk.  You may manually delete existing\n"
3061bb16350dSlclee 			    "partitions, or fdisk can do it.\n"
3062bb16350dSlclee 			    "Do you want fdisk to destroy existing "
3063bb16350dSlclee 			    "partitions?\n"
3064bb16350dSlclee 			    "Please type \"y\" or \"n\". ");
30657c478bd9Sstevel@tonic-gate 
30667c478bd9Sstevel@tonic-gate 			if (yesno()) {
30677c478bd9Sstevel@tonic-gate 				nulltbl();
30687c478bd9Sstevel@tonic-gate 			} else {
30697c478bd9Sstevel@tonic-gate 				return (-1);
30707c478bd9Sstevel@tonic-gate 			}
30717c478bd9Sstevel@tonic-gate 		}
30727c478bd9Sstevel@tonic-gate 
30737c478bd9Sstevel@tonic-gate 		/* create the table entry - i should be 0 */
3074342440ecSPrasad Singamsetty 		i = insert_tbl(tsystid, 0, 0, 0, 0, 0, 0, 0, 1,
3075342440ecSPrasad Singamsetty 		    (dev_capacity > DK_MAX_2TB) ? DK_MAX_2TB:
3076342440ecSPrasad Singamsetty 		    (dev_capacity - 1));
30777c478bd9Sstevel@tonic-gate 
30787c478bd9Sstevel@tonic-gate 		if (i != 0) {
3079bb16350dSlclee 			(void) printf("Error creating EFI partition!!!\n");
30807c478bd9Sstevel@tonic-gate 			i = -1;
30817c478bd9Sstevel@tonic-gate 		} else {
30827c478bd9Sstevel@tonic-gate 
30837c478bd9Sstevel@tonic-gate 			/* EFI partitions are currently never active */
30847c478bd9Sstevel@tonic-gate 			Table[i].bootid = 0;
30857c478bd9Sstevel@tonic-gate 
30867c478bd9Sstevel@tonic-gate 			/* set up the return code */
30877c478bd9Sstevel@tonic-gate 			i = 1;
30887c478bd9Sstevel@tonic-gate 		}
30897c478bd9Sstevel@tonic-gate 	}
30907c478bd9Sstevel@tonic-gate 
30917c478bd9Sstevel@tonic-gate 	return (i);
30927c478bd9Sstevel@tonic-gate }
30937c478bd9Sstevel@tonic-gate 
30947c478bd9Sstevel@tonic-gate /*
30957c478bd9Sstevel@tonic-gate  * specify
30967c478bd9Sstevel@tonic-gate  * Query the user to specify the size of the new partition in
30977c478bd9Sstevel@tonic-gate  * terms of percentage of the disk or by specifying the starting
30987c478bd9Sstevel@tonic-gate  * cylinder and length in cylinders.
30997c478bd9Sstevel@tonic-gate  */
3100bb16350dSlclee static int
3101bb16350dSlclee specify(uchar_t tsystid)
31027c478bd9Sstevel@tonic-gate {
31031237e847Slclee 	int	i, j, percent = -1;
3104342440ecSPrasad Singamsetty 	int	cyl, cylen;
3105342440ecSPrasad Singamsetty 	diskaddr_t first_free, size_free;
3106342440ecSPrasad Singamsetty 	diskaddr_t max_free;
31071237e847Slclee 	int	cyl_size;
31087c478bd9Sstevel@tonic-gate 	struct ipart *partition[FD_NUMPART];
31097c478bd9Sstevel@tonic-gate 
31101237e847Slclee 	cyl_size = heads * sectors;
31111237e847Slclee 
31121237e847Slclee 	/*
31131237e847Slclee 	 * make a local copy of the partition table
31141237e847Slclee 	 * and sort it into relsect order
31151237e847Slclee 	 */
31161237e847Slclee 	for (i = 0; i < FD_NUMPART; i++)
31171237e847Slclee 		partition[i] = &Table[i];
31181237e847Slclee 
31191237e847Slclee 	for (i = 0; i < FD_NUMPART - 1; i++) {
31201237e847Slclee 		if (partition[i]->systid == UNUSED)
31211237e847Slclee 			break;
31221237e847Slclee 		for (j = i + 1; j < FD_NUMPART; j++) {
31231237e847Slclee 			if (partition[j]->systid == UNUSED)
31241237e847Slclee 				break;
3125*aa1b14e7SSheshadri Vasudevan 			if (LE_32(partition[j]->relsect) <
3126*aa1b14e7SSheshadri Vasudevan 			    LE_32(partition[i]->relsect)) {
31271237e847Slclee 				struct ipart *temp = partition[i];
31281237e847Slclee 				partition[i] = partition[j];
31291237e847Slclee 				partition[j] = temp;
31301237e847Slclee 			}
31311237e847Slclee 		}
31321237e847Slclee 	}
31331237e847Slclee 
3134342440ecSPrasad Singamsetty 
3135bb16350dSlclee 	(void) printf(Q_LINE);
3136bb16350dSlclee 	(void) printf(
3137bb16350dSlclee 	    "Specify the percentage of disk to use for this partition\n"
3138bb16350dSlclee 	    "(or type \"c\" to specify the size in cylinders). ");
3139933c1499SBarry Harding 	(void) fgets(s, sizeof (s), stdin);
31407c478bd9Sstevel@tonic-gate 	rm_blanks(s);
31417c478bd9Sstevel@tonic-gate 	if (s[0] != 'c') {	/* Specify size in percentage of disk */
31421237e847Slclee 		i = 0;
3143933c1499SBarry Harding 		while ((s[i] != '\0') && (s[i] != '\n')) {
31441237e847Slclee 			if (s[i] < '0' || s[i] > '9') {
31451237e847Slclee 				(void) printf(E_LINE);
31461237e847Slclee 				(void) printf("Invalid percentage value "
31471237e847Slclee 				    "specified; retry the operation.");
31481237e847Slclee 				return (-1);
31491237e847Slclee 			}
31501237e847Slclee 			i++;
31511237e847Slclee 			if (i > 3) {
31521237e847Slclee 				(void) printf(E_LINE);
31531237e847Slclee 				(void) printf("Invalid percentage value "
31541237e847Slclee 				    "specified; retry the operation.");
31551237e847Slclee 				return (-1);
31561237e847Slclee 			}
31577c478bd9Sstevel@tonic-gate 		}
31581237e847Slclee 		if ((percent = atoi(s)) > 100) {
31591237e847Slclee 			(void) printf(E_LINE);
31601237e847Slclee 			(void) printf(
31611237e847Slclee 			    "Percentage value is too large. The value must be"
31621237e847Slclee 			    " between 1 and 100;\nretry the operation.\n");
31631237e847Slclee 			return (-1);
31641237e847Slclee 		}
31651237e847Slclee 		if (percent < 1) {
31661237e847Slclee 			(void) printf(E_LINE);
31671237e847Slclee 			(void) printf(
31681237e847Slclee 			    "Percentage value is too small. The value must be"
31691237e847Slclee 			    " between 1 and 100;\nretry the operation.\n");
31701237e847Slclee 			return (-1);
31711237e847Slclee 		}
31721237e847Slclee 
31731237e847Slclee 		if (percent == 100)
3174342440ecSPrasad Singamsetty 			cylen = Numcyl_usable - 1;
31751237e847Slclee 		else
3176342440ecSPrasad Singamsetty 			cylen = (Numcyl_usable * percent) / 100;
31771237e847Slclee 
31781237e847Slclee 		/* Verify DOS12 partition doesn't exceed max size of 32MB. */
31791237e847Slclee 		if ((tsystid == DOSOS12) &&
31801237e847Slclee 		    ((long)((long)cylen * cyl_size) > MAXDOS)) {
31811237e847Slclee 			int n;
3182342440ecSPrasad Singamsetty 			n = MAXDOS * 100 / (int)(cyl_size) / Numcyl_usable;
31831237e847Slclee 			(void) printf(E_LINE);
31841237e847Slclee 			(void) printf("Maximum size for a DOS partition "
31851237e847Slclee 			    "is %d%%; retry the operation.",
31861237e847Slclee 			    n <= 100 ? n : 100);
31871237e847Slclee 			return (-1);
31881237e847Slclee 		}
31891237e847Slclee 
31901237e847Slclee 
31911237e847Slclee 		max_free = 0;
31921237e847Slclee 		for (i = 0; i < FD_NUMPART; i++) {
31931237e847Slclee 
31941237e847Slclee 			/*
31951237e847Slclee 			 * check for free space before partition i
31961237e847Slclee 			 * where i varies from 0 to 3
31971237e847Slclee 			 *
31981237e847Slclee 			 * freespace after partition 3 is unusable
31991237e847Slclee 			 * because there are no free partitions
32001237e847Slclee 			 *
32011237e847Slclee 			 * freespace begins at the end of previous partition
32021237e847Slclee 			 * or cylinder 1
32031237e847Slclee 			 */
32041237e847Slclee 			if (i) {
32051237e847Slclee 				/* Not an empty table */
3206*aa1b14e7SSheshadri Vasudevan 				first_free = LE_32(partition[i - 1]->relsect) +
3207*aa1b14e7SSheshadri Vasudevan 				    LE_32(partition[i - 1]->numsect);
32081237e847Slclee 			} else {
32091237e847Slclee 				first_free = cyl_size;
32101237e847Slclee 			}
32111237e847Slclee 
32121237e847Slclee 			/*
32131237e847Slclee 			 * freespace ends before the current partition
32141237e847Slclee 			 * or the end of the disk (chs end)
32151237e847Slclee 			 */
32161237e847Slclee 			if (partition[i]->systid == UNUSED) {
32171237e847Slclee 				size_free = chs_capacity - first_free;
32181237e847Slclee 			} else {
321933c00887SShidokht Yadegari 				/*
322033c00887SShidokht Yadegari 				 * Partition might start before cylinder 1.
322133c00887SShidokht Yadegari 				 * Make sure free space is not negative.
322233c00887SShidokht Yadegari 				 */
32231237e847Slclee 				size_free =
3224*aa1b14e7SSheshadri Vasudevan 				    (LE_32(partition[i]->relsect > first_free))
3225*aa1b14e7SSheshadri Vasudevan 				    ? (LE_32(partition[i]->relsect) -
3226*aa1b14e7SSheshadri Vasudevan 				    first_free) : 0;
32271237e847Slclee 			}
32281237e847Slclee 
32291237e847Slclee 			/* save largest free space */
32301237e847Slclee 			if (max_free < size_free)
32311237e847Slclee 				max_free = size_free;
32321237e847Slclee 
3233342440ecSPrasad Singamsetty 			if (((uint64_t)cylen * cyl_size) <= size_free) {
32341237e847Slclee 				/* We found a place to use */
32351237e847Slclee 				break;
32361237e847Slclee 			}
32371237e847Slclee 			if (partition[i]->systid == UNUSED) {
32381237e847Slclee 				(void) printf(E_LINE);
32391237e847Slclee 				max_free /= (cyl_size);
32401237e847Slclee 				(void) fprintf(stderr, "fdisk: "
3241342440ecSPrasad Singamsetty 				    "Maximum percentage available is %lld\n",
3242342440ecSPrasad Singamsetty 				    100 * max_free / Numcyl_usable);
32431237e847Slclee 				return (-1);
32441237e847Slclee 			}
32451237e847Slclee 		}
32461237e847Slclee 
3247bb16350dSlclee 		(void) printf(E_LINE);
32481237e847Slclee 		if (i >= FD_NUMPART) {
32491237e847Slclee 			(void) fprintf(stderr,
32501237e847Slclee 			    "fdisk: Partition table is full.\n");
32511237e847Slclee 			return (-1);
32521237e847Slclee 		}
32531237e847Slclee 
32541237e847Slclee 		if ((i = insert_tbl(tsystid, 0, 0, 0, 0, 0, 0, 0,
32551237e847Slclee 		    first_free, cylen * cyl_size)) >= 0)  {
32561237e847Slclee 			return (i);
32571237e847Slclee 		}
32587c478bd9Sstevel@tonic-gate 		return (-1);
32591237e847Slclee 	} else {
32607c478bd9Sstevel@tonic-gate 
32611237e847Slclee 		/* Specifying size in cylinders */
3262bb16350dSlclee 		(void) printf(E_LINE);
32631237e847Slclee 		(void) printf(Q_LINE);
32641237e847Slclee 		(void) printf("Enter starting cylinder number: ");
32651237e847Slclee 		if ((cyl = getcyl()) == -1) {
32661237e847Slclee 			(void) printf(E_LINE);
32671237e847Slclee 			(void) printf("Invalid number; retry the operation.");
32681237e847Slclee 			return (-1);
32691237e847Slclee 		}
32701237e847Slclee 		if (cyl == 0) {
32711237e847Slclee 			(void) printf(E_LINE);
32721237e847Slclee 			(void) printf(
32731237e847Slclee 			    "New partition cannot start at cylinder 0.\n");
32741237e847Slclee 			return (-1);
32751237e847Slclee 		}
3276342440ecSPrasad Singamsetty 
3277342440ecSPrasad Singamsetty 
3278342440ecSPrasad Singamsetty 		if (cyl >= Numcyl_usable) {
32791237e847Slclee 			(void) printf(E_LINE);
32801237e847Slclee 			(void) printf(
32811237e847Slclee 			    "Cylinder %d is out of bounds, "
32821237e847Slclee 			    "the maximum is %d.\n",
3283342440ecSPrasad Singamsetty 			    cyl, Numcyl_usable - 1);
32841237e847Slclee 			return (-1);
32851237e847Slclee 		}
3286342440ecSPrasad Singamsetty 
32871237e847Slclee 		(void) printf(Q_LINE);
32881237e847Slclee 		(void) printf("Enter partition size in cylinders: ");
32891237e847Slclee 		if ((cylen = getcyl()) == -1) {
32901237e847Slclee 			(void) printf(E_LINE);
32911237e847Slclee 			(void) printf("Invalid number, retry the operation.");
32921237e847Slclee 			return (-1);
32931237e847Slclee 		}
32941237e847Slclee 
32951237e847Slclee 		for (i = 0; i < FD_NUMPART; i++) {
32961237e847Slclee 			uint32_t	t_relsect, t_numsect;
32971237e847Slclee 
32981237e847Slclee 			if (partition[i]->systid == UNUSED)
32991237e847Slclee 				break;
3300*aa1b14e7SSheshadri Vasudevan 			t_relsect = LE_32(partition[i]->relsect);
3301*aa1b14e7SSheshadri Vasudevan 			t_numsect = LE_32(partition[i]->numsect);
33021237e847Slclee 
33031237e847Slclee 			if (cyl * cyl_size >= t_relsect &&
33041237e847Slclee 			    cyl * cyl_size < t_relsect + t_numsect) {
33051237e847Slclee 				(void) printf(E_LINE);
33061237e847Slclee 				(void) printf(
33071237e847Slclee 				    "Cylinder %d is already allocated"
33081237e847Slclee 				    "\nretry the operation.",
33091237e847Slclee 				    cyl);
33101237e847Slclee 				return (-1);
33111237e847Slclee 			}
33121237e847Slclee 
33131237e847Slclee 			if (cyl * cyl_size < t_relsect &&
33141237e847Slclee 			    (cyl + cylen - 1) * cyl_size > t_relsect) {
33151237e847Slclee 				(void) printf(E_LINE);
33161237e847Slclee 				(void) printf(
33171237e847Slclee 				    "Maximum size for partition is %u cylinders"
33181237e847Slclee 				    "\nretry the operation.",
33191237e847Slclee 				    (t_relsect - cyl * cyl_size) / cyl_size);
33201237e847Slclee 				return (-1);
33211237e847Slclee 			}
33221237e847Slclee 		}
33237c478bd9Sstevel@tonic-gate 
3324342440ecSPrasad Singamsetty 		/* Verify partition doesn't exceed disk size or 2 TB */
3325342440ecSPrasad Singamsetty 		if (cyl + cylen > Numcyl_usable) {
33261237e847Slclee 			(void) printf(E_LINE);
3327342440ecSPrasad Singamsetty 			if (Numcyl > Numcyl_usable) {
3328342440ecSPrasad Singamsetty 				(void) printf(
3329342440ecSPrasad Singamsetty 				    "Maximum size for partition is %d "
3330342440ecSPrasad Singamsetty 				    "cylinders; \nretry the operation.",
3331342440ecSPrasad Singamsetty 				    Numcyl_usable - cyl);
3332342440ecSPrasad Singamsetty 			} else {
3333342440ecSPrasad Singamsetty 				(void) printf(
3334342440ecSPrasad Singamsetty 				    "Maximum size for partition is %d "
3335342440ecSPrasad Singamsetty 				    "cylinders; \nretry the operation.",
3336342440ecSPrasad Singamsetty 				    Numcyl_usable - cyl);
3337342440ecSPrasad Singamsetty 			}
33381237e847Slclee 			return (-1);
33391237e847Slclee 		}
33401237e847Slclee 
33411237e847Slclee 		/* Verify DOS12 partition doesn't exceed max size of 32MB. */
33421237e847Slclee 		if ((tsystid == DOSOS12) &&
33431237e847Slclee 		    ((long)((long)cylen * cyl_size) > MAXDOS)) {
33441237e847Slclee 			(void) printf(E_LINE);
33451237e847Slclee 			(void) printf(
33461237e847Slclee 			    "Maximum size for a %s partition is %ld cylinders;"
33471237e847Slclee 			    "\nretry the operation.",
33481237e847Slclee 			    Dstr, MAXDOS / (int)(cyl_size));
33491237e847Slclee 			return (-1);
33501237e847Slclee 		}
33517c478bd9Sstevel@tonic-gate 
3352bb16350dSlclee 		(void) printf(E_LINE);
33531237e847Slclee 		i = insert_tbl(tsystid, 0, 0, 0, 0, 0, 0, 0,
33541237e847Slclee 		    cyl * cyl_size, cylen * cyl_size);
33551237e847Slclee 		if (i < 0)
33561237e847Slclee 			return (-1);
33571237e847Slclee 
33581237e847Slclee 		if (verify_tbl() < 0) {
33591237e847Slclee 			(void) printf(E_LINE);
33601237e847Slclee 			(void) printf("fdisk: Cannot create partition table\n");
33611237e847Slclee 			return (-1);
33621237e847Slclee 		}
33637c478bd9Sstevel@tonic-gate 
33641237e847Slclee 		return (i);
33657c478bd9Sstevel@tonic-gate 	}
33667c478bd9Sstevel@tonic-gate }
33677c478bd9Sstevel@tonic-gate 
33687c478bd9Sstevel@tonic-gate /*
33697c478bd9Sstevel@tonic-gate  * dispmenu
33707c478bd9Sstevel@tonic-gate  * Display command menu (interactive mode).
33717c478bd9Sstevel@tonic-gate  */
3372bb16350dSlclee static void
3373bb16350dSlclee dispmenu(void)
33747c478bd9Sstevel@tonic-gate {
3375bb16350dSlclee 	(void) printf(M_LINE);
3376*aa1b14e7SSheshadri Vasudevan #ifdef i386
3377*aa1b14e7SSheshadri Vasudevan 	(void) printf(
3378*aa1b14e7SSheshadri Vasudevan 	    "SELECT ONE OF THE FOLLOWING:\n"
3379*aa1b14e7SSheshadri Vasudevan 	    "   1. Create a partition\n"
3380*aa1b14e7SSheshadri Vasudevan 	    "   2. Specify the active partition\n"
3381*aa1b14e7SSheshadri Vasudevan 	    "   3. Delete a partition\n"
3382*aa1b14e7SSheshadri Vasudevan 	    "   4. Change between Solaris and Solaris2 Partition IDs\n"
3383*aa1b14e7SSheshadri Vasudevan 	    "   5. Edit/View extended partitions\n"
3384*aa1b14e7SSheshadri Vasudevan 	    "   6. Exit (update disk configuration and exit)\n"
3385*aa1b14e7SSheshadri Vasudevan 	    "   7. Cancel (exit without updating disk configuration)\n");
3386*aa1b14e7SSheshadri Vasudevan #else
3387bb16350dSlclee 	(void) printf(
3388bb16350dSlclee 	    "SELECT ONE OF THE FOLLOWING:\n"
3389bb16350dSlclee 	    "   1. Create a partition\n"
3390bb16350dSlclee 	    "   2. Specify the active partition\n"
3391bb16350dSlclee 	    "   3. Delete a partition\n"
3392bb16350dSlclee 	    "   4. Change between Solaris and Solaris2 Partition IDs\n"
3393bb16350dSlclee 	    "   5. Exit (update disk configuration and exit)\n"
3394bb16350dSlclee 	    "   6. Cancel (exit without updating disk configuration)\n");
3395*aa1b14e7SSheshadri Vasudevan #endif
33967c478bd9Sstevel@tonic-gate }
33977c478bd9Sstevel@tonic-gate 
33987c478bd9Sstevel@tonic-gate /*
33997c478bd9Sstevel@tonic-gate  * pchange
34007c478bd9Sstevel@tonic-gate  * Change the ACTIVE designation of a partition.
34017c478bd9Sstevel@tonic-gate  */
3402bb16350dSlclee static int
3403bb16350dSlclee pchange(void)
34047c478bd9Sstevel@tonic-gate {
34057c478bd9Sstevel@tonic-gate 	char s[80];
34067c478bd9Sstevel@tonic-gate 	int i, j;
34077c478bd9Sstevel@tonic-gate 
3408bb16350dSlclee 	for (;;) {
3409bb16350dSlclee 		(void) printf(Q_LINE);
34107c478bd9Sstevel@tonic-gate 			{
3411bb16350dSlclee 			(void) printf(
3412bb16350dSlclee 			    "Specify the partition number to boot from"
34137c478bd9Sstevel@tonic-gate 			    " (or specify 0 for none): ");
34147c478bd9Sstevel@tonic-gate 			}
3415933c1499SBarry Harding 		(void) fgets(s, sizeof (s), stdin);
34167c478bd9Sstevel@tonic-gate 		rm_blanks(s);
3417933c1499SBarry Harding 		if (((s[1] != '\0') && (s[1] != '\n')) ||
3418933c1499SBarry Harding 		    (s[0] < '0') || (s[0] > '4')) {
3419bb16350dSlclee 			(void) printf(E_LINE);
3420bb16350dSlclee 			(void) printf(
3421bb16350dSlclee 			    "Invalid response, please specify a number"
34227c478bd9Sstevel@tonic-gate 			    " between 0 and 4.\n");
34237c478bd9Sstevel@tonic-gate 		} else {
34247c478bd9Sstevel@tonic-gate 			break;
34257c478bd9Sstevel@tonic-gate 		}
34267c478bd9Sstevel@tonic-gate 	}
34277c478bd9Sstevel@tonic-gate 	if (s[0] == '0') {	/* No active partitions */
34287c478bd9Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
34297c478bd9Sstevel@tonic-gate 			if (Table[i].systid != UNUSED &&
34307c478bd9Sstevel@tonic-gate 			    Table[i].bootid == ACTIVE)
34317c478bd9Sstevel@tonic-gate 				Table[i].bootid = 0;
34327c478bd9Sstevel@tonic-gate 		}
3433bb16350dSlclee 		(void) printf(E_LINE);
3434bb16350dSlclee 			(void) printf(
3435bb16350dSlclee 			    "No partition is currently marked as active.");
34367c478bd9Sstevel@tonic-gate 		return (0);
34377c478bd9Sstevel@tonic-gate 	} else {	/* User has selected a partition to be active */
34387c478bd9Sstevel@tonic-gate 		i = s[0] - '1';
34397c478bd9Sstevel@tonic-gate 		if (Table[i].systid == UNUSED) {
3440bb16350dSlclee 			(void) printf(E_LINE);
3441bb16350dSlclee 			(void) printf("Partition does not exist.");
34427c478bd9Sstevel@tonic-gate 			return (-1);
34437c478bd9Sstevel@tonic-gate 		}
34447c478bd9Sstevel@tonic-gate 		/* a DOS-DATA or EXT-DOS partition cannot be active */
34457c478bd9Sstevel@tonic-gate 		else if ((Table[i].systid == DOSDATA) ||
34467c478bd9Sstevel@tonic-gate 		    (Table[i].systid == EXTDOS) ||
34477c478bd9Sstevel@tonic-gate 		    (Table[i].systid == FDISK_EXTLBA)) {
3448bb16350dSlclee 			(void) printf(E_LINE);
3449bb16350dSlclee 			(void) printf(
3450bb16350dSlclee 			    "DOS-DATA, EXT_DOS and EXT_DOS_LBA partitions "
34517c478bd9Sstevel@tonic-gate 			    "cannot be made active.\n");
3452bb16350dSlclee 			(void) printf("Select another partition.");
34537c478bd9Sstevel@tonic-gate 			return (-1);
34547c478bd9Sstevel@tonic-gate 		}
34557c478bd9Sstevel@tonic-gate 		Table[i].bootid = ACTIVE;
34567c478bd9Sstevel@tonic-gate 		for (j = 0; j < FD_NUMPART; j++) {
34577c478bd9Sstevel@tonic-gate 			if (j != i)
34587c478bd9Sstevel@tonic-gate 			Table[j].bootid = 0;
34597c478bd9Sstevel@tonic-gate 		}
34607c478bd9Sstevel@tonic-gate 	}
3461bb16350dSlclee 	(void) printf(E_LINE);
34627c478bd9Sstevel@tonic-gate 		{
3463bb16350dSlclee 		(void) printf(
3464bb16350dSlclee 		    "Partition %d is now active. The system will start up"
3465bb16350dSlclee 		    " from this\n", i + 1);
3466bb16350dSlclee 		(void) printf("partition after the next reboot.");
34677c478bd9Sstevel@tonic-gate 		}
34687c478bd9Sstevel@tonic-gate 	return (1);
34697c478bd9Sstevel@tonic-gate }
34707c478bd9Sstevel@tonic-gate 
34717c478bd9Sstevel@tonic-gate /*
34727c478bd9Sstevel@tonic-gate  * Change between SOLARIS and SOLARIS2 partition id
34737c478bd9Sstevel@tonic-gate  */
3474bb16350dSlclee static int
3475bb16350dSlclee ppartid(void)
34767c478bd9Sstevel@tonic-gate {
34777c478bd9Sstevel@tonic-gate 	char	*p, s[80];
34787c478bd9Sstevel@tonic-gate 	int	i;
34797c478bd9Sstevel@tonic-gate 
34807c478bd9Sstevel@tonic-gate 	for (;;) {
3481bb16350dSlclee 		(void) printf(Q_LINE);
3482bb16350dSlclee 		(void) printf("Specify the partition number to change"
34831237e847Slclee 		    " (or enter 0 to exit): ");
3484bb16350dSlclee 		if (!fgets(s, sizeof (s), stdin))
3485bb16350dSlclee 			return (1);
34867c478bd9Sstevel@tonic-gate 		i = strtol(s, &p, 10);
34877c478bd9Sstevel@tonic-gate 
34887c478bd9Sstevel@tonic-gate 		if (*p != '\n' || i < 0 || i > FD_NUMPART) {
3489bb16350dSlclee 			(void) printf(E_LINE);
3490bb16350dSlclee 			(void) printf(
3491bb16350dSlclee 			    "Invalid response, retry the operation.\n");
34927c478bd9Sstevel@tonic-gate 			continue;
34937c478bd9Sstevel@tonic-gate 		}
34947c478bd9Sstevel@tonic-gate 
34957c478bd9Sstevel@tonic-gate 		if (i == 0) {
34967c478bd9Sstevel@tonic-gate 			/* exit delete command */
3497bb16350dSlclee 			(void) printf(E_LINE); /* clear error message */
34987c478bd9Sstevel@tonic-gate 			return (1);
34997c478bd9Sstevel@tonic-gate 		}
35007c478bd9Sstevel@tonic-gate 
35017c478bd9Sstevel@tonic-gate 		i -= 1;
35027c478bd9Sstevel@tonic-gate 		if (Table[i].systid == SUNIXOS) {
35037c478bd9Sstevel@tonic-gate 			Table[i].systid = SUNIXOS2;
35047c478bd9Sstevel@tonic-gate 		} else if (Table[i].systid == SUNIXOS2) {
35057c478bd9Sstevel@tonic-gate 			Table[i].systid = SUNIXOS;
35067c478bd9Sstevel@tonic-gate 		} else {
3507bb16350dSlclee 			(void) printf(E_LINE);
3508bb16350dSlclee 			(void) printf(
3509bb16350dSlclee 			    "Partition %d is not a Solaris partition.",
35107c478bd9Sstevel@tonic-gate 			    i + 1);
35117c478bd9Sstevel@tonic-gate 			continue;
35127c478bd9Sstevel@tonic-gate 		}
35137c478bd9Sstevel@tonic-gate 
3514bb16350dSlclee 		(void) printf(E_LINE);
3515bb16350dSlclee 		(void) printf("Partition %d has been changed.", i + 1);
35167c478bd9Sstevel@tonic-gate 		return (1);
35177c478bd9Sstevel@tonic-gate 	}
35187c478bd9Sstevel@tonic-gate }
35197c478bd9Sstevel@tonic-gate 
35207c478bd9Sstevel@tonic-gate /*
35217c478bd9Sstevel@tonic-gate  * pdelete
35227c478bd9Sstevel@tonic-gate  * Remove partition entry from the table (interactive mode).
35237c478bd9Sstevel@tonic-gate  */
3524bb16350dSlclee static char
3525bb16350dSlclee pdelete(void)
35267c478bd9Sstevel@tonic-gate {
35277c478bd9Sstevel@tonic-gate 	char s[80];
35287c478bd9Sstevel@tonic-gate 	int i, j;
35297c478bd9Sstevel@tonic-gate 	char pactive;
35307c478bd9Sstevel@tonic-gate 
3531bb16350dSlclee DEL1:	(void) printf(Q_LINE);
3532bb16350dSlclee 	(void) printf("Specify the partition number to delete"
35337c478bd9Sstevel@tonic-gate 	    " (or enter 0 to exit): ");
3534933c1499SBarry Harding 	(void) fgets(s, sizeof (s), stdin);
35357c478bd9Sstevel@tonic-gate 	rm_blanks(s);
35367c478bd9Sstevel@tonic-gate 	if ((s[0] == '0')) {	/* exit delete command */
3537bb16350dSlclee 		(void) printf(E_LINE);	/* clear error message */
35387c478bd9Sstevel@tonic-gate 		return (1);
35397c478bd9Sstevel@tonic-gate 	}
35407c478bd9Sstevel@tonic-gate 	/* Accept only a single digit between 1 and 4 */
3541933c1499SBarry Harding 	if (((s[1] != '\0') && (s[1] != '\n')) ||
3542933c1499SBarry Harding 	    (i = atoi(s)) < 1 || i > FD_NUMPART) {
3543bb16350dSlclee 		(void) printf(E_LINE);
3544bb16350dSlclee 		(void) printf("Invalid response, retry the operation.\n");
35457c478bd9Sstevel@tonic-gate 		goto DEL1;
35467c478bd9Sstevel@tonic-gate 	} else {		/* Found a digit between 1 and 4 */
35477c478bd9Sstevel@tonic-gate 		--i;	/* Structure begins with element 0 */
35487c478bd9Sstevel@tonic-gate 	}
35497c478bd9Sstevel@tonic-gate 
35507c478bd9Sstevel@tonic-gate 	if (Table[i].systid == UNUSED) {
3551bb16350dSlclee 		(void) printf(E_LINE);
3552bb16350dSlclee 		(void) printf("Partition %d does not exist.", i + 1);
35537c478bd9Sstevel@tonic-gate 		return (-1);
35547c478bd9Sstevel@tonic-gate 	}
35557c478bd9Sstevel@tonic-gate 
3556*aa1b14e7SSheshadri Vasudevan #ifdef i386
3557*aa1b14e7SSheshadri Vasudevan 	if (fdisk_is_dos_extended(Table[i].systid) &&
3558*aa1b14e7SSheshadri Vasudevan 	    (Table[i].relsect == fdisk_get_ext_beg_sec(epp)) &&
3559*aa1b14e7SSheshadri Vasudevan 	    fdisk_get_logical_drive_count(epp)) {
3560*aa1b14e7SSheshadri Vasudevan 		(void) printf(Q_LINE);
3561*aa1b14e7SSheshadri Vasudevan 		(void) printf("There are logical drives inside the"
3562*aa1b14e7SSheshadri Vasudevan 		    " extended partition\n");
3563*aa1b14e7SSheshadri Vasudevan 		(void) printf("Are you sure of proceeding with deletion ?"
3564*aa1b14e7SSheshadri Vasudevan 		    " (type \"y\" or \"n\") ");
3565c26dc428SSheshadri Vasudevan 
3566*aa1b14e7SSheshadri Vasudevan 		(void) printf(E_LINE);
3567*aa1b14e7SSheshadri Vasudevan 		if (! yesno()) {
3568*aa1b14e7SSheshadri Vasudevan 			return (1);
3569*aa1b14e7SSheshadri Vasudevan 		}
3570*aa1b14e7SSheshadri Vasudevan 		if (fdisk_mounted_logical_drives(epp) == FDISK_EMOUNTED) {
3571*aa1b14e7SSheshadri Vasudevan 			(void) printf(Q_LINE);
3572*aa1b14e7SSheshadri Vasudevan 			(void) printf("There are mounted logical drives. "
3573*aa1b14e7SSheshadri Vasudevan 			    "Committing changes now can cause data loss or "
3574*aa1b14e7SSheshadri Vasudevan 			    "corruption. Unmount all logical drives and then "
3575*aa1b14e7SSheshadri Vasudevan 			    "try committing the changes again.\n");
3576*aa1b14e7SSheshadri Vasudevan 			(void) printf("Press enter to continue.\n");
3577*aa1b14e7SSheshadri Vasudevan 			ext_read_input(s);
3578*aa1b14e7SSheshadri Vasudevan 			return (1);
3579*aa1b14e7SSheshadri Vasudevan 		}
3580*aa1b14e7SSheshadri Vasudevan 		fdisk_delete_ext_part(epp);
3581*aa1b14e7SSheshadri Vasudevan 	} else {
3582*aa1b14e7SSheshadri Vasudevan #endif
3583*aa1b14e7SSheshadri Vasudevan 		(void) printf(Q_LINE);
3584*aa1b14e7SSheshadri Vasudevan 		(void) printf("Are you sure you want to delete partition %d?"
3585*aa1b14e7SSheshadri Vasudevan 		    " This will make all files and \n", i + 1);
3586*aa1b14e7SSheshadri Vasudevan 		(void) printf("programs in this partition inaccessible (type"
3587*aa1b14e7SSheshadri Vasudevan 		    " \"y\" or \"n\"). ");
3588*aa1b14e7SSheshadri Vasudevan 
3589*aa1b14e7SSheshadri Vasudevan 		(void) printf(E_LINE);
3590*aa1b14e7SSheshadri Vasudevan 		if (! yesno()) {
3591*aa1b14e7SSheshadri Vasudevan 			return (1);
3592*aa1b14e7SSheshadri Vasudevan 		}
3593*aa1b14e7SSheshadri Vasudevan #ifdef i386
35947c478bd9Sstevel@tonic-gate 	}
3595*aa1b14e7SSheshadri Vasudevan #endif
35967c478bd9Sstevel@tonic-gate 
35977c478bd9Sstevel@tonic-gate 	if (Table[i].bootid == ACTIVE) {
35987c478bd9Sstevel@tonic-gate 		pactive = 1;
35997c478bd9Sstevel@tonic-gate 	} else {
36007c478bd9Sstevel@tonic-gate 		pactive = 0;
36017c478bd9Sstevel@tonic-gate 	}
36027c478bd9Sstevel@tonic-gate 
36037c478bd9Sstevel@tonic-gate 	for (j = i; j < FD_NUMPART - 1; j++) {
36041237e847Slclee 		Table[j] = Table[j + 1];
36057c478bd9Sstevel@tonic-gate 	}
36067c478bd9Sstevel@tonic-gate 
36077c478bd9Sstevel@tonic-gate 	Table[j].systid = UNUSED;
36087c478bd9Sstevel@tonic-gate 	Table[j].numsect = 0;
36097c478bd9Sstevel@tonic-gate 	Table[j].relsect = 0;
36107c478bd9Sstevel@tonic-gate 	Table[j].bootid = 0;
3611bb16350dSlclee 	(void) printf(E_LINE);
3612bb16350dSlclee 	(void) printf("Partition %d has been deleted.", i + 1);
36137c478bd9Sstevel@tonic-gate 
36147c478bd9Sstevel@tonic-gate 	if (pactive) {
36151237e847Slclee 		(void) printf(" This was the active partition.");
36167c478bd9Sstevel@tonic-gate 	}
36177c478bd9Sstevel@tonic-gate 
36187c478bd9Sstevel@tonic-gate 	return (1);
36197c478bd9Sstevel@tonic-gate }
36207c478bd9Sstevel@tonic-gate 
36217c478bd9Sstevel@tonic-gate /*
36227c478bd9Sstevel@tonic-gate  * rm_blanks
36237c478bd9Sstevel@tonic-gate  * Remove blanks from strings of user responses.
36247c478bd9Sstevel@tonic-gate  */
3625bb16350dSlclee static void
3626bb16350dSlclee rm_blanks(char *s)
36277c478bd9Sstevel@tonic-gate {
36287c478bd9Sstevel@tonic-gate 	register int i, j;
36297c478bd9Sstevel@tonic-gate 
36307c478bd9Sstevel@tonic-gate 	for (i = 0; i < CBUFLEN; i++) {
36317c478bd9Sstevel@tonic-gate 		if ((s[i] == ' ') || (s[i] == '\t'))
36327c478bd9Sstevel@tonic-gate 			continue;
36337c478bd9Sstevel@tonic-gate 		else
36347c478bd9Sstevel@tonic-gate 			/* Found first non-blank character of the string */
36357c478bd9Sstevel@tonic-gate 			break;
36367c478bd9Sstevel@tonic-gate 	}
36377c478bd9Sstevel@tonic-gate 	for (j = 0; i < CBUFLEN; j++, i++) {
36387c478bd9Sstevel@tonic-gate 		if ((s[j] = s[i]) == '\0') {
36397c478bd9Sstevel@tonic-gate 			/* Reached end of string */
36407c478bd9Sstevel@tonic-gate 			return;
36417c478bd9Sstevel@tonic-gate 		}
36427c478bd9Sstevel@tonic-gate 	}
36437c478bd9Sstevel@tonic-gate }
36447c478bd9Sstevel@tonic-gate 
36457c478bd9Sstevel@tonic-gate /*
36467c478bd9Sstevel@tonic-gate  * getcyl
36477c478bd9Sstevel@tonic-gate  * Take the user-specified cylinder number and convert it from a
36487c478bd9Sstevel@tonic-gate  * string to a decimal value.
36497c478bd9Sstevel@tonic-gate  */
3650bb16350dSlclee static int
3651bb16350dSlclee getcyl(void)
36527c478bd9Sstevel@tonic-gate {
36537c478bd9Sstevel@tonic-gate int slen, i, j;
36547c478bd9Sstevel@tonic-gate unsigned int cyl;
3655933c1499SBarry Harding 	(void) fgets(s, sizeof (s), stdin);
36567c478bd9Sstevel@tonic-gate 	rm_blanks(s);
36577c478bd9Sstevel@tonic-gate 	slen = strlen(s);
3658933c1499SBarry Harding 	if (s[slen - 1] == '\n')
3659933c1499SBarry Harding 		slen--;
36607c478bd9Sstevel@tonic-gate 	j = 1;
36617c478bd9Sstevel@tonic-gate 	cyl = 0;
3662bb16350dSlclee 	for (i = slen - 1; i >= 0; i--) {
36637c478bd9Sstevel@tonic-gate 		if (s[i] < '0' || s[i] > '9') {
36647c478bd9Sstevel@tonic-gate 			return (-1);
36657c478bd9Sstevel@tonic-gate 		}
3666bb16350dSlclee 		cyl += (j * (s[i] - '0'));
36677c478bd9Sstevel@tonic-gate 		j *= 10;
36687c478bd9Sstevel@tonic-gate 	}
36697c478bd9Sstevel@tonic-gate 	return (cyl);
36707c478bd9Sstevel@tonic-gate }
36717c478bd9Sstevel@tonic-gate 
36727c478bd9Sstevel@tonic-gate /*
36737c478bd9Sstevel@tonic-gate  * disptbl
36747c478bd9Sstevel@tonic-gate  * Display the current fdisk table; determine percentage
36757c478bd9Sstevel@tonic-gate  * of the disk used for each partition.
36767c478bd9Sstevel@tonic-gate  */
3677bb16350dSlclee static void
3678bb16350dSlclee disptbl(void)
36797c478bd9Sstevel@tonic-gate {
36807c478bd9Sstevel@tonic-gate 	int i;
36817c478bd9Sstevel@tonic-gate 	unsigned int startcyl, endcyl, length, percent, remainder;
36827c478bd9Sstevel@tonic-gate 	char *stat, *type;
3683342440ecSPrasad Singamsetty 	int is_pmbr = 0;
36847c478bd9Sstevel@tonic-gate 
36857c478bd9Sstevel@tonic-gate 	if ((heads == 0) || (sectors == 0)) {
3686bb16350dSlclee 		(void) printf("WARNING: critical disk geometry information"
36871237e847Slclee 		    " missing!\n");
3688bb16350dSlclee 		(void) printf("\theads = %d, sectors = %d\n", heads, sectors);
36897c478bd9Sstevel@tonic-gate 		exit(1);
36907c478bd9Sstevel@tonic-gate 	}
36917c478bd9Sstevel@tonic-gate 
3692bb16350dSlclee 	(void) printf(HOME);
3693bb16350dSlclee 	(void) printf(T_LINE);
3694bb16350dSlclee 	(void) printf("             Total disk size is %d cylinders\n", Numcyl);
369565908c77Syu, larry liu - Sun Microsystems - Beijing China 	(void) printf("             Cylinder size is %d (%d byte) blocks\n\n",
369665908c77Syu, larry liu - Sun Microsystems - Beijing China 	    heads * sectors, sectsiz);
3697bb16350dSlclee 	(void) printf(
3698bb16350dSlclee 	    "                                               Cylinders\n");
3699bb16350dSlclee 	(void) printf(
3700bb16350dSlclee 	    "      Partition   Status    Type          Start   End   Length"
37017c478bd9Sstevel@tonic-gate 	    "    %%\n");
3702bb16350dSlclee 	(void) printf(
3703bb16350dSlclee 	    "      =========   ======    ============  =====   ===   ======"
37047c478bd9Sstevel@tonic-gate 	    "   ===");
37057c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
37067c478bd9Sstevel@tonic-gate 		if (Table[i].systid == UNUSED) {
3707bb16350dSlclee 			(void) printf("\n");
3708bb16350dSlclee 			(void) printf(CLR_LIN);
37097c478bd9Sstevel@tonic-gate 			continue;
37107c478bd9Sstevel@tonic-gate 		}
37117c478bd9Sstevel@tonic-gate 		if (Table[i].bootid == ACTIVE)
37121237e847Slclee 			stat = Actvstr;
37137c478bd9Sstevel@tonic-gate 		else
37141237e847Slclee 			stat = NAstr;
37157c478bd9Sstevel@tonic-gate 		switch (Table[i].systid) {
37167c478bd9Sstevel@tonic-gate 		case UNIXOS:
37171237e847Slclee 			type = Ustr;
37181237e847Slclee 			break;
37197c478bd9Sstevel@tonic-gate 		case SUNIXOS:
37201237e847Slclee 			type = SUstr;
37211237e847Slclee 			break;
37227c478bd9Sstevel@tonic-gate 		case SUNIXOS2:
37231237e847Slclee 			type = SU2str;
37241237e847Slclee 			break;
37257c478bd9Sstevel@tonic-gate 		case X86BOOT:
37261237e847Slclee 			type = X86str;
37271237e847Slclee 			break;
37287c478bd9Sstevel@tonic-gate 		case DOSOS12:
37291237e847Slclee 			type = Dstr;
37301237e847Slclee 			break;
37317c478bd9Sstevel@tonic-gate 		case DOSOS16:
37321237e847Slclee 			type = D16str;
37331237e847Slclee 			break;
37347c478bd9Sstevel@tonic-gate 		case EXTDOS:
37351237e847Slclee 			type = EDstr;
37361237e847Slclee 			break;
37377c478bd9Sstevel@tonic-gate 		case DOSDATA:
37381237e847Slclee 			type = DDstr;
37391237e847Slclee 			break;
37407c478bd9Sstevel@tonic-gate 		case DOSHUGE:
37411237e847Slclee 			type = DBstr;
37421237e847Slclee 			break;
37437c478bd9Sstevel@tonic-gate 		case PCIXOS:
37441237e847Slclee 			type = PCstr;
37451237e847Slclee 			break;
37467c478bd9Sstevel@tonic-gate 		case DIAGPART:
37471237e847Slclee 			type = DIAGstr;
37481237e847Slclee 			break;
37497c478bd9Sstevel@tonic-gate 		case FDISK_IFS:
37501237e847Slclee 			type = IFSstr;
37511237e847Slclee 			break;
37527c478bd9Sstevel@tonic-gate 		case FDISK_AIXBOOT:
37531237e847Slclee 			type = AIXstr;
37541237e847Slclee 			break;
37557c478bd9Sstevel@tonic-gate 		case FDISK_AIXDATA:
37561237e847Slclee 			type = AIXDstr;
37571237e847Slclee 			break;
37587c478bd9Sstevel@tonic-gate 		case FDISK_OS2BOOT:
37591237e847Slclee 			type = OS2str;
37601237e847Slclee 			break;
37617c478bd9Sstevel@tonic-gate 		case FDISK_WINDOWS:
37621237e847Slclee 			type = WINstr;
37631237e847Slclee 			break;
37647c478bd9Sstevel@tonic-gate 		case FDISK_EXT_WIN:
37651237e847Slclee 			type = EWINstr;
37661237e847Slclee 			break;
37677c478bd9Sstevel@tonic-gate 		case FDISK_FAT95:
37681237e847Slclee 			type = FAT95str;
37691237e847Slclee 			break;
37707c478bd9Sstevel@tonic-gate 		case FDISK_EXTLBA:
37711237e847Slclee 			type = EXTLstr;
37721237e847Slclee 			break;
37737c478bd9Sstevel@tonic-gate 		case FDISK_LINUX:
37741237e847Slclee 			type = LINUXstr;
37751237e847Slclee 			break;
37767c478bd9Sstevel@tonic-gate 		case FDISK_CPM:
37771237e847Slclee 			type = CPMstr;
37781237e847Slclee 			break;
3779*aa1b14e7SSheshadri Vasudevan 		case FDISK_NOVELL2:
3780*aa1b14e7SSheshadri Vasudevan 			type = NOV2str;
3781*aa1b14e7SSheshadri Vasudevan 			break;
37827c478bd9Sstevel@tonic-gate 		case FDISK_NOVELL3:
37831237e847Slclee 			type = NOVstr;
37841237e847Slclee 			break;
37857c478bd9Sstevel@tonic-gate 		case FDISK_QNX4:
37861237e847Slclee 			type = QNXstr;
37871237e847Slclee 			break;
37887c478bd9Sstevel@tonic-gate 		case FDISK_QNX42:
37891237e847Slclee 			type = QNX2str;
37901237e847Slclee 			break;
37917c478bd9Sstevel@tonic-gate 		case FDISK_QNX43:
37921237e847Slclee 			type = QNX3str;
37931237e847Slclee 			break;
37947c478bd9Sstevel@tonic-gate 		case FDISK_LINUXNAT:
37951237e847Slclee 			type = LINNATstr;
37961237e847Slclee 			break;
37977c478bd9Sstevel@tonic-gate 		case FDISK_NTFSVOL1:
37981237e847Slclee 			type = NTFSVOL1str;
37991237e847Slclee 			break;
38007c478bd9Sstevel@tonic-gate 		case FDISK_NTFSVOL2:
38011237e847Slclee 			type = NTFSVOL2str;
38021237e847Slclee 			break;
38037c478bd9Sstevel@tonic-gate 		case FDISK_BSD:
38041237e847Slclee 			type = BSDstr;
38051237e847Slclee 			break;
38067c478bd9Sstevel@tonic-gate 		case FDISK_NEXTSTEP:
38071237e847Slclee 			type = NEXTSTEPstr;
38081237e847Slclee 			break;
38097c478bd9Sstevel@tonic-gate 		case FDISK_BSDIFS:
38101237e847Slclee 			type = BSDIFSstr;
38111237e847Slclee 			break;
38127c478bd9Sstevel@tonic-gate 		case FDISK_BSDISWAP:
38131237e847Slclee 			type = BSDISWAPstr;
38141237e847Slclee 			break;
38157c478bd9Sstevel@tonic-gate 		case EFI_PMBR:
38161237e847Slclee 			type = EFIstr;
3817*aa1b14e7SSheshadri Vasudevan 			if (LE_32(Table[i].numsect) == DK_MAX_2TB)
3818342440ecSPrasad Singamsetty 				is_pmbr = 1;
3819342440ecSPrasad Singamsetty 
38201237e847Slclee 			break;
38217c478bd9Sstevel@tonic-gate 		default:
38221237e847Slclee 			type = Ostr;
38231237e847Slclee 			break;
38247c478bd9Sstevel@tonic-gate 		}
3825*aa1b14e7SSheshadri Vasudevan 		startcyl = LE_32(Table[i].relsect) /
38262b26c6eeSbharding 		    (unsigned long)(heads * sectors);
3827342440ecSPrasad Singamsetty 
3828*aa1b14e7SSheshadri Vasudevan 		if (LE_32(Table[i].numsect) == DK_MAX_2TB) {
3829342440ecSPrasad Singamsetty 			endcyl = Numcyl - 1;
3830342440ecSPrasad Singamsetty 			length = endcyl - startcyl + 1;
3831342440ecSPrasad Singamsetty 		} else {
3832*aa1b14e7SSheshadri Vasudevan 			length = LE_32(Table[i].numsect) /
3833342440ecSPrasad Singamsetty 			    (unsigned long)(heads * sectors);
3834*aa1b14e7SSheshadri Vasudevan 			if (LE_32(Table[i].numsect) %
3835342440ecSPrasad Singamsetty 			    (unsigned long)(heads * sectors))
3836342440ecSPrasad Singamsetty 				length++;
3837342440ecSPrasad Singamsetty 			endcyl = startcyl + length - 1;
3838342440ecSPrasad Singamsetty 		}
3839342440ecSPrasad Singamsetty 
3840342440ecSPrasad Singamsetty 		percent = length * 100 / Numcyl_usable;
3841342440ecSPrasad Singamsetty 		if ((remainder = (length * 100 % Numcyl_usable)) != 0) {
3842342440ecSPrasad Singamsetty 			if ((remainder * 100 / Numcyl_usable) > 50) {
38437c478bd9Sstevel@tonic-gate 				/* round up */
38447c478bd9Sstevel@tonic-gate 				percent++;
38457c478bd9Sstevel@tonic-gate 			}
38467c478bd9Sstevel@tonic-gate 			/* Else leave the percent as is since it's already */
38477c478bd9Sstevel@tonic-gate 			/* rounded down */
38487c478bd9Sstevel@tonic-gate 		}
38497c478bd9Sstevel@tonic-gate 		if (percent > 100)
38507c478bd9Sstevel@tonic-gate 			percent = 100;
3851bb16350dSlclee 		(void) printf(
3852bb16350dSlclee 		    "\n          %d       %s    %-12.12s   %4d  %4d    %4d"
3853bb16350dSlclee 		    "    %3d",
3854bb16350dSlclee 		    i + 1, stat, type, startcyl, endcyl, length, percent);
38557c478bd9Sstevel@tonic-gate 	}
3856342440ecSPrasad Singamsetty 
38577c478bd9Sstevel@tonic-gate 	/* Print warning message if table is empty */
38587c478bd9Sstevel@tonic-gate 	if (Table[0].systid == UNUSED) {
3859bb16350dSlclee 		(void) printf(W_LINE);
3860bb16350dSlclee 		(void) printf("WARNING: no partitions are defined!");
38617c478bd9Sstevel@tonic-gate 	} else {
38627c478bd9Sstevel@tonic-gate 		/* Clear the warning line */
3863bb16350dSlclee 		(void) printf(W_LINE);
3864342440ecSPrasad Singamsetty 
3865342440ecSPrasad Singamsetty 		/* Print warning if disk > 2TB and is not EFI PMBR */
3866342440ecSPrasad Singamsetty 		if (!is_pmbr && (dev_capacity > DK_MAX_2TB))
3867342440ecSPrasad Singamsetty 			(void) printf("WARNING: Disk is larger than 2 TB. "
3868342440ecSPrasad Singamsetty 			    "Upper limit is 2 TB for non-EFI partition ID\n");
38697c478bd9Sstevel@tonic-gate 	}
38707c478bd9Sstevel@tonic-gate }
38717c478bd9Sstevel@tonic-gate 
38727c478bd9Sstevel@tonic-gate /*
38737c478bd9Sstevel@tonic-gate  * print_Table
38747c478bd9Sstevel@tonic-gate  * Write the detailed fdisk table to standard error for
38757c478bd9Sstevel@tonic-gate  * the selected disk device.
38767c478bd9Sstevel@tonic-gate  */
3877bb16350dSlclee static void
3878bb16350dSlclee print_Table(void)
3879bb16350dSlclee {
38807c478bd9Sstevel@tonic-gate 	int i;
38817c478bd9Sstevel@tonic-gate 
3882bb16350dSlclee 	(void) fprintf(stderr,
38837c478bd9Sstevel@tonic-gate 	    "  SYSID ACT BHEAD BSECT BEGCYL   EHEAD ESECT ENDCYL   RELSECT"
38847c478bd9Sstevel@tonic-gate 	    "   NUMSECT\n");
38857c478bd9Sstevel@tonic-gate 
38867c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
3887bb16350dSlclee 		(void) fprintf(stderr, "  %-5d ", Table[i].systid);
3888bb16350dSlclee 		(void) fprintf(stderr, "%-3d ", Table[i].bootid);
3889bb16350dSlclee 		(void) fprintf(stderr, "%-5d ", Table[i].beghead);
3890bb16350dSlclee 		(void) fprintf(stderr, "%-5d ", Table[i].begsect & 0x3f);
38911237e847Slclee 		(void) fprintf(stderr, "%-8d ",
38921237e847Slclee 		    (((uint_t)Table[i].begsect & 0xc0) << 2) + Table[i].begcyl);
38937c478bd9Sstevel@tonic-gate 
3894bb16350dSlclee 		(void) fprintf(stderr, "%-5d ", Table[i].endhead);
3895bb16350dSlclee 		(void) fprintf(stderr, "%-5d ", Table[i].endsect & 0x3f);
38961237e847Slclee 		(void) fprintf(stderr, "%-8d ",
38971237e847Slclee 		    (((uint_t)Table[i].endsect & 0xc0) << 2) + Table[i].endcyl);
3898*aa1b14e7SSheshadri Vasudevan 		(void) fprintf(stderr, "%-10u ", LE_32(Table[i].relsect));
3899*aa1b14e7SSheshadri Vasudevan 		(void) fprintf(stderr, "%-10u\n", LE_32(Table[i].numsect));
39007c478bd9Sstevel@tonic-gate 
39017c478bd9Sstevel@tonic-gate 	}
39027c478bd9Sstevel@tonic-gate }
39037c478bd9Sstevel@tonic-gate 
39047c478bd9Sstevel@tonic-gate /*
39057c478bd9Sstevel@tonic-gate  * copy_Table_to_Old_Table
39067c478bd9Sstevel@tonic-gate  * Copy Table into Old_Table. The function only copies the systid,
39077c478bd9Sstevel@tonic-gate  * numsect, relsect, and bootid values because they are the only
39087c478bd9Sstevel@tonic-gate  * ones compared when determining if Table has changed.
39097c478bd9Sstevel@tonic-gate  */
3910bb16350dSlclee static void
3911bb16350dSlclee copy_Table_to_Old_Table(void)
39127c478bd9Sstevel@tonic-gate {
39137c478bd9Sstevel@tonic-gate 	int i;
39147c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++)  {
39151237e847Slclee 		(void) memcpy(&Old_Table[i], &Table[i], sizeof (Table[0]));
39167c478bd9Sstevel@tonic-gate 	}
39177c478bd9Sstevel@tonic-gate }
39187c478bd9Sstevel@tonic-gate 
39197c478bd9Sstevel@tonic-gate /*
39207c478bd9Sstevel@tonic-gate  * nulltbl
39217c478bd9Sstevel@tonic-gate  * Zero out the systid, numsect, relsect, and bootid values in the
39227c478bd9Sstevel@tonic-gate  * fdisk table.
39237c478bd9Sstevel@tonic-gate  */
3924bb16350dSlclee static void
3925bb16350dSlclee nulltbl(void)
39267c478bd9Sstevel@tonic-gate {
39277c478bd9Sstevel@tonic-gate 	int i;
39287c478bd9Sstevel@tonic-gate 
39297c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++)  {
39301237e847Slclee 		Table[i].systid = UNUSED;
3931*aa1b14e7SSheshadri Vasudevan 		Table[i].numsect = LE_32(UNUSED);
3932*aa1b14e7SSheshadri Vasudevan 		Table[i].relsect = LE_32(UNUSED);
39331237e847Slclee 		Table[i].bootid = 0;
39342f8ec719SBarry Harding 		skip_verify[i] = 0;
39357c478bd9Sstevel@tonic-gate 	}
39367c478bd9Sstevel@tonic-gate }
39377c478bd9Sstevel@tonic-gate 
39387c478bd9Sstevel@tonic-gate /*
39397c478bd9Sstevel@tonic-gate  * copy_Bootblk_to_Table
39407c478bd9Sstevel@tonic-gate  * Copy the bytes from the boot record to an internal "Table".
39417c478bd9Sstevel@tonic-gate  * All unused are padded with zeros starting at offset 446.
39427c478bd9Sstevel@tonic-gate  */
3943bb16350dSlclee static void
3944bb16350dSlclee copy_Bootblk_to_Table(void)
39457c478bd9Sstevel@tonic-gate {
39467c478bd9Sstevel@tonic-gate 	int i, j;
39477c478bd9Sstevel@tonic-gate 	char *bootptr;
39487c478bd9Sstevel@tonic-gate 	struct ipart iparts[FD_NUMPART];
39497c478bd9Sstevel@tonic-gate 
39507c478bd9Sstevel@tonic-gate 	/* Get an aligned copy of the partition tables */
3951bb16350dSlclee 	(void) memcpy(iparts, Bootblk->parts, sizeof (iparts));
39527c478bd9Sstevel@tonic-gate 	bootptr = (char *)iparts;	/* Points to start of partition table */
3953*aa1b14e7SSheshadri Vasudevan 	if (LE_16(Bootblk->signature) != MBB_MAGIC)  {
39547c478bd9Sstevel@tonic-gate 		/* Signature is missing */
39557c478bd9Sstevel@tonic-gate 		nulltbl();
3956bb16350dSlclee 		(void) memcpy(Bootblk->bootinst, &BootCod, BOOTSZ);
39577c478bd9Sstevel@tonic-gate 		return;
39587c478bd9Sstevel@tonic-gate 	}
39597c478bd9Sstevel@tonic-gate 	/*
39607c478bd9Sstevel@tonic-gate 	 * When the DOS fdisk command deletes a partition, it is not
39617c478bd9Sstevel@tonic-gate 	 * recognized by the old algorithm.  The algorithm that
39627c478bd9Sstevel@tonic-gate 	 * follows looks at each entry in the Bootrec and copies all
39637c478bd9Sstevel@tonic-gate 	 * those that are valid.
39647c478bd9Sstevel@tonic-gate 	 */
39657c478bd9Sstevel@tonic-gate 	j = 0;
39667c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
39677c478bd9Sstevel@tonic-gate 		if (iparts[i].systid == 0) {
39687c478bd9Sstevel@tonic-gate 			/* Null entry */
39697c478bd9Sstevel@tonic-gate 			bootptr += sizeof (struct ipart);
39707c478bd9Sstevel@tonic-gate 		} else {
3971bb16350dSlclee 			fill_ipart(bootptr, &Table[j]);
39727c478bd9Sstevel@tonic-gate 			j++;
39737c478bd9Sstevel@tonic-gate 			bootptr += sizeof (struct ipart);
39747c478bd9Sstevel@tonic-gate 		}
39757c478bd9Sstevel@tonic-gate 	}
39767c478bd9Sstevel@tonic-gate 	for (i = j; i < FD_NUMPART; i++) {
39777c478bd9Sstevel@tonic-gate 		Table[i].systid = UNUSED;
3978*aa1b14e7SSheshadri Vasudevan 		Table[i].numsect = LE_32(UNUSED);
3979*aa1b14e7SSheshadri Vasudevan 		Table[i].relsect = LE_32(UNUSED);
39807c478bd9Sstevel@tonic-gate 		Table[i].bootid = 0;
39817c478bd9Sstevel@tonic-gate 
39827c478bd9Sstevel@tonic-gate 	}
39837c478bd9Sstevel@tonic-gate 	/* For now, always replace the bootcode with ours */
3984bb16350dSlclee 	(void) memcpy(Bootblk->bootinst, &BootCod, BOOTSZ);
39857c478bd9Sstevel@tonic-gate 	copy_Table_to_Bootblk();
39867c478bd9Sstevel@tonic-gate }
39877c478bd9Sstevel@tonic-gate 
39887c478bd9Sstevel@tonic-gate /*
39897c478bd9Sstevel@tonic-gate  * fill_ipart
39907c478bd9Sstevel@tonic-gate  * Initialize ipart structure values.
39917c478bd9Sstevel@tonic-gate  */
3992bb16350dSlclee static void
39937c478bd9Sstevel@tonic-gate fill_ipart(char *bootptr, struct ipart *partp)
39947c478bd9Sstevel@tonic-gate {
39957c478bd9Sstevel@tonic-gate #ifdef sparc
39967c478bd9Sstevel@tonic-gate 	/* Packing struct ipart for Sparc */
3997bb16350dSlclee 	partp->bootid	= getbyte(&bootptr);
3998bb16350dSlclee 	partp->beghead	= getbyte(&bootptr);
3999bb16350dSlclee 	partp->begsect	= getbyte(&bootptr);
4000bb16350dSlclee 	partp->begcyl	= getbyte(&bootptr);
4001bb16350dSlclee 	partp->systid	= getbyte(&bootptr);
4002bb16350dSlclee 	partp->endhead	= getbyte(&bootptr);
4003bb16350dSlclee 	partp->endsect	= getbyte(&bootptr);
4004bb16350dSlclee 	partp->endcyl	= getbyte(&bootptr);
4005bb16350dSlclee 	partp->relsect	= (int32_t)getlong(&bootptr);
4006bb16350dSlclee 	partp->numsect	= (int32_t)getlong(&bootptr);
40077c478bd9Sstevel@tonic-gate #else
40087c478bd9Sstevel@tonic-gate 	*partp = *(struct ipart *)bootptr;
40097c478bd9Sstevel@tonic-gate #endif
40107c478bd9Sstevel@tonic-gate }
40117c478bd9Sstevel@tonic-gate 
40127c478bd9Sstevel@tonic-gate /*
4013bb16350dSlclee  * getbyte, getlong
40147c478bd9Sstevel@tonic-gate  * 	Get a byte, a short, or a long (SPARC only).
40157c478bd9Sstevel@tonic-gate  */
40167c478bd9Sstevel@tonic-gate #ifdef sparc
4017bb16350dSlclee uchar_t
4018bb16350dSlclee getbyte(char **bp)
40197c478bd9Sstevel@tonic-gate {
4020bb16350dSlclee 	uchar_t	b;
40217c478bd9Sstevel@tonic-gate 
4022bb16350dSlclee 	b = (uchar_t)**bp;
40237c478bd9Sstevel@tonic-gate 	*bp = *bp + 1;
40247c478bd9Sstevel@tonic-gate 	return (b);
40257c478bd9Sstevel@tonic-gate }
40267c478bd9Sstevel@tonic-gate 
4027bb16350dSlclee uint32_t
4028bb16350dSlclee getlong(char **bp)
40297c478bd9Sstevel@tonic-gate {
4030bb16350dSlclee 	int32_t	b, bh, bl;
40317c478bd9Sstevel@tonic-gate 
40327c478bd9Sstevel@tonic-gate 	bh = ((**bp) << 8) | *(*bp + 1);
40337c478bd9Sstevel@tonic-gate 	*bp += 2;
40347c478bd9Sstevel@tonic-gate 	bl = ((**bp) << 8) | *(*bp + 1);
40357c478bd9Sstevel@tonic-gate 	*bp += 2;
40367c478bd9Sstevel@tonic-gate 
40377c478bd9Sstevel@tonic-gate 	b = (bh << 16) | bl;
4038bb16350dSlclee 	return ((uint32_t)b);
40397c478bd9Sstevel@tonic-gate }
40407c478bd9Sstevel@tonic-gate #endif
40417c478bd9Sstevel@tonic-gate 
40427c478bd9Sstevel@tonic-gate /*
40437c478bd9Sstevel@tonic-gate  * copy_Table_to_Bootblk
404465908c77Syu, larry liu - Sun Microsystems - Beijing China  * Copy the table into the boot record. Note that the unused
40457c478bd9Sstevel@tonic-gate  * entries will always be the last ones in the table and they are
40467c478bd9Sstevel@tonic-gate  * marked with 100 in sysind. The the unused portion of the table
40477c478bd9Sstevel@tonic-gate  * is padded with zeros in the bytes after the used entries.
40487c478bd9Sstevel@tonic-gate  */
4049bb16350dSlclee static void
4050bb16350dSlclee copy_Table_to_Bootblk(void)
40517c478bd9Sstevel@tonic-gate {
40527c478bd9Sstevel@tonic-gate 	struct ipart *boot_ptr, *tbl_ptr;
40537c478bd9Sstevel@tonic-gate 
40547c478bd9Sstevel@tonic-gate 	boot_ptr = (struct ipart *)Bootblk->parts;
40557c478bd9Sstevel@tonic-gate 	tbl_ptr = (struct ipart *)&Table[0].bootid;
40567c478bd9Sstevel@tonic-gate 	for (; tbl_ptr < (struct ipart *)&Table[FD_NUMPART].bootid;
40577c478bd9Sstevel@tonic-gate 	    tbl_ptr++, boot_ptr++) {
40581237e847Slclee 		if (tbl_ptr->systid == UNUSED)
40591237e847Slclee 			(void) memset(boot_ptr, 0, sizeof (struct ipart));
40601237e847Slclee 		else
40611237e847Slclee 			(void) memcpy(boot_ptr, tbl_ptr, sizeof (struct ipart));
40627c478bd9Sstevel@tonic-gate 	}
4063*aa1b14e7SSheshadri Vasudevan 	Bootblk->signature = LE_16(MBB_MAGIC);
40647c478bd9Sstevel@tonic-gate }
40657c478bd9Sstevel@tonic-gate 
40667c478bd9Sstevel@tonic-gate /*
40677c478bd9Sstevel@tonic-gate  * TableChanged
40687c478bd9Sstevel@tonic-gate  * 	Check for any changes in the partition table.
40697c478bd9Sstevel@tonic-gate  */
4070bb16350dSlclee static int
4071bb16350dSlclee TableChanged(void)
40727c478bd9Sstevel@tonic-gate {
40737c478bd9Sstevel@tonic-gate 	int i, changed;
40747c478bd9Sstevel@tonic-gate 
40757c478bd9Sstevel@tonic-gate 	changed = 0;
40767c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
40771237e847Slclee 		if (memcmp(&Old_Table[i], &Table[i], sizeof (Table[0])) != 0) {
40781237e847Slclee 			/* Partition table changed, write back to disk */
40791237e847Slclee 			changed = 1;
40801237e847Slclee 		}
40817c478bd9Sstevel@tonic-gate 	}
40827c478bd9Sstevel@tonic-gate 
40837c478bd9Sstevel@tonic-gate 	return (changed);
40847c478bd9Sstevel@tonic-gate }
40857c478bd9Sstevel@tonic-gate 
40867c478bd9Sstevel@tonic-gate /*
40877c478bd9Sstevel@tonic-gate  * ffile_write
40887c478bd9Sstevel@tonic-gate  * 	Display contents of partition table to standard output or
40897c478bd9Sstevel@tonic-gate  *	another file name without writing it to the disk (-W file).
40907c478bd9Sstevel@tonic-gate  */
4091bb16350dSlclee static void
4092bb16350dSlclee ffile_write(char *file)
40937c478bd9Sstevel@tonic-gate {
40947c478bd9Sstevel@tonic-gate 	register int	i;
40957c478bd9Sstevel@tonic-gate 	FILE *fp;
40967c478bd9Sstevel@tonic-gate 
40977c478bd9Sstevel@tonic-gate 	/*
40987c478bd9Sstevel@tonic-gate 	 * If file isn't standard output, then it's a file name.
40997c478bd9Sstevel@tonic-gate 	 * Open file and write it.
41007c478bd9Sstevel@tonic-gate 	 */
41017c478bd9Sstevel@tonic-gate 	if (file != (char *)stdout) {
41021237e847Slclee 		if ((fp = fopen(file, "w")) == NULL) {
41031237e847Slclee 			(void) fprintf(stderr,
41041237e847Slclee 			    "fdisk: Cannot open output file %s.\n",
41051237e847Slclee 			    file);
41061237e847Slclee 			exit(1);
41071237e847Slclee 		}
41087c478bd9Sstevel@tonic-gate 	}
41097c478bd9Sstevel@tonic-gate 	else
41101237e847Slclee 		fp = stdout;
41117c478bd9Sstevel@tonic-gate 
41127c478bd9Sstevel@tonic-gate 	/*
41137c478bd9Sstevel@tonic-gate 	 * Write the fdisk table information
41147c478bd9Sstevel@tonic-gate 	 */
4115bb16350dSlclee 	(void) fprintf(fp, "\n* %s default fdisk table\n", Dfltdev);
4116bb16350dSlclee 	(void) fprintf(fp, "* Dimensions:\n");
4117bb16350dSlclee 	(void) fprintf(fp, "*   %4d bytes/sector\n", sectsiz);
4118bb16350dSlclee 	(void) fprintf(fp, "*   %4d sectors/track\n", sectors);
4119bb16350dSlclee 	(void) fprintf(fp, "*   %4d tracks/cylinder\n", heads);
4120bb16350dSlclee 	(void) fprintf(fp, "*   %4d cylinders\n", Numcyl);
4121bb16350dSlclee 	(void) fprintf(fp, "*\n");
41227c478bd9Sstevel@tonic-gate 	/* Write virtual (HBA) geometry, if required	*/
41237c478bd9Sstevel@tonic-gate 	if (v_flag) {
4124bb16350dSlclee 		(void) fprintf(fp, "* HBA Dimensions:\n");
4125bb16350dSlclee 		(void) fprintf(fp, "*   %4d bytes/sector\n", sectsiz);
4126bb16350dSlclee 		(void) fprintf(fp, "*   %4d sectors/track\n", hba_sectors);
4127bb16350dSlclee 		(void) fprintf(fp, "*   %4d tracks/cylinder\n", hba_heads);
4128bb16350dSlclee 		(void) fprintf(fp, "*   %4d cylinders\n", hba_Numcyl);
4129bb16350dSlclee 		(void) fprintf(fp, "*\n");
4130bb16350dSlclee 	}
4131bb16350dSlclee 	(void) fprintf(fp, "* systid:\n");
4132bb16350dSlclee 	(void) fprintf(fp, "*    1: DOSOS12\n");
4133bb16350dSlclee 	(void) fprintf(fp, "*    2: PCIXOS\n");
4134bb16350dSlclee 	(void) fprintf(fp, "*    4: DOSOS16\n");
4135bb16350dSlclee 	(void) fprintf(fp, "*    5: EXTDOS\n");
4136bb16350dSlclee 	(void) fprintf(fp, "*    6: DOSBIG\n");
4137bb16350dSlclee 	(void) fprintf(fp, "*    7: FDISK_IFS\n");
4138bb16350dSlclee 	(void) fprintf(fp, "*    8: FDISK_AIXBOOT\n");
4139bb16350dSlclee 	(void) fprintf(fp, "*    9: FDISK_AIXDATA\n");
4140bb16350dSlclee 	(void) fprintf(fp, "*   10: FDISK_0S2BOOT\n");
4141bb16350dSlclee 	(void) fprintf(fp, "*   11: FDISK_WINDOWS\n");
4142bb16350dSlclee 	(void) fprintf(fp, "*   12: FDISK_EXT_WIN\n");
4143bb16350dSlclee 	(void) fprintf(fp, "*   14: FDISK_FAT95\n");
4144bb16350dSlclee 	(void) fprintf(fp, "*   15: FDISK_EXTLBA\n");
4145bb16350dSlclee 	(void) fprintf(fp, "*   18: DIAGPART\n");
4146bb16350dSlclee 	(void) fprintf(fp, "*   65: FDISK_LINUX\n");
4147bb16350dSlclee 	(void) fprintf(fp, "*   82: FDISK_CPM\n");
4148bb16350dSlclee 	(void) fprintf(fp, "*   86: DOSDATA\n");
4149bb16350dSlclee 	(void) fprintf(fp, "*   98: OTHEROS\n");
4150bb16350dSlclee 	(void) fprintf(fp, "*   99: UNIXOS\n");
4151*aa1b14e7SSheshadri Vasudevan 	(void) fprintf(fp, "*  100: FDISK_NOVELL2\n");
4152bb16350dSlclee 	(void) fprintf(fp, "*  101: FDISK_NOVELL3\n");
4153bb16350dSlclee 	(void) fprintf(fp, "*  119: FDISK_QNX4\n");
4154bb16350dSlclee 	(void) fprintf(fp, "*  120: FDISK_QNX42\n");
4155bb16350dSlclee 	(void) fprintf(fp, "*  121: FDISK_QNX43\n");
4156bb16350dSlclee 	(void) fprintf(fp, "*  130: SUNIXOS\n");
4157bb16350dSlclee 	(void) fprintf(fp, "*  131: FDISK_LINUXNAT\n");
4158bb16350dSlclee 	(void) fprintf(fp, "*  134: FDISK_NTFSVOL1\n");
4159bb16350dSlclee 	(void) fprintf(fp, "*  135: FDISK_NTFSVOL2\n");
4160bb16350dSlclee 	(void) fprintf(fp, "*  165: FDISK_BSD\n");
4161bb16350dSlclee 	(void) fprintf(fp, "*  167: FDISK_NEXTSTEP\n");
4162bb16350dSlclee 	(void) fprintf(fp, "*  183: FDISK_BSDIFS\n");
4163bb16350dSlclee 	(void) fprintf(fp, "*  184: FDISK_BSDISWAP\n");
4164bb16350dSlclee 	(void) fprintf(fp, "*  190: X86BOOT\n");
4165bb16350dSlclee 	(void) fprintf(fp, "*  191: SUNIXOS2\n");
4166bb16350dSlclee 	(void) fprintf(fp, "*  238: EFI_PMBR\n");
4167bb16350dSlclee 	(void) fprintf(fp, "*  239: EFI_FS\n");
4168bb16350dSlclee 	(void) fprintf(fp, "*\n");
4169bb16350dSlclee 	(void) fprintf(fp,
41707c478bd9Sstevel@tonic-gate 	    "\n* Id    Act  Bhead  Bsect  Bcyl    Ehead  Esect  Ecyl"
4171342440ecSPrasad Singamsetty 	    "    Rsect      Numsect\n");
4172342440ecSPrasad Singamsetty 
41737c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
4174*aa1b14e7SSheshadri Vasudevan 		(void) fprintf(fp,
4175*aa1b14e7SSheshadri Vasudevan 		    "  %-5d %-4d %-6d %-6d %-7d %-6d %-6d %-7d %-10u"
4176*aa1b14e7SSheshadri Vasudevan 		    " %-10u\n",
4177*aa1b14e7SSheshadri Vasudevan 		    Table[i].systid,
4178*aa1b14e7SSheshadri Vasudevan 		    Table[i].bootid,
4179*aa1b14e7SSheshadri Vasudevan 		    Table[i].beghead,
4180*aa1b14e7SSheshadri Vasudevan 		    Table[i].begsect & 0x3f,
4181*aa1b14e7SSheshadri Vasudevan 		    ((Table[i].begcyl & 0xff) | ((Table[i].begsect &
4182*aa1b14e7SSheshadri Vasudevan 		    0xc0) << 2)),
4183*aa1b14e7SSheshadri Vasudevan 		    Table[i].endhead,
4184*aa1b14e7SSheshadri Vasudevan 		    Table[i].endsect & 0x3f,
4185*aa1b14e7SSheshadri Vasudevan 		    ((Table[i].endcyl & 0xff) | ((Table[i].endsect &
4186*aa1b14e7SSheshadri Vasudevan 		    0xc0) << 2)),
4187*aa1b14e7SSheshadri Vasudevan 		    LE_32(Table[i].relsect),
4188*aa1b14e7SSheshadri Vasudevan 		    LE_32(Table[i].numsect));
4189*aa1b14e7SSheshadri Vasudevan 	}
4190*aa1b14e7SSheshadri Vasudevan #ifdef i386
4191*aa1b14e7SSheshadri Vasudevan 	if (fdisk_ext_part_exists(epp)) {
4192*aa1b14e7SSheshadri Vasudevan 		struct ipart ext_tab;
4193*aa1b14e7SSheshadri Vasudevan 		logical_drive_t *temp;
4194*aa1b14e7SSheshadri Vasudevan 		uint32_t rsect, numsect, tempsect = 0;
4195*aa1b14e7SSheshadri Vasudevan 		for (temp = fdisk_get_ld_head(epp); temp != NULL;
4196*aa1b14e7SSheshadri Vasudevan 		    temp = temp->next) {
4197*aa1b14e7SSheshadri Vasudevan 			ext_tab = temp->parts[0];
4198*aa1b14e7SSheshadri Vasudevan 			rsect = tempsect + LE_32(ext_tab.relsect) +
4199*aa1b14e7SSheshadri Vasudevan 			    fdisk_get_ext_beg_sec(epp);
4200*aa1b14e7SSheshadri Vasudevan 			numsect = LE_32(ext_tab.numsect);
4201*aa1b14e7SSheshadri Vasudevan 			tempsect = LE_32(temp->parts[1].relsect);
4202bb16350dSlclee 			(void) fprintf(fp,
4203*aa1b14e7SSheshadri Vasudevan 			    "  %-5d %-4d %-6d %-6d %-7d %-6d %-6d "
4204*aa1b14e7SSheshadri Vasudevan 			    "%-7d %-8u %-8u\n",
4205*aa1b14e7SSheshadri Vasudevan 			    ext_tab.systid,
4206*aa1b14e7SSheshadri Vasudevan 			    ext_tab.bootid,
4207*aa1b14e7SSheshadri Vasudevan 			    ext_tab.beghead,
4208*aa1b14e7SSheshadri Vasudevan 			    ext_tab.begsect & 0x3f,
4209*aa1b14e7SSheshadri Vasudevan 			    ((ext_tab.begcyl & 0xff) |
4210*aa1b14e7SSheshadri Vasudevan 			    ((ext_tab.begsect & 0xc0) << 2)),
4211*aa1b14e7SSheshadri Vasudevan 			    ext_tab.endhead,
4212*aa1b14e7SSheshadri Vasudevan 			    ext_tab.endsect & 0x3f,
4213*aa1b14e7SSheshadri Vasudevan 			    ((ext_tab.endcyl & 0xff) |
4214*aa1b14e7SSheshadri Vasudevan 			    ((ext_tab.endsect & 0xc0) << 2)),
4215*aa1b14e7SSheshadri Vasudevan 			    rsect,
4216*aa1b14e7SSheshadri Vasudevan 			    numsect);
4217*aa1b14e7SSheshadri Vasudevan 		}
42187c478bd9Sstevel@tonic-gate 	}
4219*aa1b14e7SSheshadri Vasudevan #endif
4220*aa1b14e7SSheshadri Vasudevan 
42217c478bd9Sstevel@tonic-gate 	if (fp != stdout)
4222bb16350dSlclee 		(void) fclose(fp);
42237c478bd9Sstevel@tonic-gate }
42247c478bd9Sstevel@tonic-gate 
42257c478bd9Sstevel@tonic-gate /*
42267c478bd9Sstevel@tonic-gate  * fix_slice
42277c478bd9Sstevel@tonic-gate  * 	Read the VTOC table on the Solaris partition and check that no
42287c478bd9Sstevel@tonic-gate  *	slices exist that extend past the end of the Solaris partition.
42297c478bd9Sstevel@tonic-gate  *	If no Solaris partition exists, nothing is done.
42307c478bd9Sstevel@tonic-gate  */
4231bb16350dSlclee static void
4232bb16350dSlclee fix_slice(void)
42337c478bd9Sstevel@tonic-gate {
42347c478bd9Sstevel@tonic-gate 	int	i;
4235342440ecSPrasad Singamsetty 	uint32_t	numsect;
42367c478bd9Sstevel@tonic-gate 
42377c478bd9Sstevel@tonic-gate 	if (io_image) {
4238bb16350dSlclee 		return;
42397c478bd9Sstevel@tonic-gate 	}
42407c478bd9Sstevel@tonic-gate 
42417c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
42427c478bd9Sstevel@tonic-gate 		if (Table[i].systid == SUNIXOS || Table[i].systid == SUNIXOS2) {
42437c478bd9Sstevel@tonic-gate 			/*
42447c478bd9Sstevel@tonic-gate 			 * Only the size matters (not starting point), since
42457c478bd9Sstevel@tonic-gate 			 * VTOC entries are relative to the start of
42467c478bd9Sstevel@tonic-gate 			 * the partition.
42477c478bd9Sstevel@tonic-gate 			 */
4248*aa1b14e7SSheshadri Vasudevan 			numsect = LE_32(Table[i].numsect);
42497c478bd9Sstevel@tonic-gate 			break;
42507c478bd9Sstevel@tonic-gate 		}
42517c478bd9Sstevel@tonic-gate 	}
42527c478bd9Sstevel@tonic-gate 
42537c478bd9Sstevel@tonic-gate 	if (i >= FD_NUMPART) {
42547c478bd9Sstevel@tonic-gate 		if (!io_nifdisk) {
42557c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
42567c478bd9Sstevel@tonic-gate 			    "fdisk: No Solaris partition found - VTOC not"
42577c478bd9Sstevel@tonic-gate 			    " checked.\n");
42587c478bd9Sstevel@tonic-gate 		}
4259bb16350dSlclee 		return;
42607c478bd9Sstevel@tonic-gate 	}
42617c478bd9Sstevel@tonic-gate 
4262bb16350dSlclee 	if (readvtoc() != VTOC_OK) {
42637c478bd9Sstevel@tonic-gate 		exit(1);		/* Failed to read the VTOC */
42641237e847Slclee 	}
42651237e847Slclee 	for (i = 0; i < V_NUMPAR; i++) {
42661237e847Slclee 		/* Special case for slice two (entire disk) */
42671237e847Slclee 		if (i == 2) {
42681237e847Slclee 			if (disk_vtoc.v_part[i].p_start != 0) {
42691237e847Slclee 				(void) fprintf(stderr,
4270342440ecSPrasad Singamsetty 				    "slice %d starts at %llu, is not at"
42711237e847Slclee 				    " start of partition",
42721237e847Slclee 				    i, disk_vtoc.v_part[i].p_start);
42731237e847Slclee 				if (!io_nifdisk) {
42741237e847Slclee 					(void) printf(" adjust ?:");
42751237e847Slclee 					if (yesno())
42767c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_start = 0;
42771237e847Slclee 				} else {
42781237e847Slclee 					disk_vtoc.v_part[i].p_start = 0;
42791237e847Slclee 					(void) fprintf(stderr, " adjusted!\n");
42807c478bd9Sstevel@tonic-gate 				}
42811237e847Slclee 
42821237e847Slclee 			}
42831237e847Slclee 			if (disk_vtoc.v_part[i].p_size != numsect) {
42841237e847Slclee 				(void) fprintf(stderr,
4285342440ecSPrasad Singamsetty 				    "slice %d size %llu does not cover"
42861237e847Slclee 				    " complete partition",
42871237e847Slclee 				    i, disk_vtoc.v_part[i].p_size);
42881237e847Slclee 				if (!io_nifdisk) {
42891237e847Slclee 					(void) printf(" adjust ?:");
42901237e847Slclee 					if (yesno())
42917c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_size =
42927c478bd9Sstevel@tonic-gate 						    numsect;
42931237e847Slclee 				} else {
42941237e847Slclee 					disk_vtoc.v_part[i].p_size = numsect;
42951237e847Slclee 					(void) fprintf(stderr, " adjusted!\n");
42967c478bd9Sstevel@tonic-gate 				}
42971237e847Slclee 			}
42981237e847Slclee 			if (disk_vtoc.v_part[i].p_tag != V_BACKUP) {
42991237e847Slclee 				(void) fprintf(stderr,
43001237e847Slclee 				    "slice %d tag was %d should be %d",
43011237e847Slclee 				    i, disk_vtoc.v_part[i].p_tag,
43021237e847Slclee 				    V_BACKUP);
43031237e847Slclee 				if (!io_nifdisk) {
4304bb16350dSlclee 					(void) printf(" fix ?:");
43051237e847Slclee 					if (yesno())
43067c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_tag =
43077c478bd9Sstevel@tonic-gate 						    V_BACKUP;
43081237e847Slclee 				} else {
43097c478bd9Sstevel@tonic-gate 					disk_vtoc.v_part[i].p_tag = V_BACKUP;
43107c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr, " fixed!\n");
43117c478bd9Sstevel@tonic-gate 				}
43121237e847Slclee 			}
43131237e847Slclee 			continue;
43141237e847Slclee 		}
43151237e847Slclee 		if (io_ADJT) {
43161237e847Slclee 			if (disk_vtoc.v_part[i].p_start > numsect ||
43171237e847Slclee 			    disk_vtoc.v_part[i].p_start +
43181237e847Slclee 			    disk_vtoc.v_part[i].p_size > numsect) {
43191237e847Slclee 				(void) fprintf(stderr,
4320342440ecSPrasad Singamsetty 				    "slice %d (start %llu, end %llu)"
43211237e847Slclee 				    " is larger than the partition",
43221237e847Slclee 				    i, disk_vtoc.v_part[i].p_start,
43231237e847Slclee 				    disk_vtoc.v_part[i].p_start +
43241237e847Slclee 				    disk_vtoc.v_part[i].p_size);
43251237e847Slclee 				if (!io_nifdisk) {
43261237e847Slclee 					(void) printf(" remove ?:");
43271237e847Slclee 					if (yesno()) {
43287c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_size = 0;
43297c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_start = 0;
43307c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_tag = 0;
43317c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_flag = 0;
43327c478bd9Sstevel@tonic-gate 					}
43337c478bd9Sstevel@tonic-gate 				} else {
43341237e847Slclee 					disk_vtoc.v_part[i].p_size = 0;
43351237e847Slclee 					disk_vtoc.v_part[i].p_start = 0;
43361237e847Slclee 					disk_vtoc.v_part[i].p_tag = 0;
43371237e847Slclee 					disk_vtoc.v_part[i].p_flag = 0;
43387c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
43391237e847Slclee 					    " removed!\n");
43407c478bd9Sstevel@tonic-gate 				}
43417c478bd9Sstevel@tonic-gate 			}
43421237e847Slclee 			continue;
43431237e847Slclee 		}
43441237e847Slclee 		if (disk_vtoc.v_part[i].p_start > numsect) {
43451237e847Slclee 			(void) fprintf(stderr,
4346342440ecSPrasad Singamsetty 			    "slice %d (start %llu) is larger than the "
4347342440ecSPrasad Singamsetty 			    "partition", i, disk_vtoc.v_part[i].p_start);
43481237e847Slclee 			if (!io_nifdisk) {
43491237e847Slclee 				(void) printf(" remove ?:");
43501237e847Slclee 				if (yesno()) {
43511237e847Slclee 					disk_vtoc.v_part[i].p_size = 0;
43521237e847Slclee 					disk_vtoc.v_part[i].p_start = 0;
43531237e847Slclee 					disk_vtoc.v_part[i].p_tag = 0;
43541237e847Slclee 					disk_vtoc.v_part[i].p_flag = 0;
43551237e847Slclee 				}
43561237e847Slclee 			} else {
43571237e847Slclee 				disk_vtoc.v_part[i].p_size = 0;
43581237e847Slclee 				disk_vtoc.v_part[i].p_start = 0;
43591237e847Slclee 				disk_vtoc.v_part[i].p_tag = 0;
43601237e847Slclee 				disk_vtoc.v_part[i].p_flag = 0;
43611237e847Slclee 				(void) fprintf(stderr,
43621237e847Slclee 				" removed!\n");
43631237e847Slclee 			}
43641237e847Slclee 		} else if (disk_vtoc.v_part[i].p_start
43651237e847Slclee 		    + disk_vtoc.v_part[i].p_size > numsect) {
43661237e847Slclee 			(void) fprintf(stderr,
4367342440ecSPrasad Singamsetty 			    "slice %d (end %llu) is larger"
43681237e847Slclee 			    " than the partition",
43691237e847Slclee 			    i,
43701237e847Slclee 			    disk_vtoc.v_part[i].p_start +
43711237e847Slclee 			    disk_vtoc.v_part[i].p_size);
43721237e847Slclee 			if (!io_nifdisk) {
43731237e847Slclee 				(void) printf(" adjust ?:");
43741237e847Slclee 				if (yesno()) {
43751237e847Slclee 					disk_vtoc.v_part[i].p_size = numsect;
43761237e847Slclee 				}
43771237e847Slclee 			} else {
43781237e847Slclee 				disk_vtoc.v_part[i].p_size = numsect;
43791237e847Slclee 				(void) fprintf(stderr, " adjusted!\n");
43801237e847Slclee 			}
43817c478bd9Sstevel@tonic-gate 		}
43827c478bd9Sstevel@tonic-gate 	}
43837c478bd9Sstevel@tonic-gate #if 1		/* bh for now */
43847c478bd9Sstevel@tonic-gate 	/* Make the VTOC look sane - ha ha */
43857c478bd9Sstevel@tonic-gate 	disk_vtoc.v_version = V_VERSION;
43867c478bd9Sstevel@tonic-gate 	disk_vtoc.v_sanity = VTOC_SANE;
43877c478bd9Sstevel@tonic-gate 	disk_vtoc.v_nparts = V_NUMPAR;
43887c478bd9Sstevel@tonic-gate 	if (disk_vtoc.v_sectorsz == 0)
43897c478bd9Sstevel@tonic-gate 		disk_vtoc.v_sectorsz = NBPSCTR;
43907c478bd9Sstevel@tonic-gate #endif
43917c478bd9Sstevel@tonic-gate 
43927c478bd9Sstevel@tonic-gate 	/* Write the VTOC back to the disk */
43937c478bd9Sstevel@tonic-gate 	if (!io_readonly)
4394bb16350dSlclee 		(void) writevtoc();
43957c478bd9Sstevel@tonic-gate }
43967c478bd9Sstevel@tonic-gate 
43977c478bd9Sstevel@tonic-gate /*
43987c478bd9Sstevel@tonic-gate  * yesno
43997c478bd9Sstevel@tonic-gate  * Get yes or no answer. Return 1 for yes and 0 for no.
44007c478bd9Sstevel@tonic-gate  */
44017c478bd9Sstevel@tonic-gate 
4402bb16350dSlclee static int
4403bb16350dSlclee yesno(void)
44047c478bd9Sstevel@tonic-gate {
44057c478bd9Sstevel@tonic-gate 	char	s[80];
44067c478bd9Sstevel@tonic-gate 
44077c478bd9Sstevel@tonic-gate 	for (;;) {
4408933c1499SBarry Harding 		(void) fgets(s, sizeof (s), stdin);
44097c478bd9Sstevel@tonic-gate 		rm_blanks(s);
4410933c1499SBarry Harding 		if (((s[1] != '\0') && (s[1] != '\n')) ||
4411933c1499SBarry Harding 		    ((s[0] != 'y') && (s[0] != 'n'))) {
4412bb16350dSlclee 			(void) printf(E_LINE);
4413bb16350dSlclee 			(void) printf("Please answer with \"y\" or \"n\": ");
44147c478bd9Sstevel@tonic-gate 			continue;
44157c478bd9Sstevel@tonic-gate 		}
44167c478bd9Sstevel@tonic-gate 		if (s[0] == 'y')
44177c478bd9Sstevel@tonic-gate 			return (1);
44187c478bd9Sstevel@tonic-gate 		else
44197c478bd9Sstevel@tonic-gate 			return (0);
44207c478bd9Sstevel@tonic-gate 	}
44217c478bd9Sstevel@tonic-gate }
44227c478bd9Sstevel@tonic-gate 
44237c478bd9Sstevel@tonic-gate /*
44247c478bd9Sstevel@tonic-gate  * readvtoc
44257c478bd9Sstevel@tonic-gate  * 	Read the VTOC from the Solaris partition of the device.
44267c478bd9Sstevel@tonic-gate  */
4427bb16350dSlclee static int
4428bb16350dSlclee readvtoc(void)
44297c478bd9Sstevel@tonic-gate {
44307c478bd9Sstevel@tonic-gate 	int	i;
44317c478bd9Sstevel@tonic-gate 	int	retval = VTOC_OK;
44327c478bd9Sstevel@tonic-gate 
4433342440ecSPrasad Singamsetty 	if ((i = read_extvtoc(Dev, &disk_vtoc)) < VTOC_OK) {
44347c478bd9Sstevel@tonic-gate 		if (i == VT_EINVAL) {
44357c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: Invalid VTOC.\n");
44367c478bd9Sstevel@tonic-gate 			vt_inval++;
44377c478bd9Sstevel@tonic-gate 			retval = VTOC_INVAL;
44387c478bd9Sstevel@tonic-gate 		} else if (i == VT_ENOTSUP) {
44397c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: partition may have EFI "
44401237e847Slclee 			    "GPT\n");
44417c478bd9Sstevel@tonic-gate 			retval = VTOC_NOTSUP;
44427c478bd9Sstevel@tonic-gate 		} else {
44437c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: Cannot read VTOC.\n");
44447c478bd9Sstevel@tonic-gate 			retval = VTOC_RWERR;
44457c478bd9Sstevel@tonic-gate 		}
44467c478bd9Sstevel@tonic-gate 	}
44477c478bd9Sstevel@tonic-gate 	return (retval);
44487c478bd9Sstevel@tonic-gate }
44497c478bd9Sstevel@tonic-gate 
44507c478bd9Sstevel@tonic-gate /*
44517c478bd9Sstevel@tonic-gate  * writevtoc
44527c478bd9Sstevel@tonic-gate  * 	Write the VTOC to the Solaris partition on the device.
44537c478bd9Sstevel@tonic-gate  */
4454bb16350dSlclee static int
4455bb16350dSlclee writevtoc(void)
44567c478bd9Sstevel@tonic-gate {
44577c478bd9Sstevel@tonic-gate 	int	i;
44587c478bd9Sstevel@tonic-gate 	int	retval = 0;
44597c478bd9Sstevel@tonic-gate 
4460342440ecSPrasad Singamsetty 	if ((i = write_extvtoc(Dev, &disk_vtoc)) != 0) {
44617c478bd9Sstevel@tonic-gate 		if (i == VT_EINVAL) {
44627c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
44637c478bd9Sstevel@tonic-gate 			    "fdisk: Invalid entry exists in VTOC.\n");
44647c478bd9Sstevel@tonic-gate 			retval = VTOC_INVAL;
44657c478bd9Sstevel@tonic-gate 		} else if (i == VT_ENOTSUP) {
44667c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: partition may have EFI "
44671237e847Slclee 			    "GPT\n");
44687c478bd9Sstevel@tonic-gate 			retval = VTOC_NOTSUP;
44697c478bd9Sstevel@tonic-gate 		} else {
44707c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: Cannot write VTOC.\n");
44717c478bd9Sstevel@tonic-gate 			retval = VTOC_RWERR;
44727c478bd9Sstevel@tonic-gate 		}
44737c478bd9Sstevel@tonic-gate 	}
44747c478bd9Sstevel@tonic-gate 	return (retval);
44757c478bd9Sstevel@tonic-gate }
44767c478bd9Sstevel@tonic-gate 
44777c478bd9Sstevel@tonic-gate /*
44787c478bd9Sstevel@tonic-gate  * efi_ioctl
44797c478bd9Sstevel@tonic-gate  * issues DKIOCSETEFI IOCTL
44807c478bd9Sstevel@tonic-gate  * (duplicate of private efi_ioctl() in rdwr_efi.c
44817c478bd9Sstevel@tonic-gate  */
44827c478bd9Sstevel@tonic-gate static int
44837c478bd9Sstevel@tonic-gate efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc)
44847c478bd9Sstevel@tonic-gate {
44857c478bd9Sstevel@tonic-gate 	void *data = dk_ioc->dki_data;
44867c478bd9Sstevel@tonic-gate 	int error;
44877c478bd9Sstevel@tonic-gate 
44887c478bd9Sstevel@tonic-gate 	dk_ioc->dki_data_64 = (uintptr_t)data;
44897c478bd9Sstevel@tonic-gate 	error = ioctl(fd, cmd, (void *)dk_ioc);
44907c478bd9Sstevel@tonic-gate 
44917c478bd9Sstevel@tonic-gate 	return (error);
44927c478bd9Sstevel@tonic-gate }
44937c478bd9Sstevel@tonic-gate 
44947c478bd9Sstevel@tonic-gate /*
44957c478bd9Sstevel@tonic-gate  * clear_efi
44967c478bd9Sstevel@tonic-gate  * Clear EFI labels from the EFI_PMBR partition on the device
44977c478bd9Sstevel@tonic-gate  * This function is modeled on the libefi(3LIB) call efi_write()
44987c478bd9Sstevel@tonic-gate  */
4499bb16350dSlclee static int
4500bb16350dSlclee clear_efi(void)
45017c478bd9Sstevel@tonic-gate {
45027c478bd9Sstevel@tonic-gate 	struct dk_gpt	*efi_vtoc;
45037c478bd9Sstevel@tonic-gate 	dk_efi_t	dk_ioc;
45047c478bd9Sstevel@tonic-gate 
45057c478bd9Sstevel@tonic-gate 	/*
45067c478bd9Sstevel@tonic-gate 	 * see if we can read the EFI label
45077c478bd9Sstevel@tonic-gate 	 */
45087c478bd9Sstevel@tonic-gate 	if (efi_alloc_and_read(Dev, &efi_vtoc) < 0) {
45097c478bd9Sstevel@tonic-gate 		return (VT_ERROR);
45107c478bd9Sstevel@tonic-gate 	}
45117c478bd9Sstevel@tonic-gate 
45127c478bd9Sstevel@tonic-gate 	/*
45137c478bd9Sstevel@tonic-gate 	 * set up the dk_ioc structure for writing
45147c478bd9Sstevel@tonic-gate 	 */
45157c478bd9Sstevel@tonic-gate 	dk_ioc.dki_lba = 1;
45167c478bd9Sstevel@tonic-gate 	dk_ioc.dki_length = EFI_MIN_ARRAY_SIZE + efi_vtoc->efi_lbasize;
45177c478bd9Sstevel@tonic-gate 
45187c478bd9Sstevel@tonic-gate 	if ((dk_ioc.dki_data = calloc(dk_ioc.dki_length, 1)) == NULL) {
45197c478bd9Sstevel@tonic-gate 		return (VT_ERROR);
45207c478bd9Sstevel@tonic-gate 	}
45217c478bd9Sstevel@tonic-gate 
45227c478bd9Sstevel@tonic-gate 	/*
45237c478bd9Sstevel@tonic-gate 	 * clear the primary label
45247c478bd9Sstevel@tonic-gate 	 */
45257c478bd9Sstevel@tonic-gate 	if (io_debug) {
4526bb16350dSlclee 		(void) fprintf(stderr,
4527bb16350dSlclee 		    "\tClearing primary EFI label at block %lld\n",
4528bb16350dSlclee 		    dk_ioc.dki_lba);
45297c478bd9Sstevel@tonic-gate 	}
45307c478bd9Sstevel@tonic-gate 
45317c478bd9Sstevel@tonic-gate 	if (efi_ioctl(Dev, DKIOCSETEFI, &dk_ioc) == -1) {
45327c478bd9Sstevel@tonic-gate 		free(dk_ioc.dki_data);
45337c478bd9Sstevel@tonic-gate 		switch (errno) {
45347c478bd9Sstevel@tonic-gate 			case EIO:
45357c478bd9Sstevel@tonic-gate 				return (VT_EIO);
45367c478bd9Sstevel@tonic-gate 			case EINVAL:
45377c478bd9Sstevel@tonic-gate 				return (VT_EINVAL);
45387c478bd9Sstevel@tonic-gate 			default:
45397c478bd9Sstevel@tonic-gate 				return (VT_ERROR);
45407c478bd9Sstevel@tonic-gate 		}
45417c478bd9Sstevel@tonic-gate 	}
45427c478bd9Sstevel@tonic-gate 
45437c478bd9Sstevel@tonic-gate 	/*
45447c478bd9Sstevel@tonic-gate 	 * clear the backup partition table
45457c478bd9Sstevel@tonic-gate 	 */
45467c478bd9Sstevel@tonic-gate 	dk_ioc.dki_lba = efi_vtoc->efi_last_u_lba + 1;
45477c478bd9Sstevel@tonic-gate 	dk_ioc.dki_length -= efi_vtoc->efi_lbasize;
454865908c77Syu, larry liu - Sun Microsystems - Beijing China 	dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data +
454965908c77Syu, larry liu - Sun Microsystems - Beijing China 	    efi_vtoc->efi_lbasize);
45507c478bd9Sstevel@tonic-gate 	if (io_debug) {
4551bb16350dSlclee 		(void) fprintf(stderr,
4552bb16350dSlclee 		    "\tClearing backup partition table at block %lld\n",
4553bb16350dSlclee 		    dk_ioc.dki_lba);
45547c478bd9Sstevel@tonic-gate 	}
45557c478bd9Sstevel@tonic-gate 
45567c478bd9Sstevel@tonic-gate 	if (efi_ioctl(Dev, DKIOCSETEFI, &dk_ioc) == -1) {
45577c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "\tUnable to clear backup EFI label at "
45581237e847Slclee 		    "block %llu; errno %d\n", efi_vtoc->efi_last_u_lba + 1,
45591237e847Slclee 		    errno);
45607c478bd9Sstevel@tonic-gate 	}
45617c478bd9Sstevel@tonic-gate 
45627c478bd9Sstevel@tonic-gate 	/*
45637c478bd9Sstevel@tonic-gate 	 * clear the backup label
45647c478bd9Sstevel@tonic-gate 	 */
45657c478bd9Sstevel@tonic-gate 	dk_ioc.dki_lba = efi_vtoc->efi_last_lba;
45667c478bd9Sstevel@tonic-gate 	dk_ioc.dki_length = efi_vtoc->efi_lbasize;
456765908c77Syu, larry liu - Sun Microsystems - Beijing China 	dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data -
456865908c77Syu, larry liu - Sun Microsystems - Beijing China 	    efi_vtoc->efi_lbasize);
45697c478bd9Sstevel@tonic-gate 	if (io_debug) {
4570bb16350dSlclee 		(void) fprintf(stderr, "\tClearing backup label at block "
4571bb16350dSlclee 		    "%lld\n", dk_ioc.dki_lba);
45727c478bd9Sstevel@tonic-gate 	}
45737c478bd9Sstevel@tonic-gate 
45747c478bd9Sstevel@tonic-gate 	if (efi_ioctl(Dev, DKIOCSETEFI, &dk_ioc) == -1) {
4575bb16350dSlclee 		(void) fprintf(stderr,
4576bb16350dSlclee 		    "\tUnable to clear backup EFI label at "
4577bb16350dSlclee 		    "block %llu; errno %d\n",
4578bb16350dSlclee 		    efi_vtoc->efi_last_lba,
4579bb16350dSlclee 		    errno);
45807c478bd9Sstevel@tonic-gate 	}
45817c478bd9Sstevel@tonic-gate 
45827c478bd9Sstevel@tonic-gate 	free(dk_ioc.dki_data);
45837c478bd9Sstevel@tonic-gate 	efi_free(efi_vtoc);
45847c478bd9Sstevel@tonic-gate 
45857c478bd9Sstevel@tonic-gate 	return (0);
45867c478bd9Sstevel@tonic-gate }
45877c478bd9Sstevel@tonic-gate 
45887c478bd9Sstevel@tonic-gate /*
45897c478bd9Sstevel@tonic-gate  * clear_vtoc
45907c478bd9Sstevel@tonic-gate  * 	Clear the VTOC from the current or previous Solaris partition on the
45917c478bd9Sstevel@tonic-gate  *      device.
45927c478bd9Sstevel@tonic-gate  */
4593bb16350dSlclee static void
45947c478bd9Sstevel@tonic-gate clear_vtoc(int table, int part)
45957c478bd9Sstevel@tonic-gate {
45967c478bd9Sstevel@tonic-gate 	struct ipart *clr_table;
459765908c77Syu, larry liu - Sun Microsystems - Beijing China 	char *disk_label;
4598342440ecSPrasad Singamsetty 	uint32_t pcyl, ncyl, count;
4599342440ecSPrasad Singamsetty 	diskaddr_t backup_block, solaris_offset;
4600342440ecSPrasad Singamsetty 	ssize_t bytes;
46019d5d1945Sbharding 	off_t seek_byte;
46027c478bd9Sstevel@tonic-gate 
46037c478bd9Sstevel@tonic-gate #ifdef DEBUG
460465908c77Syu, larry liu - Sun Microsystems - Beijing China 	char *read_label;
46057c478bd9Sstevel@tonic-gate #endif /* DEBUG */
46067c478bd9Sstevel@tonic-gate 
46077c478bd9Sstevel@tonic-gate 	if (table == OLD) {
46087c478bd9Sstevel@tonic-gate 		clr_table = &Old_Table[part];
46097c478bd9Sstevel@tonic-gate 	} else {
46107c478bd9Sstevel@tonic-gate 		clr_table = &Table[part];
46117c478bd9Sstevel@tonic-gate 	}
46127c478bd9Sstevel@tonic-gate 
461365908c77Syu, larry liu - Sun Microsystems - Beijing China 	disk_label = (char *)calloc(sectsiz, 1);
461465908c77Syu, larry liu - Sun Microsystems - Beijing China 	if (disk_label == NULL) {
461565908c77Syu, larry liu - Sun Microsystems - Beijing China 		return;
461665908c77Syu, larry liu - Sun Microsystems - Beijing China 	}
46177c478bd9Sstevel@tonic-gate 
4618*aa1b14e7SSheshadri Vasudevan 	seek_byte = (off_t)(LE_32(clr_table->relsect) + VTOC_OFFSET) * sectsiz;
46197c478bd9Sstevel@tonic-gate 
46207c478bd9Sstevel@tonic-gate 	if (io_debug) {
46219d5d1945Sbharding 		(void) fprintf(stderr,
46229d5d1945Sbharding 		    "\tClearing primary VTOC at byte %llu (block %llu)\n",
46239d5d1945Sbharding 		    (uint64_t)seek_byte,
4624*aa1b14e7SSheshadri Vasudevan 		    (uint64_t)(LE_32(clr_table->relsect) + VTOC_OFFSET));
46257c478bd9Sstevel@tonic-gate 	}
46267c478bd9Sstevel@tonic-gate 
46277c478bd9Sstevel@tonic-gate 	if (lseek(Dev, seek_byte, SEEK_SET) == -1) {
4628bb16350dSlclee 		(void) fprintf(stderr,
46299d5d1945Sbharding 		    "\tError seeking to primary label at byte %llu\n",
46309d5d1945Sbharding 		    (uint64_t)seek_byte);
463165908c77Syu, larry liu - Sun Microsystems - Beijing China 		free(disk_label);
4632bb16350dSlclee 		return;
46337c478bd9Sstevel@tonic-gate 	}
46347c478bd9Sstevel@tonic-gate 
463565908c77Syu, larry liu - Sun Microsystems - Beijing China 	bytes = write(Dev, disk_label, sectsiz);
46367c478bd9Sstevel@tonic-gate 
463765908c77Syu, larry liu - Sun Microsystems - Beijing China 	if (bytes != sectsiz) {
4638bb16350dSlclee 		(void) fprintf(stderr,
4639342440ecSPrasad Singamsetty 		    "\tWarning: only %d bytes written to clear primary"
4640342440ecSPrasad Singamsetty 		    " VTOC!\n", bytes);
46417c478bd9Sstevel@tonic-gate 	}
46427c478bd9Sstevel@tonic-gate 
46437c478bd9Sstevel@tonic-gate #ifdef DEBUG
46447c478bd9Sstevel@tonic-gate 	if (lseek(Dev, seek_byte, SEEK_SET) == -1) {
4645bb16350dSlclee 		(void) fprintf(stderr,
46469d5d1945Sbharding 		    "DEBUG: Error seeking to primary label at byte %llu\n",
46479d5d1945Sbharding 		    (uint64_t)seek_byte);
464865908c77Syu, larry liu - Sun Microsystems - Beijing China 		free(disk_label);
4649bb16350dSlclee 		return;
46507c478bd9Sstevel@tonic-gate 	} else {
46519d5d1945Sbharding 		(void) fprintf(stderr,
46529d5d1945Sbharding 		    "DEBUG: Successful lseek() to byte %llu\n",
46539d5d1945Sbharding 		    (uint64_t)seek_byte);
46547c478bd9Sstevel@tonic-gate 	}
46557c478bd9Sstevel@tonic-gate 
465665908c77Syu, larry liu - Sun Microsystems - Beijing China 	read_label = (char *)calloc(sectsiz, 1);
465765908c77Syu, larry liu - Sun Microsystems - Beijing China 	if (read_label == NULL) {
465865908c77Syu, larry liu - Sun Microsystems - Beijing China 		free(disk_label);
465965908c77Syu, larry liu - Sun Microsystems - Beijing China 		return;
466065908c77Syu, larry liu - Sun Microsystems - Beijing China 	}
466165908c77Syu, larry liu - Sun Microsystems - Beijing China 
466265908c77Syu, larry liu - Sun Microsystems - Beijing China 	bytes = read(Dev, read_label, sectsiz);
46637c478bd9Sstevel@tonic-gate 
466465908c77Syu, larry liu - Sun Microsystems - Beijing China 	if (bytes != sectsiz) {
4665bb16350dSlclee 		(void) fprintf(stderr,
4666bb16350dSlclee 		    "DEBUG: Warning: only %d bytes read of label\n",
46677c478bd9Sstevel@tonic-gate 		    bytes);
46687c478bd9Sstevel@tonic-gate 	}
46697c478bd9Sstevel@tonic-gate 
467065908c77Syu, larry liu - Sun Microsystems - Beijing China 	if (memcmp(disk_label, read_label, sectsiz) != 0) {
4671bb16350dSlclee 		(void) fprintf(stderr,
4672bb16350dSlclee 		    "DEBUG: Warning: disk_label and read_label differ!!!\n");
46737c478bd9Sstevel@tonic-gate 	} else {
4674bb16350dSlclee 		(void) fprintf(stderr, "DEBUG Good compare of disk_label and "
46757c478bd9Sstevel@tonic-gate 		    "read_label\n");
46767c478bd9Sstevel@tonic-gate 	}
46777c478bd9Sstevel@tonic-gate #endif /* DEBUG */
46787c478bd9Sstevel@tonic-gate 
46797c478bd9Sstevel@tonic-gate 	/* Clear backup label */
4680*aa1b14e7SSheshadri Vasudevan 	pcyl = LE_32(clr_table->numsect) / (heads * sectors);
4681*aa1b14e7SSheshadri Vasudevan 	solaris_offset = LE_32(clr_table->relsect);
46827c478bd9Sstevel@tonic-gate 	ncyl = pcyl - acyl;
46837c478bd9Sstevel@tonic-gate 
46847c478bd9Sstevel@tonic-gate 	backup_block = ((ncyl + acyl - 1) *
46857c478bd9Sstevel@tonic-gate 	    (heads * sectors)) + ((heads - 1) * sectors) + 1;
46867c478bd9Sstevel@tonic-gate 
46877c478bd9Sstevel@tonic-gate 	for (count = 1; count < 6; count++) {
468865908c77Syu, larry liu - Sun Microsystems - Beijing China 		seek_byte = (off_t)(solaris_offset + backup_block) * sectsiz;
46897c478bd9Sstevel@tonic-gate 
46907c478bd9Sstevel@tonic-gate 		if (lseek(Dev, seek_byte, SEEK_SET) == -1) {
4691bb16350dSlclee 			(void) fprintf(stderr,
46929d5d1945Sbharding 			    "\tError seeking to backup label at byte %llu on "
46939d5d1945Sbharding 			    "%s.\n", (uint64_t)seek_byte, Dfltdev);
469465908c77Syu, larry liu - Sun Microsystems - Beijing China 			free(disk_label);
469565908c77Syu, larry liu - Sun Microsystems - Beijing China #ifdef DEBUG
469665908c77Syu, larry liu - Sun Microsystems - Beijing China 			free(read_label);
469765908c77Syu, larry liu - Sun Microsystems - Beijing China #endif /* DEBUG */
4698bb16350dSlclee 			return;
46997c478bd9Sstevel@tonic-gate 		}
47007c478bd9Sstevel@tonic-gate 
47017c478bd9Sstevel@tonic-gate 		if (io_debug) {
4702bb16350dSlclee 			(void) fprintf(stderr, "\tClearing backup VTOC at"
47039d5d1945Sbharding 			    " byte %llu (block %llu)\n",
47049d5d1945Sbharding 			    (uint64_t)seek_byte,
47059d5d1945Sbharding 			    (uint64_t)(solaris_offset + backup_block));
47067c478bd9Sstevel@tonic-gate 		}
47077c478bd9Sstevel@tonic-gate 
470865908c77Syu, larry liu - Sun Microsystems - Beijing China 		bytes = write(Dev, disk_label, sectsiz);
47097c478bd9Sstevel@tonic-gate 
471065908c77Syu, larry liu - Sun Microsystems - Beijing China 		if (bytes != sectsiz) {
4711bb16350dSlclee 			(void) fprintf(stderr,
4712bb16350dSlclee 			    "\t\tWarning: only %d bytes written to "
47139d5d1945Sbharding 			    "clear backup VTOC at block %llu!\n", bytes,
47149d5d1945Sbharding 			    (uint64_t)(solaris_offset + backup_block));
47157c478bd9Sstevel@tonic-gate 		}
47167c478bd9Sstevel@tonic-gate 
47177c478bd9Sstevel@tonic-gate #ifdef DEBUG
47187c478bd9Sstevel@tonic-gate 	if (lseek(Dev, seek_byte, SEEK_SET) == -1) {
4719bb16350dSlclee 		(void) fprintf(stderr,
47209d5d1945Sbharding 		    "DEBUG: Error seeking to backup label at byte %llu\n",
47219d5d1945Sbharding 		    (uint64_t)seek_byte);
472265908c77Syu, larry liu - Sun Microsystems - Beijing China 		free(disk_label);
472365908c77Syu, larry liu - Sun Microsystems - Beijing China 		free(read_label);
4724bb16350dSlclee 		return;
47257c478bd9Sstevel@tonic-gate 	} else {
47269d5d1945Sbharding 		(void) fprintf(stderr,
47279d5d1945Sbharding 		    "DEBUG: Successful lseek() to byte %llu\n",
47289d5d1945Sbharding 		    (uint64_t)seek_byte);
47297c478bd9Sstevel@tonic-gate 	}
47307c478bd9Sstevel@tonic-gate 
473165908c77Syu, larry liu - Sun Microsystems - Beijing China 	bytes = read(Dev, read_label, sectsiz);
47327c478bd9Sstevel@tonic-gate 
473365908c77Syu, larry liu - Sun Microsystems - Beijing China 	if (bytes != sectsiz) {
4734bb16350dSlclee 		(void) fprintf(stderr,
4735bb16350dSlclee 		    "DEBUG: Warning: only %d bytes read of backup label\n",
4736bb16350dSlclee 		    bytes);
47377c478bd9Sstevel@tonic-gate 	}
47387c478bd9Sstevel@tonic-gate 
473965908c77Syu, larry liu - Sun Microsystems - Beijing China 	if (memcmp(disk_label, read_label, sectsiz) != 0) {
4740bb16350dSlclee 		(void) fprintf(stderr,
4741bb16350dSlclee 		    "DEBUG: Warning: disk_label and read_label differ!!!\n");
47427c478bd9Sstevel@tonic-gate 	} else {
4743bb16350dSlclee 		(void) fprintf(stderr,
4744bb16350dSlclee 		    "DEBUG: Good compare of disk_label and backup "
47457c478bd9Sstevel@tonic-gate 		    "read_label\n");
47467c478bd9Sstevel@tonic-gate 	}
474765908c77Syu, larry liu - Sun Microsystems - Beijing China 
47487c478bd9Sstevel@tonic-gate #endif /* DEBUG */
47497c478bd9Sstevel@tonic-gate 
47507c478bd9Sstevel@tonic-gate 		backup_block += 2;
47517c478bd9Sstevel@tonic-gate 	}
475265908c77Syu, larry liu - Sun Microsystems - Beijing China 
475365908c77Syu, larry liu - Sun Microsystems - Beijing China #ifdef DEBUG
475465908c77Syu, larry liu - Sun Microsystems - Beijing China 	free(read_label);
475565908c77Syu, larry liu - Sun Microsystems - Beijing China #endif /* DEBUG */
475665908c77Syu, larry liu - Sun Microsystems - Beijing China 	free(disk_label);
47577c478bd9Sstevel@tonic-gate }
47587c478bd9Sstevel@tonic-gate 
47597c478bd9Sstevel@tonic-gate #define	FDISK_STANDARD_LECTURE \
47607c478bd9Sstevel@tonic-gate 	"Fdisk is normally used with the device that " \
47617c478bd9Sstevel@tonic-gate 	"represents the entire fixed disk.\n" \
47627c478bd9Sstevel@tonic-gate 	"(For example, /dev/rdsk/c0d0p0 on x86 or " \
47637c478bd9Sstevel@tonic-gate 	"/dev/rdsk/c0t5d0s2 on sparc).\n"
47647c478bd9Sstevel@tonic-gate 
47657c478bd9Sstevel@tonic-gate #define	FDISK_LECTURE_NOT_SECTOR_ZERO \
47667c478bd9Sstevel@tonic-gate 	"The device does not appear to include absolute\n" \
47677c478bd9Sstevel@tonic-gate 	"sector 0 of the PHYSICAL disk " \
47687c478bd9Sstevel@tonic-gate 	"(the normal location for an fdisk table).\n"
47697c478bd9Sstevel@tonic-gate 
47707c478bd9Sstevel@tonic-gate #define	FDISK_LECTURE_NOT_FULL \
47717c478bd9Sstevel@tonic-gate 	"The device does not appear to encompass the entire PHYSICAL disk.\n"
47727c478bd9Sstevel@tonic-gate 
47737c478bd9Sstevel@tonic-gate #define	FDISK_LECTURE_NO_VTOC \
47747c478bd9Sstevel@tonic-gate 	"Unable to find a volume table of contents.\n" \
47757c478bd9Sstevel@tonic-gate 	"Cannot verify the device encompasses the full PHYSICAL disk.\n"
47767c478bd9Sstevel@tonic-gate 
47777c478bd9Sstevel@tonic-gate #define	FDISK_LECTURE_NO_GEOM \
47787c478bd9Sstevel@tonic-gate 	"Unable to get geometry from device.\n" \
47797c478bd9Sstevel@tonic-gate 	"Cannot verify the device encompasses the full PHYSICAL disk.\n"
47807c478bd9Sstevel@tonic-gate 
47817c478bd9Sstevel@tonic-gate #define	FDISK_SHALL_I_CONTINUE \
47827c478bd9Sstevel@tonic-gate 	"Are you sure you want to continue? (y/n) "
47837c478bd9Sstevel@tonic-gate 
47847c478bd9Sstevel@tonic-gate /*
47857c478bd9Sstevel@tonic-gate  *  lecture_and_query
47867c478bd9Sstevel@tonic-gate  *	Called when a sanity check fails.  This routine gives a warning
47877c478bd9Sstevel@tonic-gate  *	specific to the check that fails, followed by a generic lecture
47887c478bd9Sstevel@tonic-gate  *	about the "right" device to supply as input.  Then, if appropriate,
47897c478bd9Sstevel@tonic-gate  *	it will prompt the user on whether or not they want to continue.
47907c478bd9Sstevel@tonic-gate  *	Inappropriate times for prompting are when the user has selected
47917c478bd9Sstevel@tonic-gate  *	non-interactive mode or read-only mode.
47927c478bd9Sstevel@tonic-gate  */
4793bb16350dSlclee static int
47947c478bd9Sstevel@tonic-gate lecture_and_query(char *warning, char *devname)
47957c478bd9Sstevel@tonic-gate {
47967c478bd9Sstevel@tonic-gate 	if (io_nifdisk)
47977c478bd9Sstevel@tonic-gate 		return (0);
47987c478bd9Sstevel@tonic-gate 
4799bb16350dSlclee 	(void) fprintf(stderr, "WARNING: Device %s: \n", devname);
4800bb16350dSlclee 	(void) fprintf(stderr, "%s", warning);
4801bb16350dSlclee 	(void) fprintf(stderr, FDISK_STANDARD_LECTURE);
4802bb16350dSlclee 	(void) fprintf(stderr, FDISK_SHALL_I_CONTINUE);
48037c478bd9Sstevel@tonic-gate 
48047c478bd9Sstevel@tonic-gate 	return (yesno());
48057c478bd9Sstevel@tonic-gate }
48067c478bd9Sstevel@tonic-gate 
4807bb16350dSlclee static void
48087c478bd9Sstevel@tonic-gate sanity_check_provided_device(char *devname, int fd)
48097c478bd9Sstevel@tonic-gate {
4810342440ecSPrasad Singamsetty 	struct extvtoc v;
48117c478bd9Sstevel@tonic-gate 	struct dk_geom d;
48127c478bd9Sstevel@tonic-gate 	struct part_info pi;
4813342440ecSPrasad Singamsetty 	struct extpart_info extpi;
4814342440ecSPrasad Singamsetty 	diskaddr_t totsize;
48157c478bd9Sstevel@tonic-gate 	int idx = -1;
48167c478bd9Sstevel@tonic-gate 
48177c478bd9Sstevel@tonic-gate 	/*
48187c478bd9Sstevel@tonic-gate 	 *  First try the PARTINFO ioctl.  If it works, we will be able
48197c478bd9Sstevel@tonic-gate 	 *  to tell if they've specified the full disk partition by checking
48207c478bd9Sstevel@tonic-gate 	 *  to see if they've specified a partition that starts at sector 0.
48217c478bd9Sstevel@tonic-gate 	 */
4822342440ecSPrasad Singamsetty 	if (ioctl(fd, DKIOCEXTPARTINFO, &extpi) != -1) {
4823342440ecSPrasad Singamsetty 		if (extpi.p_start != 0) {
4824342440ecSPrasad Singamsetty 			if (!lecture_and_query(FDISK_LECTURE_NOT_SECTOR_ZERO,
4825342440ecSPrasad Singamsetty 			    devname)) {
4826342440ecSPrasad Singamsetty 				(void) close(fd);
4827342440ecSPrasad Singamsetty 				exit(1);
4828342440ecSPrasad Singamsetty 			}
4829342440ecSPrasad Singamsetty 		}
4830342440ecSPrasad Singamsetty 	} else if (ioctl(fd, DKIOCPARTINFO, &pi) != -1) {
48317c478bd9Sstevel@tonic-gate 		if (pi.p_start != 0) {
48327c478bd9Sstevel@tonic-gate 			if (!lecture_and_query(FDISK_LECTURE_NOT_SECTOR_ZERO,
48337c478bd9Sstevel@tonic-gate 			    devname)) {
48347c478bd9Sstevel@tonic-gate 				(void) close(fd);
48357c478bd9Sstevel@tonic-gate 				exit(1);
48367c478bd9Sstevel@tonic-gate 			}
48377c478bd9Sstevel@tonic-gate 		}
48387c478bd9Sstevel@tonic-gate 	} else {
4839342440ecSPrasad Singamsetty 		if ((idx = read_extvtoc(fd, &v)) < 0) {
48407c478bd9Sstevel@tonic-gate 			if (!lecture_and_query(FDISK_LECTURE_NO_VTOC,
48417c478bd9Sstevel@tonic-gate 			    devname)) {
48427c478bd9Sstevel@tonic-gate 				(void) close(fd);
48437c478bd9Sstevel@tonic-gate 				exit(1);
48447c478bd9Sstevel@tonic-gate 			}
48457c478bd9Sstevel@tonic-gate 			return;
48467c478bd9Sstevel@tonic-gate 		}
48477c478bd9Sstevel@tonic-gate 		if (ioctl(fd, DKIOCGGEOM, &d) == -1) {
48487c478bd9Sstevel@tonic-gate 			perror(devname);
48497c478bd9Sstevel@tonic-gate 			if (!lecture_and_query(FDISK_LECTURE_NO_GEOM,
48507c478bd9Sstevel@tonic-gate 			    devname)) {
48517c478bd9Sstevel@tonic-gate 				(void) close(fd);
48527c478bd9Sstevel@tonic-gate 				exit(1);
48537c478bd9Sstevel@tonic-gate 			}
48547c478bd9Sstevel@tonic-gate 			return;
48557c478bd9Sstevel@tonic-gate 		}
4856342440ecSPrasad Singamsetty 		totsize = (diskaddr_t)d.dkg_ncyl * d.dkg_nhead * d.dkg_nsect;
48577c478bd9Sstevel@tonic-gate 		if (v.v_part[idx].p_size != totsize) {
48587c478bd9Sstevel@tonic-gate 			if (!lecture_and_query(FDISK_LECTURE_NOT_FULL,
48597c478bd9Sstevel@tonic-gate 			    devname)) {
48607c478bd9Sstevel@tonic-gate 				(void) close(fd);
48617c478bd9Sstevel@tonic-gate 				exit(1);
48627c478bd9Sstevel@tonic-gate 			}
48637c478bd9Sstevel@tonic-gate 		}
48647c478bd9Sstevel@tonic-gate 	}
48657c478bd9Sstevel@tonic-gate }
48667c478bd9Sstevel@tonic-gate 
48677c478bd9Sstevel@tonic-gate 
48687c478bd9Sstevel@tonic-gate /*
48697c478bd9Sstevel@tonic-gate  * get_node
48707c478bd9Sstevel@tonic-gate  * Called from main to construct the name of the device node to open.
48717c478bd9Sstevel@tonic-gate  * Initially tries to stat the node exactly as provided, if that fails
48727c478bd9Sstevel@tonic-gate  * we prepend the default path (/dev/rdsk/).
48737c478bd9Sstevel@tonic-gate  */
48747c478bd9Sstevel@tonic-gate static char *
48757c478bd9Sstevel@tonic-gate get_node(char *devname)
48767c478bd9Sstevel@tonic-gate {
48777c478bd9Sstevel@tonic-gate 	char *node;
48787c478bd9Sstevel@tonic-gate 	struct stat statbuf;
48797c478bd9Sstevel@tonic-gate 	size_t space;
48807c478bd9Sstevel@tonic-gate 
48817c478bd9Sstevel@tonic-gate 	/* Don't do anything if we are skipping device checks */
48827c478bd9Sstevel@tonic-gate 	if (io_image)
48837c478bd9Sstevel@tonic-gate 		return (devname);
48847c478bd9Sstevel@tonic-gate 
48857c478bd9Sstevel@tonic-gate 	node = devname;
48867c478bd9Sstevel@tonic-gate 
48877c478bd9Sstevel@tonic-gate 	/* Try the node as provided first */
48887c478bd9Sstevel@tonic-gate 	if (stat(node, (struct stat *)&statbuf) == -1) {
48897c478bd9Sstevel@tonic-gate 		/*
48907c478bd9Sstevel@tonic-gate 		 * Copy the passed in string to a new buffer, prepend the
48917c478bd9Sstevel@tonic-gate 		 * default path and try again.
48927c478bd9Sstevel@tonic-gate 		 */
48937c478bd9Sstevel@tonic-gate 		space = strlen(DEFAULT_PATH) + strlen(devname) + 1;
48947c478bd9Sstevel@tonic-gate 
48957c478bd9Sstevel@tonic-gate 		if ((node = malloc(space)) == NULL) {
4896bb16350dSlclee 			(void) fprintf(stderr, "fdisk: Unable to obtain memory "
48977c478bd9Sstevel@tonic-gate 			    "for device node.\n");
48987c478bd9Sstevel@tonic-gate 			exit(1);
48997c478bd9Sstevel@tonic-gate 		}
49007c478bd9Sstevel@tonic-gate 
49017c478bd9Sstevel@tonic-gate 		/* Copy over the default path and the provided node */
49027c478bd9Sstevel@tonic-gate 		(void) strncpy(node, DEFAULT_PATH, strlen(DEFAULT_PATH));
49037c478bd9Sstevel@tonic-gate 		space -= strlen(DEFAULT_PATH);
49047c478bd9Sstevel@tonic-gate 		(void) strlcpy(node + strlen(DEFAULT_PATH), devname, space);
49057c478bd9Sstevel@tonic-gate 
49067c478bd9Sstevel@tonic-gate 		/* Try to stat it again */
49077c478bd9Sstevel@tonic-gate 		if (stat(node, (struct stat *)&statbuf) == -1) {
49087c478bd9Sstevel@tonic-gate 			/* Failed all options, give up */
4909bb16350dSlclee 			(void) fprintf(stderr,
4910bb16350dSlclee 			    "fdisk: Cannot stat device %s.\n",
49117c478bd9Sstevel@tonic-gate 			    devname);
49127c478bd9Sstevel@tonic-gate 			exit(1);
49137c478bd9Sstevel@tonic-gate 		}
49147c478bd9Sstevel@tonic-gate 	}
49157c478bd9Sstevel@tonic-gate 
49167c478bd9Sstevel@tonic-gate 	/* Make sure the device specified is the raw device */
49177c478bd9Sstevel@tonic-gate 	if ((statbuf.st_mode & S_IFMT) != S_IFCHR) {
4918bb16350dSlclee 		(void) fprintf(stderr,
4919bb16350dSlclee 		    "fdisk: %s must be a raw device.\n", node);
49207c478bd9Sstevel@tonic-gate 		exit(1);
49217c478bd9Sstevel@tonic-gate 	}
49227c478bd9Sstevel@tonic-gate 
49237c478bd9Sstevel@tonic-gate 	return (node);
49247c478bd9Sstevel@tonic-gate }
4925*aa1b14e7SSheshadri Vasudevan 
4926*aa1b14e7SSheshadri Vasudevan #ifdef i386
4927*aa1b14e7SSheshadri Vasudevan static void
4928*aa1b14e7SSheshadri Vasudevan preach_and_continue()
4929*aa1b14e7SSheshadri Vasudevan {
4930*aa1b14e7SSheshadri Vasudevan 	(void) fprintf(stderr, "There are mounted logical drives. Committing "
4931*aa1b14e7SSheshadri Vasudevan 	    "changes now can lead to inconsistancy in internal system state "
4932*aa1b14e7SSheshadri Vasudevan 	    "which can eventually cause data loss or corruption. Unmount all "
4933*aa1b14e7SSheshadri Vasudevan 	    "logical drives and try committing the changes again.\n");
4934*aa1b14e7SSheshadri Vasudevan 	ext_read_input(s);
4935*aa1b14e7SSheshadri Vasudevan }
4936*aa1b14e7SSheshadri Vasudevan 
4937*aa1b14e7SSheshadri Vasudevan /*
4938*aa1b14e7SSheshadri Vasudevan  * Convert a given partition ID to an descriptive string.
4939*aa1b14e7SSheshadri Vasudevan  * Just an index into the partition types table.
4940*aa1b14e7SSheshadri Vasudevan  */
4941*aa1b14e7SSheshadri Vasudevan void
4942*aa1b14e7SSheshadri Vasudevan id_to_name(uchar_t sysid, char *buffer)
4943*aa1b14e7SSheshadri Vasudevan {
4944*aa1b14e7SSheshadri Vasudevan 	strcpy(buffer, fdisk_part_types[sysid]);
4945*aa1b14e7SSheshadri Vasudevan }
4946*aa1b14e7SSheshadri Vasudevan 
4947*aa1b14e7SSheshadri Vasudevan /*
4948*aa1b14e7SSheshadri Vasudevan  * Procedure to check the validity of the extended partition menu option
4949*aa1b14e7SSheshadri Vasudevan  * entered by the user
4950*aa1b14e7SSheshadri Vasudevan  */
4951*aa1b14e7SSheshadri Vasudevan static int
4952*aa1b14e7SSheshadri Vasudevan ext_invalid_option(char ch)
4953*aa1b14e7SSheshadri Vasudevan {
4954*aa1b14e7SSheshadri Vasudevan 	char *p;
4955*aa1b14e7SSheshadri Vasudevan 
4956*aa1b14e7SSheshadri Vasudevan 	p = strchr(ext_part_menu_opts, tolower(ch));
4957*aa1b14e7SSheshadri Vasudevan 
4958*aa1b14e7SSheshadri Vasudevan 	if (p == NULL) {
4959*aa1b14e7SSheshadri Vasudevan 		return (1);
4960*aa1b14e7SSheshadri Vasudevan 	}
4961*aa1b14e7SSheshadri Vasudevan 	return (0);
4962*aa1b14e7SSheshadri Vasudevan }
4963*aa1b14e7SSheshadri Vasudevan 
4964*aa1b14e7SSheshadri Vasudevan /*
4965*aa1b14e7SSheshadri Vasudevan  * Read 16 bytes of the input (assuming that no valid user input spans more
4966*aa1b14e7SSheshadri Vasudevan  * than that). Flush the input stream, so that the next read does not reap
4967*aa1b14e7SSheshadri Vasudevan  * stale data from the previous input that was not processed.
4968*aa1b14e7SSheshadri Vasudevan  * Note that fgets also reads the trailing '\n'
4969*aa1b14e7SSheshadri Vasudevan  */
4970*aa1b14e7SSheshadri Vasudevan static void
4971*aa1b14e7SSheshadri Vasudevan ext_read_input(char *buf)
4972*aa1b14e7SSheshadri Vasudevan {
4973*aa1b14e7SSheshadri Vasudevan 	fgets(buf, 16, stdin);
4974*aa1b14e7SSheshadri Vasudevan 	fflush(stdin);
4975*aa1b14e7SSheshadri Vasudevan }
4976*aa1b14e7SSheshadri Vasudevan 
4977*aa1b14e7SSheshadri Vasudevan /*
4978*aa1b14e7SSheshadri Vasudevan  * Procedure to read and validate the user option at the extended partition menu
4979*aa1b14e7SSheshadri Vasudevan  */
4980*aa1b14e7SSheshadri Vasudevan static int
4981*aa1b14e7SSheshadri Vasudevan ext_read_options(char *buf)
4982*aa1b14e7SSheshadri Vasudevan {
4983*aa1b14e7SSheshadri Vasudevan 	ext_read_input(buf);
4984*aa1b14e7SSheshadri Vasudevan 	if ((strlen(buf) != 2) || (ext_invalid_option(buf[0]))) {
4985*aa1b14e7SSheshadri Vasudevan 		printf("\nUnknown Command\n");
4986*aa1b14e7SSheshadri Vasudevan 		return (-1);
4987*aa1b14e7SSheshadri Vasudevan 	}
4988*aa1b14e7SSheshadri Vasudevan 	return (0);
4989*aa1b14e7SSheshadri Vasudevan }
4990*aa1b14e7SSheshadri Vasudevan 
4991*aa1b14e7SSheshadri Vasudevan /*
4992*aa1b14e7SSheshadri Vasudevan  * Procedure to print the list of known partition types and their IDs
4993*aa1b14e7SSheshadri Vasudevan  */
4994*aa1b14e7SSheshadri Vasudevan static void
4995*aa1b14e7SSheshadri Vasudevan ext_print_part_types()
4996*aa1b14e7SSheshadri Vasudevan {
4997*aa1b14e7SSheshadri Vasudevan 	int i, rowmax, rowcount = 1;
4998*aa1b14e7SSheshadri Vasudevan 	struct winsize ws;
4999*aa1b14e7SSheshadri Vasudevan 	char buf[80];
5000*aa1b14e7SSheshadri Vasudevan 
5001*aa1b14e7SSheshadri Vasudevan 	/* Get the current window dimensions */
5002*aa1b14e7SSheshadri Vasudevan 	if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0) {
5003*aa1b14e7SSheshadri Vasudevan 		perror("ioctl");
5004*aa1b14e7SSheshadri Vasudevan 		rowmax = 20;
5005*aa1b14e7SSheshadri Vasudevan 	} else {
5006*aa1b14e7SSheshadri Vasudevan 		/*
5007*aa1b14e7SSheshadri Vasudevan 		 * Accommodate the initial headings by reducing the number of
5008*aa1b14e7SSheshadri Vasudevan 		 * partition IDs being printed.
5009*aa1b14e7SSheshadri Vasudevan 		 */
5010*aa1b14e7SSheshadri Vasudevan 		rowmax = ws.ws_row - 5;
5011*aa1b14e7SSheshadri Vasudevan 	}
5012*aa1b14e7SSheshadri Vasudevan 
5013*aa1b14e7SSheshadri Vasudevan 	if (rowmax < 3) {
5014*aa1b14e7SSheshadri Vasudevan 		fprintf(stderr, "Window size too small."
5015*aa1b14e7SSheshadri Vasudevan 		    " Try resizing the window\n");
5016*aa1b14e7SSheshadri Vasudevan 		return;
5017*aa1b14e7SSheshadri Vasudevan 	}
5018*aa1b14e7SSheshadri Vasudevan 
5019*aa1b14e7SSheshadri Vasudevan 	printf("List of known partition types : \n");
5020*aa1b14e7SSheshadri Vasudevan 	printf("PartID          Partition Type\n");
5021*aa1b14e7SSheshadri Vasudevan 	printf("======          ==============\n");
5022*aa1b14e7SSheshadri Vasudevan 	for (i = 0; i <= FDISK_MAX_VALID_PART_ID; i++) {
5023*aa1b14e7SSheshadri Vasudevan 		printf("%-3d          %s\n", i, fdisk_part_types[i]);
5024*aa1b14e7SSheshadri Vasudevan 		rowcount++;
5025*aa1b14e7SSheshadri Vasudevan 		if (rowcount == rowmax) {
5026*aa1b14e7SSheshadri Vasudevan 			/*
5027*aa1b14e7SSheshadri Vasudevan 			 * After the initial screen, use all the rows for
5028*aa1b14e7SSheshadri Vasudevan 			 * printing the partition IDs, but one.
5029*aa1b14e7SSheshadri Vasudevan 			 */
5030*aa1b14e7SSheshadri Vasudevan 			rowmax = ws.ws_row - 1;
5031*aa1b14e7SSheshadri Vasudevan 			fprintf(stderr, "\nPress enter to see next page or 'q'"
5032*aa1b14e7SSheshadri Vasudevan 			    " to quit : ");
5033*aa1b14e7SSheshadri Vasudevan 			ext_read_input(buf);
5034*aa1b14e7SSheshadri Vasudevan 			if ((strlen(buf) == 2) && (tolower(buf[0]) == 'q')) {
5035*aa1b14e7SSheshadri Vasudevan 				return;
5036*aa1b14e7SSheshadri Vasudevan 			}
5037*aa1b14e7SSheshadri Vasudevan 			rowcount = 1;
5038*aa1b14e7SSheshadri Vasudevan 		}
5039*aa1b14e7SSheshadri Vasudevan 	}
5040*aa1b14e7SSheshadri Vasudevan }
5041*aa1b14e7SSheshadri Vasudevan 
5042*aa1b14e7SSheshadri Vasudevan static void
5043*aa1b14e7SSheshadri Vasudevan ext_read_valid_part_num(int *pno)
5044*aa1b14e7SSheshadri Vasudevan {
5045*aa1b14e7SSheshadri Vasudevan 	char buf[80];
5046*aa1b14e7SSheshadri Vasudevan 	int len, i;
5047*aa1b14e7SSheshadri Vasudevan 
5048*aa1b14e7SSheshadri Vasudevan 	for (;;) {
5049*aa1b14e7SSheshadri Vasudevan 		printf("Enter the partition number : ");
5050*aa1b14e7SSheshadri Vasudevan 		ext_read_input(buf);
5051*aa1b14e7SSheshadri Vasudevan 
5052*aa1b14e7SSheshadri Vasudevan 		len = strlen(buf);
5053*aa1b14e7SSheshadri Vasudevan 
5054*aa1b14e7SSheshadri Vasudevan 		/* Check length of the input */
5055*aa1b14e7SSheshadri Vasudevan 		if ((len < 2) || (len > (FDISK_MAX_VALID_PART_NUM_DIGITS+1))) {
5056*aa1b14e7SSheshadri Vasudevan 			goto print_error_and_continue;
5057*aa1b14e7SSheshadri Vasudevan 		}
5058*aa1b14e7SSheshadri Vasudevan 
5059*aa1b14e7SSheshadri Vasudevan 		/* Check if there is a non-digit in the input */
5060*aa1b14e7SSheshadri Vasudevan 		for (i = 0; i < len-1; i++) {
5061*aa1b14e7SSheshadri Vasudevan 			if (!isdigit(buf[i])) {
5062*aa1b14e7SSheshadri Vasudevan 				goto print_error_and_continue;
5063*aa1b14e7SSheshadri Vasudevan 			}
5064*aa1b14e7SSheshadri Vasudevan 		}
5065*aa1b14e7SSheshadri Vasudevan 
5066*aa1b14e7SSheshadri Vasudevan 		*pno = atoi(buf);
5067*aa1b14e7SSheshadri Vasudevan 
5068*aa1b14e7SSheshadri Vasudevan 		if ((*pno <= FD_NUMPART) ||
5069*aa1b14e7SSheshadri Vasudevan 		    *pno > (fdisk_get_logical_drive_count(epp) + FD_NUMPART)) {
5070*aa1b14e7SSheshadri Vasudevan 			goto print_error_and_continue;
5071*aa1b14e7SSheshadri Vasudevan 		}
5072*aa1b14e7SSheshadri Vasudevan 
5073*aa1b14e7SSheshadri Vasudevan 		break;
5074*aa1b14e7SSheshadri Vasudevan print_error_and_continue:
5075*aa1b14e7SSheshadri Vasudevan 		printf("Invalid partition number\n");
5076*aa1b14e7SSheshadri Vasudevan 		continue;
5077*aa1b14e7SSheshadri Vasudevan 	}
5078*aa1b14e7SSheshadri Vasudevan }
5079*aa1b14e7SSheshadri Vasudevan 
5080*aa1b14e7SSheshadri Vasudevan static void
5081*aa1b14e7SSheshadri Vasudevan ext_read_valid_part_id(uchar_t *partid)
5082*aa1b14e7SSheshadri Vasudevan {
5083*aa1b14e7SSheshadri Vasudevan 	char buf[80];
5084*aa1b14e7SSheshadri Vasudevan 	int len, i, id;
5085*aa1b14e7SSheshadri Vasudevan 
5086*aa1b14e7SSheshadri Vasudevan 	for (;;) {
5087*aa1b14e7SSheshadri Vasudevan 		printf("Enter the ID ( Type I for list of partition IDs ) : ");
5088*aa1b14e7SSheshadri Vasudevan 		ext_read_input(buf);
5089*aa1b14e7SSheshadri Vasudevan 		len = strlen(buf);
5090*aa1b14e7SSheshadri Vasudevan 
5091*aa1b14e7SSheshadri Vasudevan 		if ((len < 2) || (len > (FDISK_MAX_VALID_PART_ID_DIGITS + 1))) {
5092*aa1b14e7SSheshadri Vasudevan 			printf("Invalid partition ID\n");
5093*aa1b14e7SSheshadri Vasudevan 			continue;
5094*aa1b14e7SSheshadri Vasudevan 		}
5095*aa1b14e7SSheshadri Vasudevan 
5096*aa1b14e7SSheshadri Vasudevan 		if ((len == 2) && (toupper(buf[0]) == 'I')) {
5097*aa1b14e7SSheshadri Vasudevan 			ext_print_part_types();
5098*aa1b14e7SSheshadri Vasudevan 			continue;
5099*aa1b14e7SSheshadri Vasudevan 		}
5100*aa1b14e7SSheshadri Vasudevan 
5101*aa1b14e7SSheshadri Vasudevan 		/* Check if there is a non-digit in the input */
5102*aa1b14e7SSheshadri Vasudevan 		for (i = 0; i < len-1; i++) {
5103*aa1b14e7SSheshadri Vasudevan 			if (!isdigit(buf[i])) {
5104*aa1b14e7SSheshadri Vasudevan 				printf("Invalid partition ID\n");
5105*aa1b14e7SSheshadri Vasudevan 				break;
5106*aa1b14e7SSheshadri Vasudevan 			}
5107*aa1b14e7SSheshadri Vasudevan 		}
5108*aa1b14e7SSheshadri Vasudevan 
5109*aa1b14e7SSheshadri Vasudevan 		if (i < len - 1) {
5110*aa1b14e7SSheshadri Vasudevan 			continue;
5111*aa1b14e7SSheshadri Vasudevan 		}
5112*aa1b14e7SSheshadri Vasudevan 
5113*aa1b14e7SSheshadri Vasudevan 		/* Check if the (now) valid number is greater than the limit */
5114*aa1b14e7SSheshadri Vasudevan 		if ((id = atoi(buf)) > FDISK_MAX_VALID_PART_ID) {
5115*aa1b14e7SSheshadri Vasudevan 			printf("Invalid partition ID\n");
5116*aa1b14e7SSheshadri Vasudevan 			continue;
5117*aa1b14e7SSheshadri Vasudevan 		}
5118*aa1b14e7SSheshadri Vasudevan 
5119*aa1b14e7SSheshadri Vasudevan 		*partid = (uchar_t)id;
5120*aa1b14e7SSheshadri Vasudevan 
5121*aa1b14e7SSheshadri Vasudevan 		/* Disallow multiple extended partitions */
5122*aa1b14e7SSheshadri Vasudevan 		if (fdisk_is_dos_extended(*partid)) {
5123*aa1b14e7SSheshadri Vasudevan 			printf("Multiple extended partitions not allowed\n");
5124*aa1b14e7SSheshadri Vasudevan 			continue;
5125*aa1b14e7SSheshadri Vasudevan 		}
5126*aa1b14e7SSheshadri Vasudevan 
5127*aa1b14e7SSheshadri Vasudevan 		/* Disallow EFI partitions within extended partition */
5128*aa1b14e7SSheshadri Vasudevan 		if (*partid == EFI_PMBR) {
5129*aa1b14e7SSheshadri Vasudevan 			printf("EFI partitions within an extended partition"
5130*aa1b14e7SSheshadri Vasudevan 			    " is not allowed\n");
5131*aa1b14e7SSheshadri Vasudevan 			continue;
5132*aa1b14e7SSheshadri Vasudevan 		}
5133*aa1b14e7SSheshadri Vasudevan 
5134*aa1b14e7SSheshadri Vasudevan 		return; /* Valid partition ID is in partid */
5135*aa1b14e7SSheshadri Vasudevan 	}
5136*aa1b14e7SSheshadri Vasudevan }
5137*aa1b14e7SSheshadri Vasudevan 
5138*aa1b14e7SSheshadri Vasudevan static void
5139*aa1b14e7SSheshadri Vasudevan delete_logical_drive()
5140*aa1b14e7SSheshadri Vasudevan {
5141*aa1b14e7SSheshadri Vasudevan 	int pno;
5142*aa1b14e7SSheshadri Vasudevan 
5143*aa1b14e7SSheshadri Vasudevan 	if (!fdisk_get_logical_drive_count(epp)) {
5144*aa1b14e7SSheshadri Vasudevan 		printf("\nNo logical drives defined.\n");
5145*aa1b14e7SSheshadri Vasudevan 		return;
5146*aa1b14e7SSheshadri Vasudevan 	}
5147*aa1b14e7SSheshadri Vasudevan 
5148*aa1b14e7SSheshadri Vasudevan 	printf("\n");
5149*aa1b14e7SSheshadri Vasudevan 	ext_read_valid_part_num(&pno);
5150*aa1b14e7SSheshadri Vasudevan 	fdisk_delete_logical_drive(epp, pno);
5151*aa1b14e7SSheshadri Vasudevan 	printf("Partition %d deleted\n", pno);
5152*aa1b14e7SSheshadri Vasudevan }
5153*aa1b14e7SSheshadri Vasudevan 
5154*aa1b14e7SSheshadri Vasudevan static int
5155*aa1b14e7SSheshadri Vasudevan ext_read_valid_partition_start(uint32_t *begsec)
5156*aa1b14e7SSheshadri Vasudevan {
5157*aa1b14e7SSheshadri Vasudevan 	char buf[80];
5158*aa1b14e7SSheshadri Vasudevan 	int ret, len, i;
5159*aa1b14e7SSheshadri Vasudevan 	uint32_t begcyl;
5160*aa1b14e7SSheshadri Vasudevan 	uint32_t first_free_cyl;
5161*aa1b14e7SSheshadri Vasudevan 	uint32_t first_free_sec;
5162*aa1b14e7SSheshadri Vasudevan 
5163*aa1b14e7SSheshadri Vasudevan 	ret = fdisk_ext_find_first_free_sec(epp, &first_free_sec);
5164*aa1b14e7SSheshadri Vasudevan 	if (ret != FDISK_SUCCESS) {
5165*aa1b14e7SSheshadri Vasudevan 		return (ret);
5166*aa1b14e7SSheshadri Vasudevan 	}
5167*aa1b14e7SSheshadri Vasudevan 
5168*aa1b14e7SSheshadri Vasudevan 	first_free_cyl = FDISK_SECT_TO_CYL(epp, first_free_sec);
5169*aa1b14e7SSheshadri Vasudevan 	for (;;) {
5170*aa1b14e7SSheshadri Vasudevan 		printf("Enter the beginning cylinder (Default - %d) : ",
5171*aa1b14e7SSheshadri Vasudevan 		    first_free_cyl);
5172*aa1b14e7SSheshadri Vasudevan 		ext_read_input(buf);
5173*aa1b14e7SSheshadri Vasudevan 		len = strlen(buf);
5174*aa1b14e7SSheshadri Vasudevan 		if (len == 1) { /* User accepted the default value */
5175*aa1b14e7SSheshadri Vasudevan 			*begsec = first_free_sec;
5176*aa1b14e7SSheshadri Vasudevan 			return (FDISK_SUCCESS);
5177*aa1b14e7SSheshadri Vasudevan 		}
5178*aa1b14e7SSheshadri Vasudevan 
5179*aa1b14e7SSheshadri Vasudevan 		if (len > (FDISK_MAX_VALID_CYL_NUM_DIGITS + 1)) {
5180*aa1b14e7SSheshadri Vasudevan 			printf("Input too long\n");
5181*aa1b14e7SSheshadri Vasudevan 			printf("Invalid beginning cylinder number\n");
5182*aa1b14e7SSheshadri Vasudevan 			continue;
5183*aa1b14e7SSheshadri Vasudevan 		}
5184*aa1b14e7SSheshadri Vasudevan 		/* Check if there is a non-digit in the input */
5185*aa1b14e7SSheshadri Vasudevan 		for (i = 0; i < len - 1; i++) {
5186*aa1b14e7SSheshadri Vasudevan 			if (!isdigit(buf[i])) {
5187*aa1b14e7SSheshadri Vasudevan 				printf("Invalid beginning cylinder number\n");
5188*aa1b14e7SSheshadri Vasudevan 				break;
5189*aa1b14e7SSheshadri Vasudevan 			}
5190*aa1b14e7SSheshadri Vasudevan 		}
5191*aa1b14e7SSheshadri Vasudevan 		if (i < len - 1) {
5192*aa1b14e7SSheshadri Vasudevan 			continue;
5193*aa1b14e7SSheshadri Vasudevan 		}
5194*aa1b14e7SSheshadri Vasudevan 
5195*aa1b14e7SSheshadri Vasudevan 		begcyl = atoi(buf);
5196*aa1b14e7SSheshadri Vasudevan 		ret = fdisk_ext_validate_part_start(epp, begcyl, begsec);
5197*aa1b14e7SSheshadri Vasudevan 		switch (ret) {
5198*aa1b14e7SSheshadri Vasudevan 			case FDISK_SUCCESS:
5199*aa1b14e7SSheshadri Vasudevan 				/*
5200*aa1b14e7SSheshadri Vasudevan 				 * Success.
5201*aa1b14e7SSheshadri Vasudevan 				 * Valid beginning sector is in begsec
5202*aa1b14e7SSheshadri Vasudevan 				 */
5203*aa1b14e7SSheshadri Vasudevan 				break;
5204*aa1b14e7SSheshadri Vasudevan 
5205*aa1b14e7SSheshadri Vasudevan 			case FDISK_EOVERLAP:
5206*aa1b14e7SSheshadri Vasudevan 				printf("Partition boundary overlaps with ");
5207*aa1b14e7SSheshadri Vasudevan 				printf("existing partitions\n");
5208*aa1b14e7SSheshadri Vasudevan 				printf("Invalid beginning cylinder number\n");
5209*aa1b14e7SSheshadri Vasudevan 				continue;
5210*aa1b14e7SSheshadri Vasudevan 
5211*aa1b14e7SSheshadri Vasudevan 			case FDISK_EOOBOUND:
5212*aa1b14e7SSheshadri Vasudevan 				printf("Cylinder boundary beyond the limits\n");
5213*aa1b14e7SSheshadri Vasudevan 				printf("Invalid beginning cylinder number\n");
5214*aa1b14e7SSheshadri Vasudevan 				continue;
5215*aa1b14e7SSheshadri Vasudevan 		}
5216*aa1b14e7SSheshadri Vasudevan 		return (FDISK_SUCCESS);
5217*aa1b14e7SSheshadri Vasudevan 	}
5218*aa1b14e7SSheshadri Vasudevan }
5219*aa1b14e7SSheshadri Vasudevan 
5220*aa1b14e7SSheshadri Vasudevan /*
5221*aa1b14e7SSheshadri Vasudevan  * Algorithm :
5222*aa1b14e7SSheshadri Vasudevan  * 1. Check if the first character is a +
5223*aa1b14e7SSheshadri Vasudevan  *	a) If yes, check if the last character is 'k', 'm' or 'g'
5224*aa1b14e7SSheshadri Vasudevan  * 2. If not, check if there are any non-digits
5225*aa1b14e7SSheshadri Vasudevan  * 3. Check for the length of the numeral string
5226*aa1b14e7SSheshadri Vasudevan  * 4. atoi the numeral string
5227*aa1b14e7SSheshadri Vasudevan  * 5. In case of data entered in KB, MB or GB, convert it to number of cylinders
5228*aa1b14e7SSheshadri Vasudevan  *	a) Adjust size to be cylinder boundary aligned
5229*aa1b14e7SSheshadri Vasudevan  * 6. If size specifies is zero, flag error
5230*aa1b14e7SSheshadri Vasudevan  * 7. Check if the size is less than 1 cylinder
5231*aa1b14e7SSheshadri Vasudevan  *	a) If yes, default the size FDISK_MIN_PART_SIZE
5232*aa1b14e7SSheshadri Vasudevan  * 	b) If no, Check if the size is within endcyl - begcyl
5233*aa1b14e7SSheshadri Vasudevan  */
5234*aa1b14e7SSheshadri Vasudevan static void
5235*aa1b14e7SSheshadri Vasudevan ext_read_valid_partition_size(uint32_t begsec, uint32_t *endsec)
5236*aa1b14e7SSheshadri Vasudevan {
5237*aa1b14e7SSheshadri Vasudevan 	char buf[80];
5238*aa1b14e7SSheshadri Vasudevan 	uint32_t tempcyl;
5239*aa1b14e7SSheshadri Vasudevan 	uint32_t last_free_sec;
5240*aa1b14e7SSheshadri Vasudevan 	uint32_t last_free_cyl;
5241*aa1b14e7SSheshadri Vasudevan 	int i, len, ch, mbgb = 0, scale = FDISK_SECTS_PER_CYL(epp);
5242*aa1b14e7SSheshadri Vasudevan 	uint64_t size = 0;
5243*aa1b14e7SSheshadri Vasudevan 	int copy_len;
5244*aa1b14e7SSheshadri Vasudevan 	char numbuf[FDISK_MAX_VALID_CYL_NUM_DIGITS + 1];
5245*aa1b14e7SSheshadri Vasudevan 	int sectsize = fdisk_get_disk_geom(epp, PHYSGEOM, SSIZE);
5246*aa1b14e7SSheshadri Vasudevan 	uint32_t remdr, spc, poss_end;
5247*aa1b14e7SSheshadri Vasudevan 
5248*aa1b14e7SSheshadri Vasudevan 	if (sectsize == EINVAL) {
5249*aa1b14e7SSheshadri Vasudevan 		fprintf(stderr, "Unsupported geometry statistics.\n");
5250*aa1b14e7SSheshadri Vasudevan 		exit(1);
5251*aa1b14e7SSheshadri Vasudevan 	}
5252*aa1b14e7SSheshadri Vasudevan 
5253*aa1b14e7SSheshadri Vasudevan 	last_free_sec = fdisk_ext_find_last_free_sec(epp, begsec);
5254*aa1b14e7SSheshadri Vasudevan 	last_free_cyl = FDISK_SECT_TO_CYL(epp, last_free_sec);
5255*aa1b14e7SSheshadri Vasudevan 
5256*aa1b14e7SSheshadri Vasudevan 	for (;;) {
5257*aa1b14e7SSheshadri Vasudevan 		printf("Enter the size in cylinders (Default End Cylinder -");
5258*aa1b14e7SSheshadri Vasudevan 		printf(" %u)\n", last_free_cyl);
5259*aa1b14e7SSheshadri Vasudevan 		printf("Type +<size>K, +<size>M or +<size>G to enter size in");
5260*aa1b14e7SSheshadri Vasudevan 		printf("KB, MB or GB : ");
5261*aa1b14e7SSheshadri Vasudevan 		ext_read_input(buf);
5262*aa1b14e7SSheshadri Vasudevan 		len = strlen(buf);
5263*aa1b14e7SSheshadri Vasudevan 		mbgb = 0;
5264*aa1b14e7SSheshadri Vasudevan 		scale = FDISK_SECTS_PER_CYL(epp);
5265*aa1b14e7SSheshadri Vasudevan 
5266*aa1b14e7SSheshadri Vasudevan 		if (len == 1) { /* User accepted the default value */
5267*aa1b14e7SSheshadri Vasudevan 			*endsec = last_free_sec;
5268*aa1b14e7SSheshadri Vasudevan 			return;
5269*aa1b14e7SSheshadri Vasudevan 		}
5270*aa1b14e7SSheshadri Vasudevan 
5271*aa1b14e7SSheshadri Vasudevan 		copy_len = len - 1;
5272*aa1b14e7SSheshadri Vasudevan 
5273*aa1b14e7SSheshadri Vasudevan 		if ((buf[0] == '+') && (isdigit(buf[1]))) {
5274*aa1b14e7SSheshadri Vasudevan 			copy_len--;
5275*aa1b14e7SSheshadri Vasudevan 			if ((ch = toupper(buf[len - 2])) == 'B') {
5276*aa1b14e7SSheshadri Vasudevan 				ch = toupper(buf[len - 3]);
5277*aa1b14e7SSheshadri Vasudevan 				copy_len--;
5278*aa1b14e7SSheshadri Vasudevan 			}
5279*aa1b14e7SSheshadri Vasudevan 
5280*aa1b14e7SSheshadri Vasudevan 			if (!((ch == 'K') || (ch == 'M') || (ch == 'G'))) {
5281*aa1b14e7SSheshadri Vasudevan 				printf("Invalid partition size\n");
5282*aa1b14e7SSheshadri Vasudevan 				continue;
5283*aa1b14e7SSheshadri Vasudevan 			}
5284*aa1b14e7SSheshadri Vasudevan 
5285*aa1b14e7SSheshadri Vasudevan 			copy_len--;
5286*aa1b14e7SSheshadri Vasudevan 			mbgb = 1;
5287*aa1b14e7SSheshadri Vasudevan 			scale = ((ch == 'K') ? FDISK_KB :
5288*aa1b14e7SSheshadri Vasudevan 			    ((ch == 'M') ? FDISK_MB : FDISK_GB));
5289*aa1b14e7SSheshadri Vasudevan 		}
5290*aa1b14e7SSheshadri Vasudevan 
5291*aa1b14e7SSheshadri Vasudevan 		if (copy_len > FDISK_MAX_VALID_CYL_NUM_DIGITS) {
5292*aa1b14e7SSheshadri Vasudevan 			printf("Input too long\n");
5293*aa1b14e7SSheshadri Vasudevan 			printf("Invalid partition size\n");
5294*aa1b14e7SSheshadri Vasudevan 			continue;
5295*aa1b14e7SSheshadri Vasudevan 		}
5296*aa1b14e7SSheshadri Vasudevan 
5297*aa1b14e7SSheshadri Vasudevan 		strncpy(numbuf, &buf[mbgb], copy_len);
5298*aa1b14e7SSheshadri Vasudevan 		numbuf[copy_len] = '\0';
5299*aa1b14e7SSheshadri Vasudevan 
5300*aa1b14e7SSheshadri Vasudevan 		for (i = mbgb; i < copy_len + mbgb; i++) {
5301*aa1b14e7SSheshadri Vasudevan 			if (!isdigit(buf[i])) {
5302*aa1b14e7SSheshadri Vasudevan 				break;
5303*aa1b14e7SSheshadri Vasudevan 			}
5304*aa1b14e7SSheshadri Vasudevan 		}
5305*aa1b14e7SSheshadri Vasudevan 
5306*aa1b14e7SSheshadri Vasudevan 		if (i < copy_len + mbgb) {
5307*aa1b14e7SSheshadri Vasudevan 			printf("Invalid partition size\n");
5308*aa1b14e7SSheshadri Vasudevan 			continue;
5309*aa1b14e7SSheshadri Vasudevan 		}
5310*aa1b14e7SSheshadri Vasudevan 
5311*aa1b14e7SSheshadri Vasudevan 		size = (atoll(numbuf) * (scale));
5312*aa1b14e7SSheshadri Vasudevan 
5313*aa1b14e7SSheshadri Vasudevan 		if (size == 0) {
5314*aa1b14e7SSheshadri Vasudevan 			printf("Zero size is invalid\n");
5315*aa1b14e7SSheshadri Vasudevan 			printf("Invalid partition size\n");
5316*aa1b14e7SSheshadri Vasudevan 			continue;
5317*aa1b14e7SSheshadri Vasudevan 		}
5318*aa1b14e7SSheshadri Vasudevan 
5319*aa1b14e7SSheshadri Vasudevan 		if (mbgb) {
5320*aa1b14e7SSheshadri Vasudevan 			size /= sectsize;
5321*aa1b14e7SSheshadri Vasudevan 		}
5322*aa1b14e7SSheshadri Vasudevan 
5323*aa1b14e7SSheshadri Vasudevan 		if (size > (last_free_sec - begsec + 1)) {
5324*aa1b14e7SSheshadri Vasudevan 			printf("Cylinder boundary beyond the limits");
5325*aa1b14e7SSheshadri Vasudevan 			printf(" or overlaps with existing");
5326*aa1b14e7SSheshadri Vasudevan 			printf(" partitions\n");
5327*aa1b14e7SSheshadri Vasudevan 			printf("Invalid partition size\n");
5328*aa1b14e7SSheshadri Vasudevan 			continue;
5329*aa1b14e7SSheshadri Vasudevan 		}
5330*aa1b14e7SSheshadri Vasudevan 
5331*aa1b14e7SSheshadri Vasudevan 		/*
5332*aa1b14e7SSheshadri Vasudevan 		 * Adjust the ending sector such that there are no partial
5333*aa1b14e7SSheshadri Vasudevan 		 * cylinders allocated. But at the same time, make sure it
5334*aa1b14e7SSheshadri Vasudevan 		 * doesn't over shoot boundaries.
5335*aa1b14e7SSheshadri Vasudevan 		 */
5336*aa1b14e7SSheshadri Vasudevan 		spc = FDISK_SECTS_PER_CYL(epp);
5337*aa1b14e7SSheshadri Vasudevan 		poss_end = begsec + size - 1;
5338*aa1b14e7SSheshadri Vasudevan 		if (remdr = (poss_end % spc)) {
5339*aa1b14e7SSheshadri Vasudevan 			poss_end += spc - remdr - 1;
5340*aa1b14e7SSheshadri Vasudevan 		}
5341*aa1b14e7SSheshadri Vasudevan 		*endsec = (poss_end > last_free_sec) ? last_free_sec :
5342*aa1b14e7SSheshadri Vasudevan 		    poss_end;
5343*aa1b14e7SSheshadri Vasudevan 
5344*aa1b14e7SSheshadri Vasudevan 		return;
5345*aa1b14e7SSheshadri Vasudevan 	}
5346*aa1b14e7SSheshadri Vasudevan }
5347*aa1b14e7SSheshadri Vasudevan 
5348*aa1b14e7SSheshadri Vasudevan /*
5349*aa1b14e7SSheshadri Vasudevan  * ALGORITHM:
5350*aa1b14e7SSheshadri Vasudevan  * 1. Get the starting and ending sectors/cylinder of the extended partition.
5351*aa1b14e7SSheshadri Vasudevan  * 2. Keep track of the first free sector/cylinder
5352*aa1b14e7SSheshadri Vasudevan  * 3. Allow the user to specify the beginning cylinder of the new partition
5353*aa1b14e7SSheshadri Vasudevan  * 4. Check for the validity of the entered data
5354*aa1b14e7SSheshadri Vasudevan  *	a) If it is non-numeric
5355*aa1b14e7SSheshadri Vasudevan  *	b) If it is beyond the extended partition limits
5356*aa1b14e7SSheshadri Vasudevan  *	c) If it overlaps with the current logical drives
5357*aa1b14e7SSheshadri Vasudevan  * 5. Allow the user to specify the size in cylinders/ human readable form
5358*aa1b14e7SSheshadri Vasudevan  * 6. Check for the validity of the entered data
5359*aa1b14e7SSheshadri Vasudevan  *	a) If it is non-numeric
5360*aa1b14e7SSheshadri Vasudevan  *	b) If it is beyond the extended partition limits
5361*aa1b14e7SSheshadri Vasudevan  *	c) If it overlaps with the current logical drives
5362*aa1b14e7SSheshadri Vasudevan  *	d) If it is a number lesser than the starting cylinder
5363*aa1b14e7SSheshadri Vasudevan  * 7. Request partition ID for the new partition.
5364*aa1b14e7SSheshadri Vasudevan  * 8. Update the first free cylinder available
5365*aa1b14e7SSheshadri Vasudevan  * 9. Display Success message
5366*aa1b14e7SSheshadri Vasudevan  */
5367*aa1b14e7SSheshadri Vasudevan 
5368*aa1b14e7SSheshadri Vasudevan static void
5369*aa1b14e7SSheshadri Vasudevan add_logical_drive()
5370*aa1b14e7SSheshadri Vasudevan {
5371*aa1b14e7SSheshadri Vasudevan 	uint32_t begsec, endsec;
5372*aa1b14e7SSheshadri Vasudevan 	uchar_t partid;
5373*aa1b14e7SSheshadri Vasudevan 	char buf[80];
5374*aa1b14e7SSheshadri Vasudevan 	int rval;
5375*aa1b14e7SSheshadri Vasudevan 
5376*aa1b14e7SSheshadri Vasudevan 	if (fdisk_get_logical_drive_count(epp) >= MAX_EXT_PARTS) {
5377*aa1b14e7SSheshadri Vasudevan 		printf("\nNumber of logical drives exceeds limit of %d.\n",
5378*aa1b14e7SSheshadri Vasudevan 		    MAX_EXT_PARTS);
5379*aa1b14e7SSheshadri Vasudevan 		printf("Command did not succeed. Press enter to continue\n");
5380*aa1b14e7SSheshadri Vasudevan 		ext_read_input(buf);
5381*aa1b14e7SSheshadri Vasudevan 		return;
5382*aa1b14e7SSheshadri Vasudevan 	}
5383*aa1b14e7SSheshadri Vasudevan 
5384*aa1b14e7SSheshadri Vasudevan 	printf("\n");
5385*aa1b14e7SSheshadri Vasudevan 	rval = ext_read_valid_partition_start(&begsec);
5386*aa1b14e7SSheshadri Vasudevan 	switch (rval) {
5387*aa1b14e7SSheshadri Vasudevan 		case FDISK_SUCCESS:
5388*aa1b14e7SSheshadri Vasudevan 			break;
5389*aa1b14e7SSheshadri Vasudevan 
5390*aa1b14e7SSheshadri Vasudevan 		case FDISK_EOOBOUND:
5391*aa1b14e7SSheshadri Vasudevan 			printf("\nNo space left in the extended partition\n");
5392*aa1b14e7SSheshadri Vasudevan 			printf("Press enter to continue\n");
5393*aa1b14e7SSheshadri Vasudevan 			ext_read_input(buf);
5394*aa1b14e7SSheshadri Vasudevan 			return;
5395*aa1b14e7SSheshadri Vasudevan 	}
5396*aa1b14e7SSheshadri Vasudevan 
5397*aa1b14e7SSheshadri Vasudevan 	ext_read_valid_partition_size(begsec, &endsec);
5398*aa1b14e7SSheshadri Vasudevan 	ext_read_valid_part_id(&partid);
5399*aa1b14e7SSheshadri Vasudevan 	fdisk_add_logical_drive(epp, begsec, endsec, partid);
5400*aa1b14e7SSheshadri Vasudevan 
5401*aa1b14e7SSheshadri Vasudevan 	printf("New partition with ID %d added\n", partid);
5402*aa1b14e7SSheshadri Vasudevan }
5403*aa1b14e7SSheshadri Vasudevan 
5404*aa1b14e7SSheshadri Vasudevan static void
5405*aa1b14e7SSheshadri Vasudevan ext_change_logical_drive_id()
5406*aa1b14e7SSheshadri Vasudevan {
5407*aa1b14e7SSheshadri Vasudevan 	int pno;
5408*aa1b14e7SSheshadri Vasudevan 	uchar_t partid;
5409*aa1b14e7SSheshadri Vasudevan 
5410*aa1b14e7SSheshadri Vasudevan 	if (!fdisk_get_logical_drive_count(epp)) {
5411*aa1b14e7SSheshadri Vasudevan 		printf("\nNo logical drives defined.\n");
5412*aa1b14e7SSheshadri Vasudevan 		return;
5413*aa1b14e7SSheshadri Vasudevan 	}
5414*aa1b14e7SSheshadri Vasudevan 
5415*aa1b14e7SSheshadri Vasudevan 	printf("\n");
5416*aa1b14e7SSheshadri Vasudevan 	ext_read_valid_part_num(&pno);
5417*aa1b14e7SSheshadri Vasudevan 	ext_read_valid_part_id(&partid);
5418*aa1b14e7SSheshadri Vasudevan 	fdisk_change_logical_drive_id(epp, pno, partid);
5419*aa1b14e7SSheshadri Vasudevan 
5420*aa1b14e7SSheshadri Vasudevan 	printf("Partition ID of partition %d changed to %d\n", pno, partid);
5421*aa1b14e7SSheshadri Vasudevan }
5422*aa1b14e7SSheshadri Vasudevan 
5423*aa1b14e7SSheshadri Vasudevan #ifdef DEBUG
5424*aa1b14e7SSheshadri Vasudevan static void
5425*aa1b14e7SSheshadri Vasudevan ext_print_logdrive_layout_debug()
5426*aa1b14e7SSheshadri Vasudevan {
5427*aa1b14e7SSheshadri Vasudevan 	int pno;
5428*aa1b14e7SSheshadri Vasudevan 	char namebuff[255];
5429*aa1b14e7SSheshadri Vasudevan 	logical_drive_t *head = fdisk_get_ld_head(epp);
5430*aa1b14e7SSheshadri Vasudevan 	logical_drive_t *temp;
5431*aa1b14e7SSheshadri Vasudevan 
5432*aa1b14e7SSheshadri Vasudevan 	if (!fdisk_get_logical_drive_count(epp)) {
5433*aa1b14e7SSheshadri Vasudevan 		printf("\nNo logical drives defined.\n");
5434*aa1b14e7SSheshadri Vasudevan 		return;
5435*aa1b14e7SSheshadri Vasudevan 	}
5436*aa1b14e7SSheshadri Vasudevan 
5437*aa1b14e7SSheshadri Vasudevan 	printf("\n\n");
5438*aa1b14e7SSheshadri Vasudevan 	puts("#  start block  end block    abs start    abs end      OSType");
5439*aa1b14e7SSheshadri Vasudevan 	for (temp = head, pno = 5; temp != NULL; temp = temp->next, pno++) {
5440*aa1b14e7SSheshadri Vasudevan 		/* Print the logical drive details */
5441*aa1b14e7SSheshadri Vasudevan 		id_to_name(temp->parts[0].systid, namebuff);
5442*aa1b14e7SSheshadri Vasudevan 		printf("%d: %.10u   %.10u   %.10u   %.10u",
5443*aa1b14e7SSheshadri Vasudevan 		    pno,
5444*aa1b14e7SSheshadri Vasudevan 		    LE_32(temp->parts[0].relsect),
5445*aa1b14e7SSheshadri Vasudevan 		    LE_32(temp->parts[0].numsect),
5446*aa1b14e7SSheshadri Vasudevan 		    temp->abs_secnum,
5447*aa1b14e7SSheshadri Vasudevan 		    temp->abs_secnum + temp->numsect - 1 +
5448*aa1b14e7SSheshadri Vasudevan 		    MAX_LOGDRIVE_OFFSET);
5449*aa1b14e7SSheshadri Vasudevan 		printf("   %s\n", namebuff);
5450*aa1b14e7SSheshadri Vasudevan 		/*
5451*aa1b14e7SSheshadri Vasudevan 		 * Print the second entry in the EBR which is information
5452*aa1b14e7SSheshadri Vasudevan 		 * about the location and the size of the next extended
5453*aa1b14e7SSheshadri Vasudevan 		 * partition.
5454*aa1b14e7SSheshadri Vasudevan 		 */
5455*aa1b14e7SSheshadri Vasudevan 		id_to_name(temp->parts[1].systid, namebuff);
5456*aa1b14e7SSheshadri Vasudevan 		printf("%d: %.10u   %.10u   %.10s   %.10s",
5457*aa1b14e7SSheshadri Vasudevan 		    pno,
5458*aa1b14e7SSheshadri Vasudevan 		    LE_32(temp->parts[1].relsect),
5459*aa1b14e7SSheshadri Vasudevan 		    LE_32(temp->parts[1].numsect),
5460*aa1b14e7SSheshadri Vasudevan 		    "          ", "          ");
5461*aa1b14e7SSheshadri Vasudevan 		printf("   %s\n", namebuff);
5462*aa1b14e7SSheshadri Vasudevan 	}
5463*aa1b14e7SSheshadri Vasudevan }
5464*aa1b14e7SSheshadri Vasudevan #endif
5465*aa1b14e7SSheshadri Vasudevan 
5466*aa1b14e7SSheshadri Vasudevan static void
5467*aa1b14e7SSheshadri Vasudevan ext_print_logical_drive_layout()
5468*aa1b14e7SSheshadri Vasudevan {
5469*aa1b14e7SSheshadri Vasudevan 	int sysid;
5470*aa1b14e7SSheshadri Vasudevan 	unsigned int startcyl, endcyl, length, percent, remainder;
5471*aa1b14e7SSheshadri Vasudevan 	logical_drive_t *temp;
5472*aa1b14e7SSheshadri Vasudevan 	struct ipart *fpart;
5473*aa1b14e7SSheshadri Vasudevan 	char namebuff[255];
5474*aa1b14e7SSheshadri Vasudevan 	int numcyl = fdisk_get_disk_geom(epp, PHYSGEOM, NCYL);
5475*aa1b14e7SSheshadri Vasudevan 	int pno;
5476*aa1b14e7SSheshadri Vasudevan 
5477*aa1b14e7SSheshadri Vasudevan 	if (numcyl == EINVAL) {
5478*aa1b14e7SSheshadri Vasudevan 		fprintf(stderr, "Unsupported geometry statistics.\n");
5479*aa1b14e7SSheshadri Vasudevan 		exit(1);
5480*aa1b14e7SSheshadri Vasudevan 	}
5481*aa1b14e7SSheshadri Vasudevan 
5482*aa1b14e7SSheshadri Vasudevan 	if (!fdisk_get_logical_drive_count(epp)) {
5483*aa1b14e7SSheshadri Vasudevan 		printf("\nNo logical drives defined.\n");
5484*aa1b14e7SSheshadri Vasudevan 		return;
5485*aa1b14e7SSheshadri Vasudevan 	}
5486*aa1b14e7SSheshadri Vasudevan 
5487*aa1b14e7SSheshadri Vasudevan 	printf("\n");
5488*aa1b14e7SSheshadri Vasudevan 	printf("Number of cylinders in disk              : %u\n", numcyl);
5489*aa1b14e7SSheshadri Vasudevan 	printf("Beginning cylinder of extended partition : %u\n",
5490*aa1b14e7SSheshadri Vasudevan 	    fdisk_get_ext_beg_cyl(epp));
5491*aa1b14e7SSheshadri Vasudevan 	printf("Ending cylinder of extended partition    : %u\n",
5492*aa1b14e7SSheshadri Vasudevan 	    fdisk_get_ext_end_cyl(epp));
5493*aa1b14e7SSheshadri Vasudevan 	printf("\n");
5494*aa1b14e7SSheshadri Vasudevan 	printf("Part#   StartCyl   EndCyl     Length    %%     "
5495*aa1b14e7SSheshadri Vasudevan 	"Part ID (Type)\n");
5496*aa1b14e7SSheshadri Vasudevan 	printf("=====   ========   ========   =======   ==="
5497*aa1b14e7SSheshadri Vasudevan 	"   ==============\n");
5498*aa1b14e7SSheshadri Vasudevan 	for (temp = fdisk_get_ld_head(epp), pno = 5; temp != NULL;
5499*aa1b14e7SSheshadri Vasudevan 	    temp = temp->next, pno++) {
5500*aa1b14e7SSheshadri Vasudevan 		/* Print the logical drive details */
5501*aa1b14e7SSheshadri Vasudevan 		fpart = &temp->parts[0];
5502*aa1b14e7SSheshadri Vasudevan 		sysid = fpart->systid;
5503*aa1b14e7SSheshadri Vasudevan 		id_to_name(sysid, namebuff);
5504*aa1b14e7SSheshadri Vasudevan 		startcyl = temp->begcyl;
5505*aa1b14e7SSheshadri Vasudevan 		endcyl = temp->endcyl;
5506*aa1b14e7SSheshadri Vasudevan 		if (startcyl == endcyl) {
5507*aa1b14e7SSheshadri Vasudevan 			length = 1;
5508*aa1b14e7SSheshadri Vasudevan 		} else {
5509*aa1b14e7SSheshadri Vasudevan 			length = endcyl - startcyl + 1;
5510*aa1b14e7SSheshadri Vasudevan 		}
5511*aa1b14e7SSheshadri Vasudevan 		percent = length * 100 / numcyl;
5512*aa1b14e7SSheshadri Vasudevan 		if ((remainder = (length * 100 % numcyl)) != 0) {
5513*aa1b14e7SSheshadri Vasudevan 			if ((remainder * 100 / numcyl) > 50) {
5514*aa1b14e7SSheshadri Vasudevan 				/* round up */
5515*aa1b14e7SSheshadri Vasudevan 				percent++;
5516*aa1b14e7SSheshadri Vasudevan 			}
5517*aa1b14e7SSheshadri Vasudevan 			/* Else leave the percent as is since it's already */
5518*aa1b14e7SSheshadri Vasudevan 			/* rounded down */
5519*aa1b14e7SSheshadri Vasudevan 		}
5520*aa1b14e7SSheshadri Vasudevan 		if (percent > 100) {
5521*aa1b14e7SSheshadri Vasudevan 			percent = 100;
5522*aa1b14e7SSheshadri Vasudevan 		}
5523*aa1b14e7SSheshadri Vasudevan 		printf("%-5d   %-8u   %-8u   %-7u   %-3d   %-3d (%-.28s)\n",
5524*aa1b14e7SSheshadri Vasudevan 		    pno, startcyl, endcyl, length, percent, sysid, namebuff);
5525*aa1b14e7SSheshadri Vasudevan 	}
5526*aa1b14e7SSheshadri Vasudevan #ifdef DEBUG
5527*aa1b14e7SSheshadri Vasudevan 	ext_print_logdrive_layout_debug();
5528*aa1b14e7SSheshadri Vasudevan #endif
5529*aa1b14e7SSheshadri Vasudevan 	printf("\n");
5530*aa1b14e7SSheshadri Vasudevan }
5531*aa1b14e7SSheshadri Vasudevan 
5532*aa1b14e7SSheshadri Vasudevan static void
5533*aa1b14e7SSheshadri Vasudevan ext_print_help_menu()
5534*aa1b14e7SSheshadri Vasudevan {
5535*aa1b14e7SSheshadri Vasudevan 	printf("\n");
5536*aa1b14e7SSheshadri Vasudevan 	printf("a	Add a logical drive\n");
5537*aa1b14e7SSheshadri Vasudevan 	printf("d	Delete a logical drive\n");
5538*aa1b14e7SSheshadri Vasudevan 	printf("h	Print this help menu\n");
5539*aa1b14e7SSheshadri Vasudevan 	printf("i	Change the id of the logical drive\n");
5540*aa1b14e7SSheshadri Vasudevan 	printf("p	Print the logical drive layout\n");
5541*aa1b14e7SSheshadri Vasudevan 	printf("r	Return to the main fdisk menu\n");
5542*aa1b14e7SSheshadri Vasudevan 	printf("        (To commit or cancel the changes)\n");
5543*aa1b14e7SSheshadri Vasudevan 	printf("\n");
5544*aa1b14e7SSheshadri Vasudevan }
5545*aa1b14e7SSheshadri Vasudevan 
5546*aa1b14e7SSheshadri Vasudevan static void
5547*aa1b14e7SSheshadri Vasudevan ext_part_menu()
5548*aa1b14e7SSheshadri Vasudevan {
5549*aa1b14e7SSheshadri Vasudevan 	char buf[80];
5550*aa1b14e7SSheshadri Vasudevan 	uchar_t *bbsigp;
5551*aa1b14e7SSheshadri Vasudevan 	static int bbsig_disp_flag = 1;
5552*aa1b14e7SSheshadri Vasudevan 
5553*aa1b14e7SSheshadri Vasudevan 	int i;
5554*aa1b14e7SSheshadri Vasudevan 
5555*aa1b14e7SSheshadri Vasudevan 	printf(CLR_SCR);
5556*aa1b14e7SSheshadri Vasudevan 
5557*aa1b14e7SSheshadri Vasudevan 	if (fdisk_corrupt_logical_drives(epp)) {
5558*aa1b14e7SSheshadri Vasudevan 		printf("One or more logical drives seem to be corrupt.\n");
5559*aa1b14e7SSheshadri Vasudevan 		printf("Displaying only sane logical drives.\n");
5560*aa1b14e7SSheshadri Vasudevan 	}
5561*aa1b14e7SSheshadri Vasudevan 
5562*aa1b14e7SSheshadri Vasudevan 	if (bbsig_disp_flag && fdisk_invalid_bb_sig(epp, &bbsigp)) {
5563*aa1b14e7SSheshadri Vasudevan 		printf("The following logical drives have a wrong boot block"
5564*aa1b14e7SSheshadri Vasudevan 		    " signature :\n\n");
5565*aa1b14e7SSheshadri Vasudevan 		for (i = 0; bbsigp[i]; i++) {
5566*aa1b14e7SSheshadri Vasudevan 			printf("%d ", bbsigp[i]);
5567*aa1b14e7SSheshadri Vasudevan 		}
5568*aa1b14e7SSheshadri Vasudevan 		printf("\n\n");
5569*aa1b14e7SSheshadri Vasudevan 		printf("They will be corrected when you choose to commit\n");
5570*aa1b14e7SSheshadri Vasudevan 		bbsig_disp_flag = 0;
5571*aa1b14e7SSheshadri Vasudevan 	}
5572*aa1b14e7SSheshadri Vasudevan 
5573*aa1b14e7SSheshadri Vasudevan 	printf("Extended partition menu\n");
5574*aa1b14e7SSheshadri Vasudevan 
5575*aa1b14e7SSheshadri Vasudevan 	for (;;) {
5576*aa1b14e7SSheshadri Vasudevan 		printf("\nEnter Command (Type h for help) : ");
5577*aa1b14e7SSheshadri Vasudevan 		if ((ext_read_options(buf)) < 0) {
5578*aa1b14e7SSheshadri Vasudevan 			printf("\nCommand Options : \n");
5579*aa1b14e7SSheshadri Vasudevan 			ext_print_help_menu();
5580*aa1b14e7SSheshadri Vasudevan 			continue;
5581*aa1b14e7SSheshadri Vasudevan 		}
5582*aa1b14e7SSheshadri Vasudevan 		switch (buf[0]) {
5583*aa1b14e7SSheshadri Vasudevan 			case 'a':
5584*aa1b14e7SSheshadri Vasudevan 				add_logical_drive();
5585*aa1b14e7SSheshadri Vasudevan 				break;
5586*aa1b14e7SSheshadri Vasudevan 			case 'd':
5587*aa1b14e7SSheshadri Vasudevan 				delete_logical_drive();
5588*aa1b14e7SSheshadri Vasudevan 				break;
5589*aa1b14e7SSheshadri Vasudevan 			case 'h':
5590*aa1b14e7SSheshadri Vasudevan 				ext_print_help_menu();
5591*aa1b14e7SSheshadri Vasudevan 				break;
5592*aa1b14e7SSheshadri Vasudevan 			case 'i':
5593*aa1b14e7SSheshadri Vasudevan 				ext_change_logical_drive_id();
5594*aa1b14e7SSheshadri Vasudevan 				break;
5595*aa1b14e7SSheshadri Vasudevan 			case 'p':
5596*aa1b14e7SSheshadri Vasudevan 				ext_print_logical_drive_layout();
5597*aa1b14e7SSheshadri Vasudevan 				break;
5598*aa1b14e7SSheshadri Vasudevan 			case 'r':
5599*aa1b14e7SSheshadri Vasudevan 				printf(CLR_SCR);
5600*aa1b14e7SSheshadri Vasudevan 				return;
5601*aa1b14e7SSheshadri Vasudevan 			default : /* NOTREACHED */
5602*aa1b14e7SSheshadri Vasudevan 				break;
5603*aa1b14e7SSheshadri Vasudevan 		}
5604*aa1b14e7SSheshadri Vasudevan 	}
5605*aa1b14e7SSheshadri Vasudevan }
5606*aa1b14e7SSheshadri Vasudevan #endif
5607*aa1b14e7SSheshadri Vasudevan 
5608*aa1b14e7SSheshadri Vasudevan #ifdef i386
5609*aa1b14e7SSheshadri Vasudevan 
5610*aa1b14e7SSheshadri Vasudevan static int
5611*aa1b14e7SSheshadri Vasudevan is_linux_swap(uint32_t part_start, off_t *lsm_offset)
5612*aa1b14e7SSheshadri Vasudevan {
5613*aa1b14e7SSheshadri Vasudevan 	int		i;
5614*aa1b14e7SSheshadri Vasudevan 	int		rval = -1;
5615*aa1b14e7SSheshadri Vasudevan 	off_t		seek_offset;
5616*aa1b14e7SSheshadri Vasudevan 	uint32_t	linux_pg_size;
5617*aa1b14e7SSheshadri Vasudevan 	char		*buf, *linux_swap_magic;
5618*aa1b14e7SSheshadri Vasudevan 	/*
5619*aa1b14e7SSheshadri Vasudevan 	 * Known linux kernel page sizes
5620*aa1b14e7SSheshadri Vasudevan 	 * The linux swap magic is found as the last 10 bytes of a disk chunk
5621*aa1b14e7SSheshadri Vasudevan 	 * at the beginning of the linux swap partition whose size is that of
5622*aa1b14e7SSheshadri Vasudevan 	 * kernel page size.
5623*aa1b14e7SSheshadri Vasudevan 	 */
5624*aa1b14e7SSheshadri Vasudevan 	uint32_t	linux_pg_size_arr[] = {4096, };
5625*aa1b14e7SSheshadri Vasudevan 
5626*aa1b14e7SSheshadri Vasudevan 	if ((buf = calloc(1, sectsiz)) == NULL) {
5627*aa1b14e7SSheshadri Vasudevan 		return (ENOMEM);
5628*aa1b14e7SSheshadri Vasudevan 	}
5629*aa1b14e7SSheshadri Vasudevan 
5630*aa1b14e7SSheshadri Vasudevan 	linux_swap_magic = buf + sectsiz - LINUX_SWAP_MAGIC_LENGTH;
5631*aa1b14e7SSheshadri Vasudevan 
5632*aa1b14e7SSheshadri Vasudevan 	for (i = 0; i < sizeof (linux_pg_size_arr)/sizeof (uint32_t); i++) {
5633*aa1b14e7SSheshadri Vasudevan 		linux_pg_size = linux_pg_size_arr[i];
5634*aa1b14e7SSheshadri Vasudevan 		seek_offset = linux_pg_size/sectsiz - 1;
5635*aa1b14e7SSheshadri Vasudevan 		seek_offset += part_start;
5636*aa1b14e7SSheshadri Vasudevan 		seek_offset *= sectsiz;
5637*aa1b14e7SSheshadri Vasudevan 
5638*aa1b14e7SSheshadri Vasudevan 		if ((rval = lseek(Dev, seek_offset, SEEK_SET)) < 0) {
5639*aa1b14e7SSheshadri Vasudevan 			break;
5640*aa1b14e7SSheshadri Vasudevan 		}
5641*aa1b14e7SSheshadri Vasudevan 
5642*aa1b14e7SSheshadri Vasudevan 		if ((rval = read(Dev, buf, sectsiz)) < sectsiz) {
5643*aa1b14e7SSheshadri Vasudevan 			rval = EIO;
5644*aa1b14e7SSheshadri Vasudevan 			break;
5645*aa1b14e7SSheshadri Vasudevan 		}
5646*aa1b14e7SSheshadri Vasudevan 
5647*aa1b14e7SSheshadri Vasudevan 		if ((strncmp(linux_swap_magic, "SWAP-SPACE",
5648*aa1b14e7SSheshadri Vasudevan 		    LINUX_SWAP_MAGIC_LENGTH) == 0) ||
5649*aa1b14e7SSheshadri Vasudevan 		    (strncmp(linux_swap_magic, "SWAPSPACE2",
5650*aa1b14e7SSheshadri Vasudevan 		    LINUX_SWAP_MAGIC_LENGTH) == 0)) {
5651*aa1b14e7SSheshadri Vasudevan 			/* Found a linux swap */
5652*aa1b14e7SSheshadri Vasudevan 			rval = 0;
5653*aa1b14e7SSheshadri Vasudevan 			*lsm_offset = seek_offset;
5654*aa1b14e7SSheshadri Vasudevan 			break;
5655*aa1b14e7SSheshadri Vasudevan 		}
5656*aa1b14e7SSheshadri Vasudevan 	}
5657*aa1b14e7SSheshadri Vasudevan 
5658*aa1b14e7SSheshadri Vasudevan 	free(buf);
5659*aa1b14e7SSheshadri Vasudevan 	return (rval);
5660*aa1b14e7SSheshadri Vasudevan }
5661*aa1b14e7SSheshadri Vasudevan 
5662*aa1b14e7SSheshadri Vasudevan #endif
5663