Home | History | Annotate | Download | only in fdisk
      1      0     stevel /*
      2      0     stevel  * CDDL HEADER START
      3      0     stevel  *
      4      0     stevel  * The contents of this file are subject to the terms of the
      5   5169      lclee  * Common Development and Distribution License (the "License").
      6   5169      lclee  * You may not use this file except in compliance with the License.
      7      0     stevel  *
      8      0     stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0     stevel  * or http://www.opensolaris.org/os/licensing.
     10      0     stevel  * See the License for the specific language governing permissions
     11      0     stevel  * and limitations under the License.
     12      0     stevel  *
     13      0     stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0     stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0     stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0     stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0     stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0     stevel  *
     19      0     stevel  * CDDL HEADER END
     20      0     stevel  */
     21   5169      lclee 
     22      0     stevel /*
     23   8904      Barry  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24      0     stevel  * Use is subject to license terms.
     25      0     stevel  */
     26      0     stevel 
     27      0     stevel /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
     28      0     stevel /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
     29      0     stevel /*	  All Rights Reserved	*/
     30      0     stevel 
     31      0     stevel /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
     32      0     stevel /*	  All Rights Reserved	*/
     33      0     stevel 
     34      0     stevel /*
     35      0     stevel  * PROGRAM: fdisk(1M)
     36      0     stevel  * This program reads the partition table on the specified device and
     37      0     stevel  * also reads the drive parameters. The user can perform various
     38      0     stevel  * operations from a supplied menu or from the command line. Diagnostic
     39      0     stevel  * options are also available.
     40      0     stevel  */
     41      0     stevel #include <stdio.h>
     42      0     stevel #include <stdlib.h>
     43      0     stevel #include <string.h>
     44      0     stevel #include <unistd.h>
     45      0     stevel #include <errno.h>
     46      0     stevel #include <fcntl.h>
     47      0     stevel #include <ctype.h>
     48      0     stevel #include <sys/stat.h>
     49      0     stevel #include <sys/types.h>
     50   7563     Prasad #include <limits.h>
     51      0     stevel #include <sys/param.h>
     52      0     stevel #include <sys/systeminfo.h>
     53      0     stevel #include <sys/efi_partition.h>
     54      0     stevel #include <sys/byteorder.h>
     55      0     stevel #include <sys/systeminfo.h>
     56      0     stevel 
     57      0     stevel #include <sys/dktp/fdisk.h>
     58      0     stevel #include <sys/dkio.h>
     59      0     stevel #include <sys/vtoc.h>
     60  10021  Sheshadri #ifdef i386
     61  10021  Sheshadri #include <sys/tty.h>
     62  10021  Sheshadri #include <libfdisk.h>
     63  10021  Sheshadri #endif
     64      0     stevel 
     65      0     stevel #define	CLR_SCR "[1;1H[0J"
     66      0     stevel #define	CLR_LIN "[0K"
     67      0     stevel #define	HOME "[1;1H[0K[2;1H[0K[3;1H[0K[4;1H[0K[5;1H[0K" \
     68      0     stevel 	"[6;1H[0K[7;1H[0K[8;1H[0K[9;1H[0K[10;1H[0K[1;1H"
     69      0     stevel #define	Q_LINE "[22;1H[0K[21;1H[0K[20;1H[0K"
     70  10021  Sheshadri 
     71  10021  Sheshadri #ifdef i386
     72  10021  Sheshadri #define	W_LINE "[11;1H[0K"
     73  10021  Sheshadri #else
     74      0     stevel #define	W_LINE "[12;1H[0K[11;1H[0K"
     75  10021  Sheshadri #endif
     76  10021  Sheshadri 
     77      0     stevel #define	E_LINE "[24;1H[0K[23;1H[0K"
     78  10021  Sheshadri 
     79  10021  Sheshadri #ifdef i386
     80  10021  Sheshadri #define	M_LINE "[12;1H[0K[13;1H[0K[14;1H[0K[15;1H[0K" \
     81  10021  Sheshadri 	"[16;1H[0K[17;1H[0K[18;1H[0K[19;1H[0K[12;1H"
     82  10021  Sheshadri #else
     83      0     stevel #define	M_LINE "[13;1H[0K[14;1H[0K[15;1H[0K[16;1H[0K[17;1H" \
     84      0     stevel 	"[0K[18;1H[0K[19;1H[0K[13;1H"
     85  10021  Sheshadri #endif
     86  10021  Sheshadri 
     87      0     stevel #define	T_LINE "[1;1H[0K"
     88      0     stevel 
     89      0     stevel #define	DEFAULT_PATH	"/dev/rdsk/"
     90   8333   Suhasini 
     91   8333   Suhasini /* XXX - should be in fdisk.h, used by sd as well */
     92   8333   Suhasini 
     93   8333   Suhasini /*
     94   8333   Suhasini  * the MAX values are the maximum usable values for BIOS chs values
     95   8333   Suhasini  * The MAX_CYL value of 1022 is the maximum usable value
     96   8333   Suhasini  *   the value of 1023 is a fence value,
     97   8333   Suhasini  *   indicating no CHS geometry exists for the corresponding LBA value.
     98   8333   Suhasini  * HEAD range [ 0 .. MAX_HEAD ], so number of heads is (MAX_HEAD + 1)
     99   8333   Suhasini  * SECT range [ 1 .. MAX_SECT ], so number of sectors is (MAX_SECT)
    100   8333   Suhasini  */
    101   8333   Suhasini #define	MAX_SECT	(63)
    102   8333   Suhasini #define	MAX_CYL		(1022)
    103   8333   Suhasini #define	MAX_HEAD	(254)
    104   7563     Prasad 
    105   7563     Prasad #define	DK_MAX_2TB	UINT32_MAX	/* Max # of sectors in 2TB */
    106      0     stevel 
    107      0     stevel /* for clear_vtoc() */
    108      0     stevel #define	OLD		0
    109      0     stevel #define	NEW		1
    110      0     stevel 
    111      0     stevel /* readvtoc/writevtoc return codes */
    112      0     stevel #define	VTOC_OK		0	/* Good VTOC */
    113      0     stevel #define	VTOC_INVAL	1	/* invalid VTOC */
    114      0     stevel #define	VTOC_NOTSUP	2	/* operation not supported - EFI label */
    115      0     stevel #define	VTOC_RWERR	3	/* couldn't read or write VTOC */
    116      0     stevel 
    117   8333   Suhasini /*
    118   8333   Suhasini  * Support for fdisk(1M) on the SPARC platform
    119   8333   Suhasini  *	In order to convert little endian values to big endian for SPARC,
    120   8333   Suhasini  *	byte/short and long values must be swapped.
    121   8333   Suhasini  *	These swapping macros will be used to access information in the
    122   8333   Suhasini  *	mboot and ipart structures.
    123   8333   Suhasini  */
    124   8333   Suhasini 
    125   8333   Suhasini #ifdef sparc
    126   8333   Suhasini #define	les(val)	((((val)&0xFF)<<8)|(((val)>>8)&0xFF))
    127   8333   Suhasini #define	lel(val)	(((unsigned)(les((val)&0x0000FFFF))<<16) | \
    128   8333   Suhasini 			    (les((unsigned)((val)&0xffff0000)>>16)))
    129   8333   Suhasini #else
    130   8333   Suhasini #define	les(val)	(val)
    131   8333   Suhasini #define	lel(val)	(val)
    132   8333   Suhasini #endif
    133   8333   Suhasini 
    134      0     stevel #if defined(_SUNOS_VTOC_16)
    135   6549   bharding #define	VTOC_OFFSET	1
    136      0     stevel #elif defined(_SUNOS_VTOC_8)
    137      0     stevel #define	VTOC_OFFSET	0
    138      0     stevel #else
    139      0     stevel #error No VTOC format defined.
    140  10021  Sheshadri #endif
    141  10021  Sheshadri 
    142  10021  Sheshadri #ifdef i386
    143  10021  Sheshadri #define	FDISK_KB	(1024)
    144  10021  Sheshadri #define	FDISK_MB	(FDISK_KB * 1024)
    145  10021  Sheshadri #define	FDISK_GB	(FDISK_MB * 1024)
    146  10021  Sheshadri #define	TRUE	1
    147  10021  Sheshadri 
    148  10021  Sheshadri #define	FDISK_MAX_VALID_PART_ID	255
    149  10021  Sheshadri #define	FDISK_MAX_VALID_PART_NUM_DIGITS	2
    150  10021  Sheshadri #define	FDISK_MAX_VALID_PART_ID_DIGITS	3
    151  10021  Sheshadri 
    152  10021  Sheshadri /* Maximum number of digits for a valid partition size */
    153  10021  Sheshadri #define	FDISK_MAX_VALID_CYL_NUM_DIGITS	10
    154  10021  Sheshadri 
    155  10021  Sheshadri /* Minimum partition size in cylinders */
    156  10021  Sheshadri #define	FDISK_MIN_PART_SIZE	1
    157      0     stevel #endif
    158      0     stevel 
    159    251      lclee static char Usage[] = "Usage: fdisk\n"
    160      0     stevel "[ -A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n"
    161      0     stevel "[ -b masterboot ]\n"
    162      0     stevel "[ -D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n"
    163      0     stevel "[ -F fdisk_file ] [ -h ] [ -o offset ] [ -P fill_patt ] [ -s size ]\n"
    164      0     stevel "[ -S geom_file ] [ [ -v ] -W { creat_fdisk_file | - } ]\n"
    165      0     stevel "[ -w | r | d | n | I | B | E | g | G | R | t | T ] rdevice";
    166      0     stevel 
    167    251      lclee static char Usage1[] = "    Partition options:\n"
    168      0     stevel "	-A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n"
    169      0     stevel "		Create a partition with specific attributes:\n"
    170      0     stevel "		id      = system id number (fdisk.h) for the partition type\n"
    171      0     stevel "		act     = active partition flag (0 is off and 128 is on)\n"
    172      0     stevel "		bhead   = beginning head for start of partition\n"
    173      0     stevel "		bsect   = beginning sector for start of partition\n"
    174      0     stevel "		bcyl    = beginning cylinder for start of partition\n"
    175      0     stevel "		ehead   = ending head for end of partition\n"
    176      0     stevel "		esect   = ending sector for end of partition\n"
    177      0     stevel "		ecyl    = ending cylinder for end of partition\n"
    178      0     stevel "		rsect   = sector number from start of disk for\n"
    179      0     stevel "			  start of partition\n"
    180      0     stevel "		numsect = partition size in sectors\n"
    181      0     stevel "	-b master_boot\n"
    182      0     stevel "		Use master_boot as the master boot file.\n"
    183      0     stevel "	-B	Create one Solaris partition that uses the entire disk.\n"
    184      0     stevel "	-E	Create one EFI partition that uses the entire disk.\n"
    185      0     stevel "	-D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n"
    186      0     stevel "		Delete a partition. See attribute definitions for -A.\n"
    187      0     stevel "	-F fdisk_file\n"
    188      0     stevel "		Use fdisk_file to initialize on-line fdisk table.\n"
    189      0     stevel "	-I	Forego device checks. Generate a file image of what would go\n"
    190      0     stevel "		on a disk using the geometry specified with the -S option.\n"
    191      0     stevel "	-n	Do not run in interactive mode.\n"
    192      0     stevel "	-R	Open the disk device as read-only.\n"
    193      0     stevel "	-t	Check and adjust VTOC to be consistent with fdisk table.\n"
    194      0     stevel "		VTOC slices exceeding the partition size will be truncated.\n"
    195      0     stevel "	-T	Check and adjust VTOC to be consistent with fdisk table.\n"
    196      0     stevel "		VTOC slices exceeding the partition size will be removed.\n"
    197      0     stevel "	-W fdisk_file\n"
    198      0     stevel "		Write on-disk table to fdisk_file.\n"
    199      0     stevel "	-W -	Write on-disk table to standard output.\n"
    200      0     stevel "	-v	Display virtual geometry. Must be used with the -W option.\n"
    201      0     stevel "    Diagnostic options:\n"
    202      0     stevel "	-d	Activate debug information about progress.\n"
    203      0     stevel "	-g	Write label geometry to standard output:\n"
    204      0     stevel "		PCYL		number of physical cylinders\n"
    205      0     stevel "		NCYL		number of usable cylinders\n"
    206      0     stevel "		ACYL		number of alternate cylinders\n"
    207      0     stevel "		BCYL		cylinder offset\n"
    208      0     stevel "		NHEADS		number of heads\n"
    209      0     stevel "		NSECTORS	number of sectors per track\n"
    210      0     stevel "		SECTSIZ		size of a sector in bytes\n"
    211      0     stevel "	-G	Write physical geometry to standard output (see -g).\n"
    212      0     stevel "	-h	Issue this verbose help message.\n"
    213      0     stevel "	-o offset\n"
    214      0     stevel "		Block offset from start of disk (default 0). Ignored if\n"
    215      0     stevel "		-P # specified.\n"
    216      0     stevel "	-P fill_patt\n"
    217      0     stevel "		Fill disk with pattern fill_patt. fill_patt can be decimal or\n"
    218      0     stevel "		hexadecimal and is used as number for constant long word\n"
    219      0     stevel "		pattern. If fill_patt is \"#\" then pattern of block #\n"
    220      0     stevel "		for each block. Pattern is put in each block as long words\n"
    221      0     stevel "		and fills each block (see -o and -s).\n"
    222      0     stevel "	-r	Read from a disk to stdout (see -o and -s).\n"
    223      0     stevel "	-s size	Number of blocks on which to perform operation (see -o).\n"
    224      0     stevel "	-S geom_file\n"
    225      0     stevel "		Use geom_file to set the label geometry (see -g).\n"
    226      0     stevel "	-w	Write to a disk from stdin (see -o and -s).";
    227      0     stevel 
    228    251      lclee static char Ostr[] = "Other OS";
    229    251      lclee static char Dstr[] = "DOS12";
    230    251      lclee static char D16str[] = "DOS16";
    231    251      lclee static char DDstr[] = "DOS-DATA";
    232    251      lclee static char EDstr[] = "EXT-DOS";
    233    251      lclee static char DBstr[] = "DOS-BIG";
    234    251      lclee static char PCstr[] = "PCIX";
    235    251      lclee static char Ustr[] = "UNIX System";
    236    251      lclee static char SUstr[] = "Solaris";
    237    251      lclee static char SU2str[] = "Solaris2";
    238    251      lclee static char X86str[] = "x86 Boot";
    239    251      lclee static char DIAGstr[] = "Diagnostic";
    240    251      lclee static char IFSstr[] = "IFS: NTFS";
    241    251      lclee static char AIXstr[] = "AIX Boot";
    242    251      lclee static char AIXDstr[] = "AIX Data";
    243    251      lclee static char OS2str[] = "OS/2 Boot";
    244    251      lclee static char WINstr[] = "Win95 FAT32";
    245    251      lclee static char EWINstr[] = "Ext Win95";
    246    251      lclee static char FAT95str[] = "FAT16 LBA";
    247    251      lclee static char EXTLstr[] = "EXT LBA";
    248    251      lclee static char LINUXstr[] = "Linux";
    249    251      lclee static char CPMstr[] = "CP/M";
    250  10021  Sheshadri static char NOV2str[] = "Netware 286";
    251    251      lclee static char NOVstr[] = "Netware 3.x+";
    252    251      lclee static char QNXstr[] = "QNX 4.x";
    253    251      lclee static char QNX2str[] = "QNX part 2";
    254    251      lclee static char QNX3str[] = "QNX part 3";
    255    251      lclee static char LINNATstr[] = "Linux native";
    256  10682  Sheshadri static char LINSWAPstr[] = "Linux swap";
    257    251      lclee static char NTFSVOL1str[] = "NT volset 1";
    258    251      lclee static char NTFSVOL2str[] = "NT volset 2";
    259    251      lclee static char BSDstr[] = "BSD OS";
    260    251      lclee static char NEXTSTEPstr[] = "NeXTSTEP";
    261    251      lclee static char BSDIFSstr[] = "BSDI FS";
    262    251      lclee static char BSDISWAPstr[] = "BSDI swap";
    263    251      lclee static char Actvstr[] = "Active";
    264    251      lclee static char EFIstr[] = "EFI";
    265    251      lclee static char NAstr[] = "      ";
    266      0     stevel 
    267      0     stevel /* All the user options and flags */
    268    251      lclee static char *Dfltdev;			/* name of fixed disk drive */
    269      0     stevel 
    270      0     stevel /* Diagnostic options */
    271    251      lclee static int	io_wrt = 0;		/* write stdin to disk (-w) */
    272    251      lclee static int	io_rd = 0;		/* read disk and write stdout (-r) */
    273    251      lclee static char	*io_fatt;		/* user supplied pattern (-P pattern) */
    274    251      lclee static int	io_patt = 0;		/* write pattern to disk (-P pattern) */
    275    251      lclee static int	io_lgeom = 0;		/* get label geometry (-g) */
    276    251      lclee static int	io_pgeom = 0;		/* get drive physical geometry (-G) */
    277    251      lclee static char	*io_sgeom = 0;		/* set label geometry (-S geom_file) */
    278    251      lclee static int	io_readonly = 0;	/* do not write to disk (-R) */
    279      0     stevel 
    280      0     stevel /* The -o offset and -s size options specify the area of the disk on */
    281      0     stevel /* which to perform the particular operation; i.e., -P, -r, or -w. */
    282   6549   bharding static off_t	io_offset = 0;		/* offset sector (-o offset) */
    283   6549   bharding static off_t	io_size = 0;		/* size in sectors (-s size) */
    284      0     stevel 
    285      0     stevel /* Partition table flags */
    286    251      lclee static int	v_flag = 0;		/* virtual geometry-HBA flag (-v) */
    287    251      lclee static int 	stdo_flag = 0;		/* stdout flag (-W -) */
    288    251      lclee static int	io_fdisk = 0;		/* do fdisk operation */
    289    251      lclee static int	io_ifdisk = 0;		/* interactive partition */
    290    251      lclee static int	io_nifdisk = 0;		/* non-interactive partition (-n) */
    291      0     stevel 
    292    251      lclee static int	io_adjt = 0;		/* check/adjust VTOC (truncate (-t)) */
    293    251      lclee static int	io_ADJT = 0;		/* check/adjust VTOC (delete (-T)) */
    294    251      lclee static char	*io_ffdisk = 0;		/* input fdisk file name (-F file) */
    295    251      lclee static char	*io_Wfdisk = 0;		/* output fdisk file name (-W file) */
    296    251      lclee static char	*io_Afdisk = 0;		/* add entry to partition table (-A) */
    297    251      lclee static char	*io_Dfdisk = 0;		/* delete entry from part. table (-D) */
    298      0     stevel 
    299    251      lclee static char	*io_mboot = 0;		/* master boot record (-b boot_file) */
    300      0     stevel 
    301    251      lclee static struct mboot BootCod;		/* buffer for master boot record */
    302      0     stevel 
    303    251      lclee static int	io_wholedisk = 0;	/* use whole disk for Solaris (-B) */
    304    251      lclee static int	io_EFIdisk = 0;		/* use whole disk for EFI (-E) */
    305    251      lclee static int	io_debug = 0;		/* activate verbose mode (-d) */
    306    251      lclee static int	io_image = 0;		/* create image using geometry (-I) */
    307      0     stevel 
    308    251      lclee static struct mboot *Bootblk;		/* pointer to cut/paste sector zero */
    309    251      lclee static char	*Bootsect;		/* pointer to sector zero buffer */
    310    251      lclee static char	*Nullsect;
    311   7563     Prasad static struct extvtoc	disk_vtoc;	/* verify VTOC table */
    312    251      lclee static int	vt_inval = 0;
    313    251      lclee static int	no_virtgeom_ioctl = 0;	/* ioctl for virtual geometry failed */
    314    251      lclee static int	no_physgeom_ioctl = 0;	/* ioctl for physical geometry failed */
    315      0     stevel 
    316    251      lclee static struct ipart	Table[FD_NUMPART];
    317    251      lclee static struct ipart	Old_Table[FD_NUMPART];
    318   8904      Barry static int		skip_verify[FD_NUMPART]; /* special case skip sz chk */
    319      0     stevel 
    320      0     stevel /* Disk geometry information */
    321   5169      lclee static struct dk_minfo	minfo;
    322    251      lclee static struct dk_geom	disk_geom;
    323   5169      lclee 
    324   7563     Prasad static int Dev;			/* fd for open device */
    325   7563     Prasad 
    326   5169      lclee static diskaddr_t	dev_capacity;	/* number of blocks on device */
    327   7563     Prasad static diskaddr_t	chs_capacity;	/* Numcyl_usable * heads * sectors */
    328      0     stevel 
    329   7563     Prasad static int		Numcyl_usable;	/* Number of usable cylinders */
    330   7563     Prasad 					/*  used to limit fdisk to 2TB */
    331   7563     Prasad 
    332      0     stevel /* Physical geometry for the drive */
    333    251      lclee static int	Numcyl;			/* number of cylinders */
    334    251      lclee static int	heads;			/* number of heads */
    335    251      lclee static int	sectors;		/* number of sectors per track */
    336    251      lclee static int	acyl;			/* number of alternate sectors */
    337      0     stevel 
    338      0     stevel /* HBA (virtual) geometry for the drive */
    339    251      lclee static int	hba_Numcyl;		/* number of cylinders */
    340    251      lclee static int	hba_heads;		/* number of heads */
    341    251      lclee static int	hba_sectors;		/* number of sectors per track */
    342      0     stevel 
    343    251      lclee static int	sectsiz;		/* sector size */
    344      0     stevel 
    345      0     stevel /* Load functions for fdisk table modification */
    346      0     stevel #define	LOADFILE	0	/* load fdisk from file */
    347      0     stevel #define	LOADDEL		1	/* delete an fdisk entry */
    348      0     stevel #define	LOADADD		2	/* add an fdisk entry */
    349      0     stevel 
    350      0     stevel #define	CBUFLEN 80
    351    251      lclee static char s[CBUFLEN];
    352  10021  Sheshadri 
    353  10021  Sheshadri #ifdef i386
    354  10021  Sheshadri /*
    355  10021  Sheshadri  * Complete list of all the 255 partition types. Some are unknown types
    356  10021  Sheshadri  * and some entries are known to be unused.
    357  10021  Sheshadri  *
    358  10021  Sheshadri  * Courtesy of http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
    359  10021  Sheshadri  */
    360  10021  Sheshadri char *fdisk_part_types[] = {
    361  10021  Sheshadri 	"Empty",				/* 0 */
    362  10021  Sheshadri 	"FAT12",				/* 1 */
    363  10021  Sheshadri 	"XENIX /",				/* 2 */
    364  10021  Sheshadri 	"XENIX /usr",				/* 3 */
    365  10021  Sheshadri 	"FAT16 (Upto 32M)",			/* 4 */
    366  10021  Sheshadri 	"DOS Extended",				/* 5 */
    367  10021  Sheshadri 	"FAT16 (>32M, HUGEDOS)",		/* 6 */
    368  10021  Sheshadri 	"IFS: NTFS",				/* 7 */
    369  10021  Sheshadri 	"AIX Boot/QNX(qny)",			/* 8 */
    370  10021  Sheshadri 	"AIX Data/QNX(qnz)",			/* 9 */
    371  10021  Sheshadri 	"OS/2 Boot/Coherent swap",		/* 10 */
    372  10021  Sheshadri 	"WIN95 FAT32(Upto 2047GB)",		/* 11 */
    373  10021  Sheshadri 	"WIN95 FAT32(LBA)",			/* 12 */
    374  10021  Sheshadri 	"Unused",				/* 13 */
    375  10021  Sheshadri 	"WIN95 FAT16(LBA)",			/* 14 */
    376  10021  Sheshadri 	"WIN95 Extended(LBA)",			/* 15 */
    377  10021  Sheshadri 	"OPUS",					/* 16 */
    378  10021  Sheshadri 	"Hidden FAT12",				/* 17 */
    379  10021  Sheshadri 	"Diagnostic",				/* 18 */
    380  10021  Sheshadri 	"Unknown",				/* 19 */
    381  10021  Sheshadri 	"Hidden FAT16(Upto 32M)",		/* 20 */
    382  10021  Sheshadri 	"Unknown",				/* 21 */
    383  10021  Sheshadri 	"Hidden FAT16(>=32M)",			/* 22 */
    384  10021  Sheshadri 	"Hidden IFS: HPFS",			/* 23 */
    385  10021  Sheshadri 	"AST SmartSleep Partition",		/* 24 */
    386  10021  Sheshadri 	"Unused/Willowtech Photon",		/* 25 */
    387  10021  Sheshadri 	"Unknown",				/* 26 */
    388  10021  Sheshadri 	"Hidden FAT32",				/* 27 */
    389  10021  Sheshadri 	"Hidden FAT32(LBA)",			/* 28 */
    390  10021  Sheshadri 	"Unused",				/* 29 */
    391  10021  Sheshadri 	"Hidden FAT16(LBA)",			/* 30 */
    392  10021  Sheshadri 	"Unknown",				/* 31 */
    393  10021  Sheshadri 	"Unused/OSF1",				/* 32 */
    394  10021  Sheshadri 	"Reserved/FSo2(Oxygen FS)",		/* 33 */
    395  10021  Sheshadri 	"Unused/(Oxygen EXT)",			/* 34 */
    396  10021  Sheshadri 	"Reserved",				/* 35 */
    397  10021  Sheshadri 	"NEC DOS 3.x",				/* 36 */
    398  10021  Sheshadri 	"Unknown",				/* 37 */
    399  10021  Sheshadri 	"Reserved",				/* 38 */
    400  10021  Sheshadri 	"Unknown",				/* 39 */
    401  10021  Sheshadri 	"Unknown",				/* 40 */
    402  10021  Sheshadri 	"Unknown",				/* 41 */
    403  10021  Sheshadri 	"AtheOS File System",			/* 42 */
    404  10021  Sheshadri 	"SyllableSecure",			/* 43 */
    405  10021  Sheshadri 	"Unknown",				/* 44 */
    406  10021  Sheshadri 	"Unknown",				/* 45 */
    407  10021  Sheshadri 	"Unknown",				/* 46 */
    408  10021  Sheshadri 	"Unknown",				/* 47 */
    409  10021  Sheshadri 	"Unknown",				/* 48 */
    410  10021  Sheshadri 	"Reserved",				/* 49 */
    411  10021  Sheshadri 	"NOS",					/* 50 */
    412  10021  Sheshadri 	"Reserved",				/* 51 */
    413  10021  Sheshadri 	"Reserved",				/* 52 */
    414  10021  Sheshadri 	"JFS on OS/2",				/* 53 */
    415  10021  Sheshadri 	"Reserved",				/* 54 */
    416  10021  Sheshadri 	"Unknown",				/* 55 */
    417  10021  Sheshadri 	"THEOS 3.2 2GB",			/* 56 */
    418  10021  Sheshadri 	"Plan9/THEOS 4",			/* 57 */
    419  10021  Sheshadri 	"THEOS 4 4GB",				/* 58 */
    420  10021  Sheshadri 	"THEOS 4 Extended",			/* 59 */
    421  10021  Sheshadri 	"PartitionMagic Recovery",		/* 60 */
    422  10021  Sheshadri 	"Hidden NetWare",			/* 61 */
    423  10021  Sheshadri 	"Unknown",				/* 62 */
    424  10021  Sheshadri 	"Unknown",				/* 63 */
    425  10021  Sheshadri 	"Venix 80286",				/* 64 */
    426  10021  Sheshadri 	"MINIX/PPC PReP Boot",			/* 65 */
    427  10021  Sheshadri 	"Win2K Dynamic Disk/SFS(DOS)",		/* 66 */
    428  10021  Sheshadri 	"Linux+DRDOS shared",			/* 67 */
    429  10021  Sheshadri 	"GoBack partition",			/* 68 */
    430  10021  Sheshadri 	"Boot-US boot manager",			/* 69 */
    431  10021  Sheshadri 	"EUMEL/Elan",				/* 70 */
    432  10021  Sheshadri 	"EUMEL/Elan",				/* 71 */
    433  10021  Sheshadri 	"EUMEL/Elan",				/* 72 */
    434  10021  Sheshadri 	"Unknown",				/* 73 */
    435  10021  Sheshadri 	"ALFS/THIN FS for DOS",			/* 74 */
    436  10021  Sheshadri 	"Unknown",				/* 75 */
    437  10021  Sheshadri 	"Oberon partition",			/* 76 */
    438  10021  Sheshadri 	"QNX 4,x",				/* 77 */
    439  10021  Sheshadri 	"QNX 4,x 2nd Part",			/* 78 */
    440  10021  Sheshadri 	"QNX 4,x 3rd Part",			/* 79 */
    441  10021  Sheshadri 	"OnTrack DM R/O, Lynx RTOS",		/* 80 */
    442  10021  Sheshadri 	"OnTrack DM R/W, Novell",		/* 81 */
    443  10021  Sheshadri 	"CP/M",					/* 82 */
    444  10021  Sheshadri 	"Disk Manager 6.0 Aux3",		/* 83 */
    445  10021  Sheshadri 	"Disk Manager 6.0 DDO",			/* 84 */
    446  10021  Sheshadri 	"EZ-Drive",				/* 85 */
    447  10021  Sheshadri 	"Golden Bow VFeature/AT&T MS-DOS",	/* 86 */
    448  10021  Sheshadri 	"DrivePro",				/* 87 */
    449  10021  Sheshadri 	"Unknown",				/* 88 */
    450  10021  Sheshadri 	"Unknown",				/* 89 */
    451  10021  Sheshadri 	"Unknown",				/* 90 */
    452  10021  Sheshadri 	"Unknown",				/* 91 */
    453  10021  Sheshadri 	"Priam EDisk",				/* 92 */
    454  10021  Sheshadri 	"Unknown",				/* 93 */
    455  10021  Sheshadri 	"Unknown",				/* 94 */
    456  10021  Sheshadri 	"Unknown",				/* 95 */
    457  10021  Sheshadri 	"Unknown",				/* 96 */
    458  10021  Sheshadri 	"SpeedStor",				/* 97 */
    459  10021  Sheshadri 	"Unknown",				/* 98 */
    460  10021  Sheshadri 	"Unix SysV, Mach, GNU Hurd",		/* 99 */
    461  10021  Sheshadri 	"PC-ARMOUR, Netware 286",		/* 100 */
    462  10021  Sheshadri 	"Netware 386",				/* 101 */
    463  10021  Sheshadri 	"Netware SMS",				/* 102 */
    464  10021  Sheshadri 	"Novell",				/* 103 */
    465  10021  Sheshadri 	"Novell",				/* 104 */
    466  10021  Sheshadri 	"Netware NSS",				/* 105 */
    467  10021  Sheshadri 	"Unknown",				/* 106 */
    468  10021  Sheshadri 	"Unknown",				/* 107 */
    469  10021  Sheshadri 	"Unknown",				/* 108 */
    470  10021  Sheshadri 	"Unknown",				/* 109 */
    471  10021  Sheshadri 	"Unknown",				/* 110 */
    472  10021  Sheshadri 	"Unknown",				/* 111 */
    473  10021  Sheshadri 	"DiskSecure Multi-Boot",		/* 112 */
    474  10021  Sheshadri 	"Reserved",				/* 113 */
    475  10021  Sheshadri 	"Unknown",				/* 114 */
    476  10021  Sheshadri 	"Reserved",				/* 115 */
    477  10021  Sheshadri 	"Scramdisk partition",			/* 116 */
    478  10021  Sheshadri 	"IBM PC/IX",				/* 117 */
    479  10021  Sheshadri 	"Reserved",				/* 118 */
    480  10021  Sheshadri 	"M2FS/M2CS,Netware VNDI",		/* 119 */
    481  10021  Sheshadri 	"XOSL FS",				/* 120 */
    482  10021  Sheshadri 	"Unknown",				/* 121 */
    483  10021  Sheshadri 	"Unknown",				/* 122 */
    484  10021  Sheshadri 	"Unknown",				/* 123 */
    485  10021  Sheshadri 	"Unknown",				/* 124 */
    486  10021  Sheshadri 	"Unknown",				/* 125 */
    487  10021  Sheshadri 	"Unused",				/* 126 */
    488  10021  Sheshadri 	"Unused",				/* 127 */
    489  10021  Sheshadri 	"MINIX until 1.4a",			/* 128 */
    490  10021  Sheshadri 	"MINIX since 1.4b, early Linux",	/* 129 */
    491  10021  Sheshadri 	"Solaris/Linux swap",			/* 130 */
    492  10021  Sheshadri 	"Linux native",				/* 131 */
    493  10021  Sheshadri 	"OS/2 hidden,Win Hibernation",		/* 132 */
    494  10021  Sheshadri 	"Linux extended",			/* 133 */
    495  10021  Sheshadri 	"Old Linux RAID,NT FAT16 RAID",		/* 134 */
    496  10021  Sheshadri 	"NTFS volume set",			/* 135 */
    497  10021  Sheshadri 	"Linux plaintext part table",		/* 136 */
    498  10021  Sheshadri 	"Unknown",				/* 137 */
    499  10021  Sheshadri 	"Linux Kernel Partition",		/* 138 */
    500  10021  Sheshadri 	"Fault Tolerant FAT32 volume",		/* 139 */
    501  10021  Sheshadri 	"Fault Tolerant FAT32 volume",		/* 140 */
    502  10021  Sheshadri 	"Free FDISK hidden PDOS FAT12",		/* 141 */
    503  10021  Sheshadri 	"Linux LVM partition",			/* 142 */
    504  10021  Sheshadri 	"Unknown",				/* 143 */
    505  10021  Sheshadri 	"Free FDISK hidden PDOS FAT16",		/* 144 */
    506  10021  Sheshadri 	"Free FDISK hidden DOS EXT",		/* 145 */
    507  10021  Sheshadri 	"Free FDISK hidden FAT16 Large",	/* 146 */
    508  10021  Sheshadri 	"Hidden Linux native, Amoeba",		/* 147 */
    509  10021  Sheshadri 	"Amoeba Bad Block Table",		/* 148 */
    510  10021  Sheshadri 	"MIT EXOPC Native",			/* 149 */
    511  10021  Sheshadri 	"Unknown",				/* 150 */
    512  10021  Sheshadri 	"Free FDISK hidden PDOS FAT32",		/* 151 */
    513  10021  Sheshadri 	"Free FDISK hidden FAT32 LBA",		/* 152 */
    514  10021  Sheshadri 	"DCE376 logical drive",			/* 153 */
    515  10021  Sheshadri 	"Free FDISK hidden FAT16 LBA",		/* 154 */
    516  10021  Sheshadri 	"Free FDISK hidden DOS EXT",		/* 155 */
    517  10021  Sheshadri 	"Unknown",				/* 156 */
    518  10021  Sheshadri 	"Unknown",				/* 157 */
    519  10021  Sheshadri 	"Unknown",				/* 158 */
    520  10021  Sheshadri 	"BSD/OS",				/* 159 */
    521  10021  Sheshadri 	"Laptop hibernation",			/* 160 */
    522  10021  Sheshadri 	"Laptop hibernate,HP SpeedStor",	/* 161 */
    523  10021  Sheshadri 	"Unknown",				/* 162 */
    524  10021  Sheshadri 	"HP SpeedStor",				/* 163 */
    525  10021  Sheshadri 	"HP SpeedStor",				/* 164 */
    526  10021  Sheshadri 	"BSD/386,386BSD,NetBSD,FreeBSD",	/* 165 */
    527  10021  Sheshadri 	"OpenBSD,HP SpeedStor",			/* 166 */
    528  10021  Sheshadri 	"NeXTStep",				/* 167 */
    529  10021  Sheshadri 	"Mac OS-X",				/* 168 */
    530  10021  Sheshadri 	"NetBSD",				/* 169 */
    531  10021  Sheshadri 	"Olivetti FAT12 1.44MB Service",	/* 170 */
    532  10021  Sheshadri 	"Mac OS-X Boot",			/* 171 */
    533  10021  Sheshadri 	"Unknown",				/* 172 */
    534  10021  Sheshadri 	"Unknown",				/* 173 */
    535  10021  Sheshadri 	"ShagOS filesystem",			/* 174 */
    536  10021  Sheshadri 	"ShagOS swap",				/* 175 */
    537  10021  Sheshadri 	"BootStar Dummy",			/* 176 */
    538  10021  Sheshadri 	"HP SpeedStor",				/* 177 */
    539  10021  Sheshadri 	"Unknown",				/* 178 */
    540  10021  Sheshadri 	"HP SpeedStor",				/* 179 */
    541  10021  Sheshadri 	"HP SpeedStor",				/* 180 */
    542  10021  Sheshadri 	"Unknown",				/* 181 */
    543  10021  Sheshadri 	"Corrupted FAT16 NT Mirror Set",	/* 182 */
    544  10021  Sheshadri 	"Corrupted NTFS NT Mirror Set",		/* 183 */
    545  10021  Sheshadri 	"Old BSDI BSD/386 swap",		/* 184 */
    546  10021  Sheshadri 	"Unknown",				/* 185 */
    547  10021  Sheshadri 	"Unknown",				/* 186 */
    548  10021  Sheshadri 	"Boot Wizard hidden",			/* 187 */
    549  10021  Sheshadri 	"Unknown",				/* 188 */
    550  10021  Sheshadri 	"Unknown",				/* 189 */
    551  10021  Sheshadri 	"Solaris x86 boot",			/* 190 */
    552  10021  Sheshadri 	"Solaris2",				/* 191 */
    553  10021  Sheshadri 	"REAL/32 or Novell DOS secured",	/* 192 */
    554  10021  Sheshadri 	"DRDOS/secured(FAT12)",			/* 193 */
    555  10021  Sheshadri 	"Hidden Linux",				/* 194 */
    556  10021  Sheshadri 	"Hidden Linux swap",			/* 195 */
    557  10021  Sheshadri 	"DRDOS/secured(FAT16,< 32M)",		/* 196 */
    558  10021  Sheshadri 	"DRDOS/secured(Extended)",		/* 197 */
    559  10021  Sheshadri 	"NT corrupted FAT16 volume",		/* 198 */
    560  10021  Sheshadri 	"NT corrupted NTFS volume",		/* 199 */
    561  10021  Sheshadri 	"DRDOS8.0+",				/* 200 */
    562  10021  Sheshadri 	"DRDOS8.0+",				/* 201 */
    563  10021  Sheshadri 	"DRDOS8.0+",				/* 202 */
    564  10021  Sheshadri 	"DRDOS7.04+ secured FAT32(CHS)",	/* 203 */
    565  10021  Sheshadri 	"DRDOS7.04+ secured FAT32(LBA)",	/* 204 */
    566  10021  Sheshadri 	"CTOS Memdump",				/* 205 */
    567  10021  Sheshadri 	"DRDOS7.04+ FAT16X(LBA)",		/* 206 */
    568  10021  Sheshadri 	"DRDOS7.04+ secure EXT DOS(LBA)",	/* 207 */
    569  10021  Sheshadri 	"REAL/32 secure big, MDOS",		/* 208 */
    570  10021  Sheshadri 	"Old MDOS secure FAT12",		/* 209 */
    571  10021  Sheshadri 	"Unknown",				/* 210 */
    572  10021  Sheshadri 	"Unknown",				/* 211 */
    573  10021  Sheshadri 	"Old MDOS secure FAT16 <32M",		/* 212 */
    574  10021  Sheshadri 	"Old MDOS secure EXT",			/* 213 */
    575  10021  Sheshadri 	"Old MDOS secure FAT16 >=32M",		/* 214 */
    576  10021  Sheshadri 	"Unknown",				/* 215 */
    577  10021  Sheshadri 	"CP/M-86",				/* 216 */
    578  10021  Sheshadri 	"Unknown",				/* 217 */
    579  10021  Sheshadri 	"Non-FS Data",				/* 218 */
    580  10021  Sheshadri 	"CP/M,Concurrent DOS,CTOS",		/* 219 */
    581  10021  Sheshadri 	"Unknown",				/* 220 */
    582  10021  Sheshadri 	"Hidden CTOS memdump",			/* 221 */
    583  10021  Sheshadri 	"Dell PowerEdge utilities(FAT)",	/* 222 */
    584  10021  Sheshadri 	"DG/UX virtual disk manager",		/* 223 */
    585  10021  Sheshadri 	"ST AVFS(STMicroelectronics)",		/* 224 */
    586  10021  Sheshadri 	"SpeedStor 12-bit FAT EXT",		/* 225 */
    587  10021  Sheshadri 	"Unknown",				/* 226 */
    588  10021  Sheshadri 	"SpeedStor",				/* 227 */
    589  10021  Sheshadri 	"SpeedStor 16-bit FAT EXT",		/* 228 */
    590  10021  Sheshadri 	"Tandy MSDOS",				/* 229 */
    591  10021  Sheshadri 	"Storage Dimensions SpeedStor",		/* 230 */
    592  10021  Sheshadri 	"Unknown",				/* 231 */
    593  10021  Sheshadri 	"Unknown",				/* 232 */
    594  10021  Sheshadri 	"Unknown",				/* 233 */
    595  10021  Sheshadri 	"Unknown",				/* 234 */
    596  10021  Sheshadri 	"BeOS BFS",				/* 235 */
    597  10021  Sheshadri 	"SkyOS SkyFS",				/* 236 */
    598  10021  Sheshadri 	"Unused",				/* 237 */
    599  10021  Sheshadri 	"EFI Header Indicator",			/* 238 */
    600  10021  Sheshadri 	"EFI Filesystem",			/* 239 */
    601  10021  Sheshadri 	"Linux/PA-RISC boot loader",		/* 240 */
    602  10021  Sheshadri 	"SpeedStor",				/* 241 */
    603  10021  Sheshadri 	"DOS 3.3+ secondary",			/* 242 */
    604  10021  Sheshadri 	"SpeedStor Reserved",			/* 243 */
    605  10021  Sheshadri 	"SpeedStor Large",			/* 244 */
    606  10021  Sheshadri 	"Prologue multi-volume",		/* 245 */
    607  10021  Sheshadri 	"SpeedStor",				/* 246 */
    608  10021  Sheshadri 	"Unused",				/* 247 */
    609  10021  Sheshadri 	"Unknown",				/* 248 */
    610  10021  Sheshadri 	"pCache",				/* 249 */
    611  10021  Sheshadri 	"Bochs",				/* 250 */
    612  10021  Sheshadri 	"VMware File System",			/* 251 */
    613  10021  Sheshadri 	"VMware swap",				/* 252 */
    614  10021  Sheshadri 	"Linux raid autodetect",		/* 253 */
    615  10021  Sheshadri 	"NT Disk Administrator hidden",		/* 254 */
    616  10021  Sheshadri 	"Xenix Bad Block Table"			/* 255 */
    617  10021  Sheshadri };
    618  10021  Sheshadri 
    619  10021  Sheshadri /* Allowed extended partition menu options */
    620  10021  Sheshadri static char ext_part_menu_opts[] = "adhipr";
    621  10021  Sheshadri 
    622  10021  Sheshadri /*
    623  10021  Sheshadri  * Structure holding all information about the extended partition
    624  10021  Sheshadri  * NOTE : As of now, there will be just one instance of ext_part_t, since most
    625  10021  Sheshadri  * known systems allow only one extended dos partition per disk.
    626  10021  Sheshadri  */
    627  10021  Sheshadri static ext_part_t *epp;
    628  10021  Sheshadri #endif
    629   8254  Sheshadri 
    630    251      lclee static void update_disk_and_exit(boolean_t table_changed);
    631    251      lclee int main(int argc, char *argv[]);
    632    251      lclee static int read_geom(char *sgeom);
    633    251      lclee static void dev_mboot_read(void);
    634   6549   bharding static void dev_mboot_write(off_t sect, char *buff, int bootsiz);
    635    251      lclee static void mboot_read(void);
    636    251      lclee static void fill_patt(void);
    637    251      lclee static void abs_read(void);
    638    251      lclee static void abs_write(void);
    639    251      lclee static void load(int funct, char *file);
    640    251      lclee static void Set_Table_CHS_Values(int ti);
    641    251      lclee static int insert_tbl(int id, int act,
    642   8904      Barry     int bhead, int bsect, int bcyl,
    643   8904      Barry     int ehead, int esect, int ecyl,
    644   8904      Barry     uint32_t rsect, uint32_t numsect);
    645   8904      Barry static int entry_from_old_table(int id, int act,
    646    251      lclee     int bhead, int bsect, int bcyl,
    647    251      lclee     int ehead, int esect, int ecyl,
    648   7563     Prasad     uint32_t rsect, uint32_t numsect);
    649    251      lclee static int verify_tbl(void);
    650    251      lclee static int pars_fdisk(char *line,
    651    251      lclee     int *id, int *act,
    652    251      lclee     int *bhead, int *bsect, int *bcyl,
    653    251      lclee     int *ehead, int *esect, int *ecyl,
    654   7563     Prasad     uint32_t *rsect, uint32_t *numsect);
    655   7563     Prasad static int validate_part(int id, uint32_t rsect, uint32_t numsect);
    656    251      lclee static void stage0(void);
    657    251      lclee static int pcreate(void);
    658    251      lclee static int specify(uchar_t tsystid);
    659    251      lclee static void dispmenu(void);
    660    251      lclee static int pchange(void);
    661    251      lclee static int ppartid(void);
    662    251      lclee static char pdelete(void);
    663    251      lclee static void rm_blanks(char *s);
    664    251      lclee static int getcyl(void);
    665    251      lclee static void disptbl(void);
    666    251      lclee static void print_Table(void);
    667    251      lclee static void copy_Table_to_Old_Table(void);
    668    251      lclee static void nulltbl(void);
    669    251      lclee static void copy_Bootblk_to_Table(void);
    670    251      lclee static void fill_ipart(char *bootptr, struct ipart *partp);
    671    251      lclee #ifdef sparc
    672    251      lclee uchar_t getbyte(char **bp);
    673    251      lclee uint32_t getlong(char **bp);
    674    251      lclee #endif
    675    251      lclee static void copy_Table_to_Bootblk(void);
    676    251      lclee static int TableChanged(void);
    677    251      lclee static void ffile_write(char *file);
    678    251      lclee static void fix_slice(void);
    679    251      lclee static int yesno(void);
    680    251      lclee static int readvtoc(void);
    681    251      lclee static int writevtoc(void);
    682    251      lclee static int efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc);
    683    251      lclee static int clear_efi(void);
    684    251      lclee static void clear_vtoc(int table, int part);
    685    251      lclee static int lecture_and_query(char *warning, char *devname);
    686    251      lclee static void sanity_check_provided_device(char *devname, int fd);
    687    251      lclee static char *get_node(char *devname);
    688      0     stevel 
    689  10021  Sheshadri #ifdef i386
    690  10021  Sheshadri static void id_to_name(uchar_t sysid, char *buffer);
    691  10021  Sheshadri static void ext_read_input(char *buf);
    692  10021  Sheshadri static int ext_read_options(char *buf);
    693  10021  Sheshadri static int ext_invalid_option(char ch);
    694  10021  Sheshadri static void ext_read_valid_part_num(int *pno);
    695  10021  Sheshadri static void ext_read_valid_part_id(uchar_t *partid);
    696  10021  Sheshadri static int ext_read_valid_partition_start(uint32_t *begsec);
    697  10021  Sheshadri static void ext_read_valid_partition_size(uint32_t begsec, uint32_t *endsec);
    698  10021  Sheshadri static void ext_part_menu();
    699  10021  Sheshadri static void add_logical_drive();
    700  10021  Sheshadri static void delete_logical_drive();
    701  10021  Sheshadri static void ext_print_help_menu();
    702  10021  Sheshadri static void ext_change_logical_drive_id();
    703  10021  Sheshadri static void ext_print_part_types();
    704  10021  Sheshadri static void ext_print_logical_drive_layout();
    705  10021  Sheshadri static void preach_and_continue();
    706  10021  Sheshadri #ifdef DEBUG
    707  10021  Sheshadri static void ext_print_logdrive_layout_debug();
    708  10021  Sheshadri #endif	/* DEBUG */
    709  10021  Sheshadri #endif	/* i386 */
    710  10021  Sheshadri 
    711  10021  Sheshadri /*
    712  10021  Sheshadri  * This function is called only during the non-interactive mode.
    713  10021  Sheshadri  * It is touchy and does not tolerate any errors. If there are
    714  10021  Sheshadri  * mounted logical drives, changes to the partition table
    715  10021  Sheshadri  * is disallowed.
    716  10021  Sheshadri  */
    717      0     stevel static void
    718      0     stevel update_disk_and_exit(boolean_t table_changed)
    719      0     stevel {
    720  10021  Sheshadri #ifdef i386
    721  10021  Sheshadri 	int rval;
    722  10021  Sheshadri #endif
    723      0     stevel 	if (table_changed) {
    724      0     stevel 		/*
    725      0     stevel 		 * Copy the new table back to the sector buffer
    726      0     stevel 		 * and write it to disk
    727      0     stevel 		 */
    728      0     stevel 		copy_Table_to_Bootblk();
    729      0     stevel 		dev_mboot_write(0, Bootsect, sectsiz);
    730      0     stevel 	}
    731   8254  Sheshadri 
    732      0     stevel 	/* If the VTOC table is wrong fix it (truncation only) */
    733      0     stevel 	if (io_adjt)
    734      0     stevel 		fix_slice();
    735      0     stevel 
    736  10021  Sheshadri #ifdef i386
    737  10021  Sheshadri 	if (!io_readonly) {
    738  10021  Sheshadri 		rval = fdisk_commit_ext_part(epp);
    739  10021  Sheshadri 		switch (rval) {
    740  10021  Sheshadri 			case FDISK_SUCCESS:
    741  10021  Sheshadri 				/* Success */
    742  10021  Sheshadri 				break;
    743  10021  Sheshadri 			case FDISK_ENOEXTPART:
    744  10021  Sheshadri 				/* Nothing to do */
    745  10021  Sheshadri 				break;
    746  10021  Sheshadri 			default:
    747  10021  Sheshadri 				fprintf(stderr, "Error in"
    748  10021  Sheshadri 				    " fdisk_commit_ext_part\n");
    749  10021  Sheshadri 				exit(rval);
    750  10021  Sheshadri 		}
    751  10021  Sheshadri 	}
    752  10021  Sheshadri 	libfdisk_fini(&epp);
    753  10021  Sheshadri #endif
    754      0     stevel 	exit(0);
    755      0     stevel }
    756      0     stevel 
    757      0     stevel /*
    758      0     stevel  * main
    759      0     stevel  * Process command-line options.
    760      0     stevel  */
    761    251      lclee int
    762      0     stevel main(int argc, char *argv[])
    763      0     stevel {
    764    251      lclee 	int c, i;
    765      0     stevel 	extern	int optind;
    766      0     stevel 	extern	char *optarg;
    767      0     stevel 	int	errflg = 0;
    768      0     stevel 	int	diag_cnt = 0;
    769      0     stevel 	int openmode;
    770  10021  Sheshadri #ifdef i386
    771  10021  Sheshadri 	int rval;
    772  10021  Sheshadri 	int lf_op_flag = 0;
    773  10021  Sheshadri #endif
    774      0     stevel 
    775      0     stevel 	setbuf(stderr, 0);	/* so all output gets out on exit */
    776      0     stevel 	setbuf(stdout, 0);
    777      0     stevel 
    778      0     stevel 	/* Process the options. */
    779      0     stevel 	while ((c = getopt(argc, argv, "o:s:P:F:b:A:D:W:S:tTIhwvrndgGRBE"))
    780      0     stevel 	    != EOF) {
    781      0     stevel 		switch (c) {
    782      0     stevel 
    783      0     stevel 			case 'o':
    784   6549   bharding 				io_offset = (off_t)strtoull(optarg, 0, 0);
    785      0     stevel 				continue;
    786      0     stevel 			case 's':
    787   6549   bharding 				io_size = (off_t)strtoull(optarg, 0, 0);
    788      0     stevel 				continue;
    789      0     stevel 			case 'P':
    790      0     stevel 				diag_cnt++;
    791      0     stevel 				io_patt++;
    792      0     stevel 				io_fatt = optarg;
    793      0     stevel 				continue;
    794      0     stevel 			case 'w':
    795      0     stevel 				diag_cnt++;
    796      0     stevel 				io_wrt++;
    797      0     stevel 				continue;
    798      0     stevel 			case 'r':
    799      0     stevel 				diag_cnt++;
    800      0     stevel 				io_rd++;
    801      0     stevel 				continue;
    802      0     stevel 			case 'd':
    803      0     stevel 				io_debug++;
    804      0     stevel 				continue;
    805      0     stevel 			case 'I':
    806      0     stevel 				io_image++;
    807      0     stevel 				continue;
    808      0     stevel 			case 'R':
    809      0     stevel 				io_readonly++;
    810      0     stevel 				continue;
    811      0     stevel 			case 'S':
    812      0     stevel 				diag_cnt++;
    813      0     stevel 				io_sgeom = optarg;
    814      0     stevel 				continue;
    815      0     stevel 			case 'T':
    816      0     stevel 				io_ADJT++;
    817    251      lclee 				/* FALLTHRU */
    818      0     stevel 			case 't':
    819      0     stevel 				io_adjt++;
    820      0     stevel 				continue;
    821      0     stevel 			case 'B':
    822      0     stevel 				io_wholedisk++;
    823      0     stevel 				io_fdisk++;
    824      0     stevel 				continue;
    825      0     stevel 			case 'E':
    826      0     stevel 				io_EFIdisk++;
    827      0     stevel 				io_fdisk++;
    828      0     stevel 				continue;
    829      0     stevel 			case 'g':
    830      0     stevel 				diag_cnt++;
    831      0     stevel 				io_lgeom++;
    832      0     stevel 				continue;
    833      0     stevel 			case 'G':
    834      0     stevel 				diag_cnt++;
    835      0     stevel 				io_pgeom++;
    836      0     stevel 				continue;
    837      0     stevel 			case 'n':
    838      0     stevel 				io_nifdisk++;
    839      0     stevel 				io_fdisk++;
    840      0     stevel 				continue;
    841      0     stevel 			case 'F':
    842      0     stevel 				io_fdisk++;
    843      0     stevel 				io_ffdisk = optarg;
    844      0     stevel 				continue;
    845      0     stevel 			case 'b':
    846      0     stevel 				io_mboot = optarg;
    847      0     stevel 				continue;
    848      0     stevel 			case 'W':
    849      0     stevel 				/*
    850      0     stevel 				 * If '-' is the -W argument, then write
    851      0     stevel 				 * to standard output, otherwise write
    852      0     stevel 				 * to the specified file.
    853      0     stevel 				 */
    854      0     stevel 				if (strncmp(optarg, "-", 1) == 0)
    855      0     stevel 					stdo_flag = 1;
    856      0     stevel 				else
    857      0     stevel 					io_Wfdisk = optarg;
    858      0     stevel 				io_fdisk++;
    859      0     stevel 				continue;
    860      0     stevel 			case 'A':
    861      0     stevel 				io_fdisk++;
    862      0     stevel 				io_Afdisk = optarg;
    863      0     stevel 				continue;
    864      0     stevel 			case 'D':
    865      0     stevel 				io_fdisk++;
    866      0     stevel 				io_Dfdisk = optarg;
    867      0     stevel 				continue;
    868      0     stevel 			case 'h':
    869    251      lclee 				(void) fprintf(stderr, "%s\n", Usage);
    870    251      lclee 				(void) fprintf(stderr, "%s\n", Usage1);
    871      0     stevel 				exit(0);
    872    251      lclee 				/* FALLTHRU */
    873      0     stevel 			case 'v':
    874      0     stevel 				v_flag = 1;
    875      0     stevel 				continue;
    876      0     stevel 			case '?':
    877      0     stevel 				errflg++;
    878      0     stevel 				break;
    879      0     stevel 		}
    880      0     stevel 		break;
    881      0     stevel 	}
    882      0     stevel 
    883      0     stevel 	if (io_image && io_sgeom && diag_cnt == 1) {
    884      0     stevel 		diag_cnt = 0;
    885      0     stevel 	}
    886      0     stevel 
    887      0     stevel 	/* User option checking */
    888      0     stevel 
    889      0     stevel 	/* By default, run in interactive mode */
    890      0     stevel 	if (!io_fdisk && !diag_cnt && !io_nifdisk) {
    891      0     stevel 		io_ifdisk++;
    892      0     stevel 		io_fdisk++;
    893      0     stevel 	}
    894      0     stevel 	if (((io_fdisk || io_adjt) && diag_cnt) || (diag_cnt > 1)) {
    895      0     stevel 		errflg++;
    896      0     stevel 	}
    897      0     stevel 
    898      0     stevel 	/* Was any error detected? */
    899      0     stevel 	if (errflg || argc == optind) {
    900    251      lclee 		(void) fprintf(stderr, "%s\n", Usage);
    901    251      lclee 		(void) fprintf(stderr,
    902      0     stevel 		    "\nDetailed help is available with the -h option.\n");
    903      0     stevel 		exit(2);
    904      0     stevel 	}
    905      0     stevel 
    906      0     stevel 
    907      0     stevel 	/* Figure out the correct device node to open */
    908      0     stevel 	Dfltdev = get_node(argv[optind]);
    909      0     stevel 
    910      0     stevel 	if (io_readonly)
    911      0     stevel 		openmode = O_RDONLY;
    912      0     stevel 	else
    913      0     stevel 		openmode = O_RDWR|O_CREAT;
    914      0     stevel 
    915      0     stevel 	if ((Dev = open(Dfltdev, openmode, 0666)) == -1) {
    916    251      lclee 		(void) fprintf(stderr,
    917    251      lclee 		    "fdisk: Cannot open device %s.\n",
    918    251      lclee 		    Dfltdev);
    919      0     stevel 		exit(1);
    920   5169      lclee 	}
    921   5169      lclee 	/*
    922   5169      lclee 	 * not all disk (or disklike) drivers support DKIOCGMEDIAINFO
    923   5169      lclee 	 * in that case leave the minfo structure zeroed
    924   5169      lclee 	 */
    925   5169      lclee 	if (ioctl(Dev, DKIOCGMEDIAINFO, &minfo)) {
    926   9889      Larry 		(void) memset(&minfo, 0, sizeof (minfo));
    927      0     stevel 	}
    928      0     stevel 
    929      0     stevel 	/* Get the disk geometry */
    930      0     stevel 	if (!io_image) {
    931      0     stevel 		/* Get disk's HBA (virtual) geometry */
    932      0     stevel 		errno = 0;
    933      0     stevel 		if (ioctl(Dev, DKIOCG_VIRTGEOM, &disk_geom)) {
    934      0     stevel 
    935      0     stevel 			/*
    936      0     stevel 			 * If ioctl isn't implemented on this platform, then
    937      0     stevel 			 * turn off flag to print out virtual geometry (-v),
    938      0     stevel 			 * otherwise use the virtual geometry.
    939      0     stevel 			 */
    940      0     stevel 
    941      0     stevel 			if (errno == ENOTTY) {
    942      0     stevel 				v_flag = 0;
    943      0     stevel 				no_virtgeom_ioctl = 1;
    944      0     stevel 			} else if (errno == EINVAL) {
    945      0     stevel 				/*
    946      0     stevel 				 * This means that the ioctl exists, but
    947      0     stevel 				 * is invalid for this disk, meaning the
    948      0     stevel 				 * disk doesn't have an HBA geometry
    949      0     stevel 				 * (like, say, it's larger than 8GB).
    950      0     stevel 				 */
    951      0     stevel 				v_flag = 0;
    952      0     stevel 				hba_Numcyl = hba_heads = hba_sectors = 0;
    953      0     stevel 			} else {
    954      0     stevel 				(void) fprintf(stderr,
    955      0     stevel 				    "%s: Cannot get virtual disk geometry.\n",
    956      0     stevel 				    argv[optind]);
    957      0     stevel 				exit(1);
    958      0     stevel 			}
    959      0     stevel 		} else {
    960      0     stevel 			/* save virtual geometry values obtained by ioctl */
    961      0     stevel 			hba_Numcyl = disk_geom.dkg_ncyl;
    962      0     stevel 			hba_heads = disk_geom.dkg_nhead;
    963      0     stevel 			hba_sectors = disk_geom.dkg_nsect;
    964      0     stevel 		}
    965      0     stevel 
    966      0     stevel 		errno = 0;
    967      0     stevel 		if (ioctl(Dev, DKIOCG_PHYGEOM, &disk_geom)) {
    968      0     stevel 			if (errno == ENOTTY) {
    969      0     stevel 				no_physgeom_ioctl = 1;
    970      0     stevel 			} else {
    971      0     stevel 				(void) fprintf(stderr,
    972      0     stevel 				    "%s: Cannot get physical disk geometry.\n",
    973      0     stevel 				    argv[optind]);
    974      0     stevel 				exit(1);
    975      0     stevel 			}
    976      0     stevel 
    977      0     stevel 		}
    978      0     stevel 		/*
    979      0     stevel 		 * Call DKIOCGGEOM if the ioctls for physical and virtual
    980      0     stevel 		 * geometry fail. Get both from this generic call.
    981      0     stevel 		 */
    982      0     stevel 		if (no_virtgeom_ioctl && no_physgeom_ioctl) {
    983      0     stevel 			errno = 0;
    984      0     stevel 			if (ioctl(Dev, DKIOCGGEOM, &disk_geom)) {
    985      0     stevel 				(void) fprintf(stderr,
    986      0     stevel 				    "%s: Cannot get disk label geometry.\n",
    987      0     stevel 				    argv[optind]);
    988      0     stevel 				exit(1);
    989      0     stevel 			}
    990      0     stevel 		}
    991      0     stevel 
    992      0     stevel 		Numcyl = disk_geom.dkg_ncyl;
    993      0     stevel 		heads = disk_geom.dkg_nhead;
    994      0     stevel 		sectors = disk_geom.dkg_nsect;
    995   9889      Larry 
    996   9889      Larry 		if (minfo.dki_lbsize != 0)
    997   9889      Larry 			sectsiz = minfo.dki_lbsize;
    998   9889      Larry 		else
    999   9889      Larry 			sectsiz = 512;
   1000   9889      Larry 
   1001      0     stevel 		acyl = disk_geom.dkg_acyl;
   1002      0     stevel 
   1003      0     stevel 		/*
   1004      0     stevel 		 * if hba geometry was not set by DKIOC_VIRTGEOM
   1005      0     stevel 		 * or we got an invalid hba geometry
   1006      0     stevel 		 * then set hba geometry based on max values
   1007      0     stevel 		 */
   1008      0     stevel 		if (no_virtgeom_ioctl ||
   1009    251      lclee 		    disk_geom.dkg_ncyl == 0 ||
   1010    251      lclee 		    disk_geom.dkg_nhead == 0 ||
   1011    251      lclee 		    disk_geom.dkg_nsect == 0 ||
   1012      0     stevel 		    disk_geom.dkg_ncyl > MAX_CYL ||
   1013      0     stevel 		    disk_geom.dkg_nhead > MAX_HEAD ||
   1014      0     stevel 		    disk_geom.dkg_nsect > MAX_SECT) {
   1015      0     stevel 
   1016      0     stevel 			/*
   1017      0     stevel 			 * turn off flag to print out virtual geometry (-v)
   1018      0     stevel 			 */
   1019      0     stevel 			v_flag = 0;
   1020      0     stevel 			hba_sectors	= MAX_SECT;
   1021      0     stevel 			hba_heads	= MAX_HEAD + 1;
   1022      0     stevel 			hba_Numcyl	= (Numcyl * heads * sectors) /
   1023      0     stevel 			    (hba_sectors * hba_heads);
   1024      0     stevel 		}
   1025      0     stevel 
   1026      0     stevel 		if (io_debug) {
   1027    251      lclee 			(void) fprintf(stderr, "Physical Geometry:\n");
   1028    251      lclee 			(void) fprintf(stderr,
   1029      0     stevel 			    "  cylinders[%d] heads[%d] sectors[%d]\n"
   1030      0     stevel 			    "  sector size[%d] blocks[%d] mbytes[%d]\n",
   1031      0     stevel 			    Numcyl,
   1032      0     stevel 			    heads,
   1033      0     stevel 			    sectors,
   1034      0     stevel 			    sectsiz,
   1035    251      lclee 			    Numcyl * heads * sectors,
   1036    251      lclee 			    (Numcyl * heads * sectors * sectsiz) / 1048576);
   1037    251      lclee 			(void) fprintf(stderr, "Virtual (HBA) Geometry:\n");
   1038    251      lclee 			(void) fprintf(stderr,
   1039      0     stevel 			    "  cylinders[%d] heads[%d] sectors[%d]\n"
   1040      0     stevel 			    "  sector size[%d] blocks[%d] mbytes[%d]\n",
   1041      0     stevel 			    hba_Numcyl,
   1042      0     stevel 			    hba_heads,
   1043      0     stevel 			    hba_sectors,
   1044      0     stevel 			    sectsiz,
   1045    251      lclee 			    hba_Numcyl * hba_heads * hba_sectors,
   1046    251      lclee 			    (hba_Numcyl * hba_heads * hba_sectors * sectsiz) /
   1047    251      lclee 			    1048576);
   1048      0     stevel 		}
   1049      0     stevel 	}
   1050      0     stevel 
   1051      0     stevel 	/* If user has requested a geometry report just do it and exit */
   1052      0     stevel 	if (io_lgeom) {
   1053      0     stevel 		if (ioctl(Dev, DKIOCGGEOM, &disk_geom)) {
   1054      0     stevel 			(void) fprintf(stderr,
   1055      0     stevel 			    "%s: Cannot get disk label geometry.\n",
   1056      0     stevel 			    argv[optind]);
   1057      0     stevel 			exit(1);
   1058      0     stevel 		}
   1059      0     stevel 		Numcyl = disk_geom.dkg_ncyl;
   1060      0     stevel 		heads = disk_geom.dkg_nhead;
   1061      0     stevel 		sectors = disk_geom.dkg_nsect;
   1062   9889      Larry 		if (minfo.dki_lbsize != 0)
   1063   9889      Larry 			sectsiz = minfo.dki_lbsize;
   1064   9889      Larry 		else
   1065   9889      Larry 			sectsiz = 512;
   1066   9889      Larry 
   1067      0     stevel 		acyl = disk_geom.dkg_acyl;
   1068    251      lclee 		(void) printf("* Label geometry for device %s\n", Dfltdev);
   1069    251      lclee 		(void) printf(
   1070    251      lclee 		    "* PCYL     NCYL     ACYL     BCYL     NHEAD NSECT"
   1071      0     stevel 		    " SECSIZ\n");
   1072    251      lclee 		(void) printf("  %-8d %-8d %-8d %-8d %-5d %-5d %-6d\n",
   1073      0     stevel 		    Numcyl,
   1074      0     stevel 		    disk_geom.dkg_ncyl,
   1075      0     stevel 		    disk_geom.dkg_acyl,
   1076      0     stevel 		    disk_geom.dkg_bcyl,
   1077      0     stevel 		    heads,
   1078      0     stevel 		    sectors,
   1079      0     stevel 		    sectsiz);
   1080      0     stevel 		exit(0);
   1081      0     stevel 	} else if (io_pgeom) {
   1082      0     stevel 		if (ioctl(Dev, DKIOCG_PHYGEOM, &disk_geom)) {
   1083      0     stevel 			(void) fprintf(stderr,
   1084      0     stevel 			    "%s: Cannot get physical disk geometry.\n",
   1085      0     stevel 			    argv[optind]);
   1086      0     stevel 			exit(1);
   1087      0     stevel 		}
   1088    251      lclee 		(void) printf("* Physical geometry for device %s\n", Dfltdev);
   1089    251      lclee 		(void) printf(
   1090    251      lclee 		    "* PCYL     NCYL     ACYL     BCYL     NHEAD NSECT"
   1091      0     stevel 		    " SECSIZ\n");
   1092    251      lclee 		(void) printf("  %-8d %-8d %-8d %-8d %-5d %-5d %-6d\n",
   1093      0     stevel 		    disk_geom.dkg_pcyl,
   1094      0     stevel 		    disk_geom.dkg_ncyl,
   1095      0     stevel 		    disk_geom.dkg_acyl,
   1096      0     stevel 		    disk_geom.dkg_bcyl,
   1097      0     stevel 		    disk_geom.dkg_nhead,
   1098      0     stevel 		    disk_geom.dkg_nsect,
   1099      0     stevel 		    sectsiz);
   1100      0     stevel 		exit(0);
   1101      0     stevel 	} else if (io_sgeom) {
   1102      0     stevel 		if (read_geom(io_sgeom)) {
   1103      0     stevel 			exit(1);
   1104      0     stevel 		} else if (!io_image) {
   1105      0     stevel 			exit(0);
   1106      0     stevel 		}
   1107      0     stevel 	}
   1108      0     stevel 
   1109   5169      lclee 	/*
   1110   5169      lclee 	 * some drivers may not support DKIOCGMEDIAINFO
   1111   5169      lclee 	 * in that case use CHS
   1112   5169      lclee 	 */
   1113   7563     Prasad 	chs_capacity = (diskaddr_t)Numcyl * heads * sectors;
   1114   5169      lclee 	dev_capacity = chs_capacity;
   1115   7563     Prasad 	Numcyl_usable = Numcyl;
   1116   7563     Prasad 
   1117   7563     Prasad 	if (chs_capacity > DK_MAX_2TB) {
   1118   7563     Prasad 		/* limit to 2TB */
   1119   7563     Prasad 		Numcyl_usable = DK_MAX_2TB / (heads * sectors);
   1120   7563     Prasad 		chs_capacity = (diskaddr_t)Numcyl_usable * heads * sectors;
   1121   7563     Prasad 	}
   1122   7563     Prasad 
   1123   5169      lclee 	if (minfo.dki_capacity > 0)
   1124   5169      lclee 		dev_capacity = minfo.dki_capacity;
   1125   5169      lclee 
   1126      0     stevel 	/* Allocate memory to hold three complete sectors */
   1127   9889      Larry 	Bootsect = (char *)calloc(3 * sectsiz, 1);
   1128      0     stevel 	if (Bootsect == NULL) {
   1129    251      lclee 		(void) fprintf(stderr,
   1130      0     stevel 		    "fdisk: Unable to obtain enough buffer memory"
   1131      0     stevel 		    " (%d bytes).\n",
   1132    251      lclee 		    3 * sectsiz);
   1133      0     stevel 		exit(1);
   1134      0     stevel 	}
   1135      0     stevel 
   1136      0     stevel 	Nullsect = Bootsect + sectsiz;
   1137      0     stevel 	/* Zero out the "NULL" sector */
   1138      0     stevel 	for (i = 0; i < sectsiz; i++) {
   1139      0     stevel 		Nullsect[i] = 0;
   1140      0     stevel 	}
   1141      0     stevel 
   1142      0     stevel 	/* Find out what the user wants done */
   1143      0     stevel 	if (io_rd) {		/* abs disk read */
   1144      0     stevel 		abs_read();	/* will not return */
   1145      0     stevel 	} else if (io_wrt && !io_readonly) {
   1146      0     stevel 		abs_write();	/* will not return */
   1147      0     stevel 	} else if (io_patt && !io_readonly) {
   1148      0     stevel 		fill_patt();	/* will not return */
   1149      0     stevel 	}
   1150      0     stevel 
   1151      0     stevel 
   1152      0     stevel 	/* This is the fdisk edit, the real reason for the program.	*/
   1153      0     stevel 
   1154      0     stevel 	sanity_check_provided_device(Dfltdev, Dev);
   1155      0     stevel 
   1156      0     stevel 	/* Get the new BOOT program in case we write a new fdisk table */
   1157      0     stevel 	mboot_read();
   1158      0     stevel 
   1159      0     stevel 	/* Read from disk master boot */
   1160      0     stevel 	dev_mboot_read();
   1161      0     stevel 
   1162      0     stevel 	/*
   1163      0     stevel 	 * Verify and copy the device's fdisk table. This will be used
   1164      0     stevel 	 * as the prototype mboot if the device's mboot looks invalid.
   1165      0     stevel 	 */
   1166      0     stevel 	Bootblk = (struct mboot *)Bootsect;
   1167      0     stevel 	copy_Bootblk_to_Table();
   1168      0     stevel 
   1169      0     stevel 	/* save away a copy of Table in Old_Table for sensing changes */
   1170      0     stevel 	copy_Table_to_Old_Table();
   1171      0     stevel 
   1172  10021  Sheshadri #ifdef i386
   1173  10021  Sheshadri 	/*
   1174  10021  Sheshadri 	 * Read extended partition only when the fdisk table is not
   1175  10021  Sheshadri 	 * supplied from a file
   1176  10021  Sheshadri 	 */
   1177  10021  Sheshadri 	if (!io_ffdisk) {
   1178  10021  Sheshadri 		lf_op_flag |= FDISK_READ_DISK;
   1179  10021  Sheshadri 	}
   1180  10021  Sheshadri 	if ((rval = libfdisk_init(&epp, Dfltdev, &Table[0], lf_op_flag))
   1181  10021  Sheshadri 	    != FDISK_SUCCESS) {
   1182  10021  Sheshadri 		switch (rval) {
   1183  10021  Sheshadri 			/*
   1184  10021  Sheshadri 			 * FDISK_EBADLOGDRIVE and FDISK_ENOLOGDRIVE can
   1185  10021  Sheshadri 			 * be considered as soft errors and hence
   1186  10021  Sheshadri 			 * we do not exit
   1187  10021  Sheshadri 			 */
   1188  10021  Sheshadri 			case FDISK_EBADLOGDRIVE:
   1189  10021  Sheshadri 				break;
   1190  10021  Sheshadri 			case FDISK_ENOLOGDRIVE:
   1191  10021  Sheshadri 				break;
   1192  10021  Sheshadri 			case FDISK_ENOVGEOM:
   1193  10021  Sheshadri 				fprintf(stderr, "Could not get virtual"
   1194  10021  Sheshadri 				    " geometry for this device\n");
   1195  10021  Sheshadri 				exit(1);
   1196  10021  Sheshadri 				break;
   1197  10021  Sheshadri 			case FDISK_ENOPGEOM:
   1198  10021  Sheshadri 				fprintf(stderr, "Could not get physical"
   1199  10021  Sheshadri 				    " geometry for this device\n");
   1200  10021  Sheshadri 				exit(1);
   1201  10021  Sheshadri 				break;
   1202  10021  Sheshadri 			case FDISK_ENOLGEOM:
   1203  10021  Sheshadri 				fprintf(stderr, "Could not get label"
   1204  10021  Sheshadri 				    " geometry for this device\n");
   1205  10021  Sheshadri 				exit(1);
   1206  10021  Sheshadri 				break;
   1207  10021  Sheshadri 			default:
   1208  10021  Sheshadri 				perror("Failed to initialise libfdisk.\n");
   1209  10021  Sheshadri 				exit(1);
   1210  10021  Sheshadri 				break;
   1211  10021  Sheshadri 		}
   1212  10021  Sheshadri 	}
   1213  10021  Sheshadri #endif
   1214  10021  Sheshadri 
   1215      0     stevel 	/* Load fdisk table from specified file (-F fdisk_file) */
   1216      0     stevel 	if (io_ffdisk) {
   1217      0     stevel 		/* Load and verify user-specified table parameters */
   1218      0     stevel 		load(LOADFILE, io_ffdisk);
   1219      0     stevel 	}
   1220      0     stevel 
   1221      0     stevel 	/* Does user want to delete or add an entry? */
   1222      0     stevel 	if (io_Dfdisk) {
   1223      0     stevel 		load(LOADDEL, io_Dfdisk);
   1224      0     stevel 	}
   1225      0     stevel 	if (io_Afdisk) {
   1226      0     stevel 		load(LOADADD, io_Afdisk);
   1227      0     stevel 	}
   1228      0     stevel 
   1229      0     stevel 	if (!io_ffdisk && !io_Afdisk && !io_Dfdisk) {
   1230      0     stevel 		/* Check if there is no fdisk table */
   1231      0     stevel 		if (Table[0].systid == UNUSED || io_wholedisk || io_EFIdisk) {
   1232      0     stevel 			if (io_ifdisk && !io_wholedisk && !io_EFIdisk) {
   1233    251      lclee 				(void) printf(
   1234    251      lclee 				    "No fdisk table exists. The default"
   1235    251      lclee 				    " partition for the disk is:\n\n"
   1236    251      lclee 				    "  a 100%% \"SOLARIS System\" "
   1237    251      lclee 				    "partition\n\n"
   1238    251      lclee 				    "Type \"y\" to accept the default "
   1239      0     stevel 				    "partition,  otherwise type \"n\" to "
   1240      0     stevel 				    "edit the\n partition table.\n");
   1241   7563     Prasad 
   1242   7563     Prasad 				if (Numcyl > Numcyl_usable)
   1243   7563     Prasad 					(void) printf("WARNING: Disk is larger"
   1244   7563     Prasad 					    " than 2TB. Solaris partition will"
   1245   7563     Prasad 					    " be limited to 2 TB.\n");
   1246      0     stevel 			}
   1247      0     stevel 
   1248      0     stevel 			/* Edit the partition table as directed */
   1249      0     stevel 			if (io_wholedisk ||(io_ifdisk && yesno())) {
   1250      0     stevel 
   1251      0     stevel 				/* Default scenario */
   1252      0     stevel 				nulltbl();
   1253      0     stevel 				/* now set up UNIX System partition */
   1254      0     stevel 				Table[0].bootid = ACTIVE;
   1255  10021  Sheshadri 				Table[0].relsect = LE_32(heads * sectors);
   1256   7563     Prasad 
   1257   7563     Prasad 				Table[0].numsect =
   1258  10021  Sheshadri 				    LE_32((ulong_t)((Numcyl_usable - 1) *
   1259      0     stevel 				    heads * sectors));
   1260   7563     Prasad 
   1261      0     stevel 				Table[0].systid = SUNIXOS2;   /* Solaris */
   1262      0     stevel 
   1263      0     stevel 				/* calculate CHS values for table entry 0 */
   1264      0     stevel 				Set_Table_CHS_Values(0);
   1265      0     stevel 				update_disk_and_exit(B_TRUE);
   1266      0     stevel 			} else if (io_EFIdisk) {
   1267      0     stevel 				/* create an EFI partition for the whole disk */
   1268      0     stevel 				nulltbl();
   1269      0     stevel 				i = insert_tbl(EFI_PMBR, 0, 0, 0, 0, 0, 0, 0, 1,
   1270   7563     Prasad 				    (dev_capacity > DK_MAX_2TB) ? DK_MAX_2TB :
   1271   7563     Prasad 				    (dev_capacity - 1));
   1272      0     stevel 				if (i != 0) {
   1273    251      lclee 					(void) fprintf(stderr,
   1274    251      lclee 					    "Error creating EFI partition\n");
   1275      0     stevel 					exit(1);
   1276      0     stevel 				}
   1277      0     stevel 				update_disk_and_exit(B_TRUE);
   1278      0     stevel 			}
   1279      0     stevel 		}
   1280      0     stevel 	}
   1281      0     stevel 
   1282      0     stevel 	/* Display complete fdisk table entries for debugging purposes */
   1283      0     stevel 	if (io_debug) {
   1284    251      lclee 		(void) fprintf(stderr, "Partition Table Entry Values:\n");
   1285      0     stevel 		print_Table();
   1286      0     stevel 		if (io_ifdisk) {
   1287    251      lclee 			(void) fprintf(stderr, "\n");
   1288    251      lclee 			(void) fprintf(stderr, "Press Enter to continue.\n");
   1289   9786      Barry 			(void) fgets(s, sizeof (s), stdin);
   1290      0     stevel 		}
   1291      0     stevel 	}
   1292      0     stevel 
   1293      0     stevel 	/* Interactive fdisk mode */
   1294      0     stevel 	if (io_ifdisk) {
   1295    251      lclee 		(void) printf(CLR_SCR);
   1296      0     stevel 		disptbl();
   1297    251      lclee 		for (;;) {
   1298    251      lclee 			stage0();
   1299      0     stevel 			copy_Bootblk_to_Table();
   1300      0     stevel 			disptbl();
   1301      0     stevel 		}
   1302      0     stevel 	}
   1303      0     stevel 
   1304      0     stevel 	/* If user wants to write the table to a file, do it */
   1305      0     stevel 	if (io_Wfdisk)
   1306      0     stevel 		ffile_write(io_Wfdisk);
   1307      0     stevel 	else if (stdo_flag)
   1308      0     stevel 		ffile_write((char *)stdout);
   1309      0     stevel 
   1310      0     stevel 	update_disk_and_exit(TableChanged() == 1);
   1311    251      lclee 	return (0);
   1312      0     stevel }
   1313      0     stevel 
   1314      0     stevel /*
   1315      0     stevel  * read_geom
   1316      0     stevel  * Read geometry from specified file (-S).
   1317      0     stevel  */
   1318      0     stevel 
   1319    251      lclee static int
   1320    251      lclee read_geom(char *sgeom)
   1321      0     stevel {
   1322      0     stevel 	char	line[256];
   1323      0     stevel 	FILE *fp;
   1324      0     stevel 
   1325      0     stevel 	/* open the prototype file */
   1326      0     stevel 	if ((fp = fopen(sgeom, "r")) == NULL) {
   1327      0     stevel 		(void) fprintf(stderr, "fdisk: Cannot open file %s.\n",
   1328      0     stevel 		    io_sgeom);
   1329      0     stevel 		return (1);
   1330      0     stevel 	}
   1331      0     stevel 
   1332      0     stevel 	/* Read a line from the file */
   1333      0     stevel 	while (fgets(line, sizeof (line) - 1, fp)) {
   1334      0     stevel 		if (line[0] == '\0' || line[0] == '\n' || line[0] == '*')
   1335      0     stevel 			continue;
   1336      0     stevel 		else {
   1337      0     stevel 			line[strlen(line)] = '\0';
   1338    251      lclee 			if (sscanf(line, "%hu %hu %hu %hu %hu %hu %d",
   1339      0     stevel 			    &disk_geom.dkg_pcyl,
   1340      0     stevel 			    &disk_geom.dkg_ncyl,
   1341      0     stevel 			    &disk_geom.dkg_acyl,
   1342      0     stevel 			    &disk_geom.dkg_bcyl,
   1343      0     stevel 			    &disk_geom.dkg_nhead,
   1344      0     stevel 			    &disk_geom.dkg_nsect,
   1345      0     stevel 			    &sectsiz) != 7) {
   1346      0     stevel 				(void) fprintf(stderr,
   1347      0     stevel 				    "Syntax error:\n	\"%s\".\n",
   1348      0     stevel 				    line);
   1349      0     stevel 				return (1);
   1350      0     stevel 			}
   1351      0     stevel 			break;
   1352      0     stevel 		} /* else */
   1353      0     stevel 	} /* while (fgets(line, sizeof (line) - 1, fp)) */
   1354      0     stevel 
   1355      0     stevel 	if (!io_image) {
   1356      0     stevel 		if (ioctl(Dev, DKIOCSGEOM, &disk_geom)) {
   1357      0     stevel 			(void) fprintf(stderr,
   1358      0     stevel 			    "fdisk: Cannot set label geometry.\n");
   1359      0     stevel 			return (1);
   1360      0     stevel 		}
   1361      0     stevel 	} else {
   1362      0     stevel 		Numcyl = hba_Numcyl = disk_geom.dkg_ncyl;
   1363      0     stevel 		heads = hba_heads = disk_geom.dkg_nhead;
   1364      0     stevel 		sectors = hba_sectors = disk_geom.dkg_nsect;
   1365      0     stevel 		acyl = disk_geom.dkg_acyl;
   1366      0     stevel 	}
   1367      0     stevel 
   1368    251      lclee 	(void) fclose(fp);
   1369      0     stevel 	return (0);
   1370      0     stevel }
   1371      0     stevel 
   1372      0     stevel /*
   1373      0     stevel  * dev_mboot_read
   1374      0     stevel  * Read the master boot sector from the device.
   1375      0     stevel  */
   1376    251      lclee static void
   1377    251      lclee dev_mboot_read(void)
   1378      0     stevel {
   1379      0     stevel 	if ((ioctl(Dev, DKIOCGMBOOT, Bootsect) < 0) && (errno != ENOTTY)) {
   1380      0     stevel 		perror("Error in ioctl DKIOCGMBOOT");
   1381      0     stevel 	}
   1382      0     stevel 	if (errno == 0)
   1383      0     stevel 		return;
   1384      0     stevel 	if (lseek(Dev, 0, SEEK_SET) == -1) {
   1385    251      lclee 		(void) fprintf(stderr,
   1386      0     stevel 		    "fdisk: Error seeking to partition table on %s.\n",
   1387      0     stevel 		    Dfltdev);
   1388      0     stevel 		if (!io_image)
   1389      0     stevel 			exit(1);
   1390      0     stevel 	}
   1391      0     stevel 	if (read(Dev, Bootsect, sectsiz) != sectsiz) {
   1392    251      lclee 		(void) fprintf(stderr,
   1393      0     stevel 		    "fdisk: Error reading partition table from %s.\n",
   1394      0     stevel 		    Dfltdev);
   1395      0     stevel 		if (!io_image)
   1396      0     stevel 			exit(1);
   1397      0     stevel 	}
   1398      0     stevel }
   1399      0     stevel 
   1400      0     stevel /*
   1401      0     stevel  * dev_mboot_write
   1402      0     stevel  * Write the master boot sector to the device.
   1403      0     stevel  */
   1404    251      lclee static void
   1405   6549   bharding dev_mboot_write(off_t sect, char *buff, int bootsiz)
   1406      0     stevel {
   1407      0     stevel 	int 	new_pt, old_pt, error;
   1408   6478   bharding 	int	clr_efi = -1;
   1409      0     stevel 
   1410      0     stevel 	if (io_readonly)
   1411    251      lclee 		return;
   1412      0     stevel 
   1413      0     stevel 	if (io_debug) {
   1414    251      lclee 		(void) fprintf(stderr, "About to write fdisk table:\n");
   1415      0     stevel 		print_Table();
   1416      0     stevel 		if (io_ifdisk) {
   1417    251      lclee 			(void) fprintf(stderr, "Press Enter to continue.\n");
   1418   9786      Barry 			(void) fgets(s, sizeof (s), stdin);
   1419      0     stevel 		}
   1420      0     stevel 	}
   1421      0     stevel 
   1422   6478   bharding 	/*
   1423   6478   bharding 	 * If the new table has any Solaris partitions and the old
   1424   6478   bharding 	 * table does not have an entry that describes it
   1425   6478   bharding 	 * exactly then clear the old vtoc (if any).
   1426   6478   bharding 	 */
   1427      0     stevel 	for (new_pt = 0; new_pt < FD_NUMPART; new_pt++) {
   1428      0     stevel 
   1429   6478   bharding 		/* We only care about potential Solaris parts. */
   1430      0     stevel 		if (Table[new_pt].systid != SUNIXOS &&
   1431      0     stevel 		    Table[new_pt].systid != SUNIXOS2)
   1432      0     stevel 			continue;
   1433  10021  Sheshadri 
   1434   6478   bharding 		/* Does the old table have an exact entry for the new entry? */
   1435   6478   bharding 		for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) {
   1436   6478   bharding 
   1437   6478   bharding 			/* We only care about old Solaris partitions. */
   1438   6478   bharding 			if ((Old_Table[old_pt].systid == SUNIXOS) ||
   1439   6478   bharding 			    (Old_Table[old_pt].systid == SUNIXOS2)) {
   1440   6478   bharding 
   1441   6478   bharding 				/* Is this old one the same as a new one? */
   1442   6478   bharding 				if ((Old_Table[old_pt].relsect ==
   1443   6478   bharding 				    Table[new_pt].relsect) &&
   1444   6478   bharding 				    (Old_Table[old_pt].numsect ==
   1445   6478   bharding 				    Table[new_pt].numsect))
   1446   6478   bharding 					break; /* Yes */
   1447   6478   bharding 			}
   1448   6478   bharding 		}
   1449   6478   bharding 
   1450   6478   bharding 		/* Did a solaris partition change location or size? */
   1451   6478   bharding 		if (old_pt >= FD_NUMPART) {
   1452   6478   bharding 			/* Yes clear old vtoc */
   1453   6478   bharding 			if (io_debug) {
   1454   6478   bharding 				(void) fprintf(stderr,
   1455   6478   bharding 				    "Clearing VTOC labels from NEW"
   1456   6478   bharding 				    " table\n");
   1457   6478   bharding 			}
   1458   6478   bharding 			clear_vtoc(NEW, new_pt);
   1459   6478   bharding 		}
   1460   6478   bharding 	}
   1461   6478   bharding 
   1462   6478   bharding 
   1463   6478   bharding 	/* see if the old table had EFI */
   1464   6478   bharding 	for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) {
   1465   6478   bharding 		if (Old_Table[old_pt].systid == EFI_PMBR) {
   1466   6478   bharding 			clr_efi = old_pt;
   1467      0     stevel 		}
   1468      0     stevel 	}
   1469      0     stevel 
   1470      0     stevel 	/* look to see if a EFI partition changed in relsect/numsect */
   1471      0     stevel 	for (new_pt = 0; new_pt < FD_NUMPART; new_pt++) {
   1472      0     stevel 		if (Table[new_pt].systid != EFI_PMBR)
   1473      0     stevel 			continue;
   1474      0     stevel 		for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) {
   1475   5169      lclee 			if ((Old_Table[old_pt].systid ==
   1476   5169      lclee 			    Table[new_pt].systid) &&
   1477   5169      lclee 			    (Old_Table[old_pt].relsect ==
   1478   5169      lclee 			    Table[new_pt].relsect) &&
   1479   5169      lclee 			    (Old_Table[old_pt].numsect ==
   1480   5169      lclee 			    Table[new_pt].numsect))
   1481   5169      lclee 				break;
   1482      0     stevel 		}
   1483      0     stevel 
   1484      0     stevel 		/*
   1485      0     stevel 		 * if EFI partition changed, set the flag to clear
   1486      0     stevel 		 * the EFI GPT
   1487      0     stevel 		 */
   1488      0     stevel 		if (old_pt == FD_NUMPART && Table[new_pt].begcyl != 0) {
   1489      0     stevel 			clr_efi = 0;
   1490      0     stevel 		}
   1491      0     stevel 		break;
   1492      0     stevel 	}
   1493      0     stevel 
   1494      0     stevel 	/* clear labels if necessary */
   1495      0     stevel 	if (clr_efi >= 0) {
   1496      0     stevel 		if (io_debug) {
   1497    251      lclee 			(void) fprintf(stderr, "Clearing EFI labels\n");
   1498      0     stevel 		}
   1499      0     stevel 		if ((error = clear_efi()) != 0) {
   1500      0     stevel 			if (io_debug) {
   1501    251      lclee 				(void) fprintf(stderr,
   1502    251      lclee 				    "\tError %d clearing EFI labels"
   1503      0     stevel 				    " (probably no EFI labels exist)\n",
   1504      0     stevel 				    error);
   1505      0     stevel 			}
   1506      0     stevel 		}
   1507      0     stevel 	}
   1508      0     stevel 
   1509      0     stevel 	if ((ioctl(Dev, DKIOCSMBOOT, buff) == -1) && (errno != ENOTTY)) {
   1510    251      lclee 		(void) fprintf(stderr,
   1511      0     stevel 		    "fdisk: Error in ioctl DKIOCSMBOOT on %s.\n",
   1512      0     stevel 		    Dfltdev);
   1513      0     stevel 	}
   1514      0     stevel 	if (errno == 0)
   1515      0     stevel 		return;
   1516      0     stevel 
   1517      0     stevel 	/* write to disk drive */
   1518      0     stevel 	if (lseek(Dev, sect, SEEK_SET) == -1) {
   1519    251      lclee 		(void) fprintf(stderr,
   1520      0     stevel 		    "fdisk: Error seeking to master boot record on %s.\n",
   1521      0     stevel 		    Dfltdev);
   1522      0     stevel 		exit(1);
   1523      0     stevel 	}
   1524      0     stevel 	if (write(Dev, buff, bootsiz) != bootsiz) {
   1525    251      lclee 		(void) fprintf(stderr,
   1526      0     stevel 		    "fdisk: Error writing master boot record to %s.\n",
   1527      0     stevel 		    Dfltdev);
   1528      0     stevel 		exit(1);
   1529      0     stevel 	}
   1530      0     stevel }
   1531      0     stevel 
   1532      0     stevel /*
   1533      0     stevel  * mboot_read
   1534      0     stevel  * Read the prototype boot records from the files.
   1535      0     stevel  */
   1536    251      lclee static void
   1537    251      lclee mboot_read(void)
   1538      0     stevel {
   1539      0     stevel 	int mDev, i;
   1540      0     stevel 	struct ipart *part;
   1541      0     stevel 
   1542      0     stevel #if defined(i386) || defined(sparc)
   1543      0     stevel 	/*
   1544      0     stevel 	 * If the master boot file hasn't been specified, use the
   1545      0     stevel 	 * implementation architecture name to generate the default one.
   1546      0     stevel 	 */
   1547      0     stevel 	if (io_mboot == (char *)0) {
   1548      0     stevel 		/*
   1549      0     stevel 		 * Bug ID 1249035:
   1550      0     stevel 		 *	The mboot file must be delivered on all platforms
   1551      0     stevel 		 *	and installed in a non-platform-dependent
   1552      0     stevel 		 *	directory; i.e., /usr/lib/fs/ufs.
   1553      0     stevel 		 */
   1554      0     stevel 		io_mboot = "/usr/lib/fs/ufs/mboot";
   1555      0     stevel 	}
   1556      0     stevel 
   1557      0     stevel 	/* First read in the master boot record */
   1558      0     stevel 
   1559      0     stevel 	/* Open the master boot proto file */
   1560      0     stevel 	if ((mDev = open(io_mboot, O_RDONLY, 0666)) == -1) {
   1561    251      lclee 		(void) fprintf(stderr,
   1562      0     stevel 		    "fdisk: Cannot open master boot file %s.\n",
   1563      0     stevel 		    io_mboot);
   1564      0     stevel 		exit(1);
   1565      0     stevel 	}
   1566      0     stevel 
   1567      0     stevel 	/* Read the master boot program */
   1568      0     stevel 	if (read(mDev, &BootCod, sizeof (struct mboot)) != sizeof
   1569      0     stevel 	    (struct mboot)) {
   1570    251      lclee 		(void) fprintf(stderr,
   1571      0     stevel 		    "fdisk: Cannot read master boot file %s.\n",
   1572      0     stevel 		    io_mboot);
   1573      0     stevel 		exit(1);
   1574      0     stevel 	}
   1575      0     stevel 
   1576      0     stevel 	/* Is this really a master boot record? */
   1577  10021  Sheshadri 	if (LE_16(BootCod.signature) != MBB_MAGIC) {
   1578    251      lclee 		(void) fprintf(stderr,
   1579      0     stevel 		    "fdisk: Invalid master boot file %s.\n", io_mboot);
   1580    251      lclee 		(void) fprintf(stderr,
   1581    251      lclee 		    "Bad magic number: is %x, but should be %x.\n",
   1582  10021  Sheshadri 		    LE_16(BootCod.signature), MBB_MAGIC);
   1583      0     stevel 		exit(1);
   1584      0     stevel 	}
   1585      0     stevel 
   1586    251      lclee 	(void) close(mDev);
   1587      0     stevel #else
   1588      0     stevel #error	fdisk needs to be ported to new architecture
   1589      0     stevel #endif
   1590      0     stevel 
   1591      0     stevel 	/* Zero out the partitions part of this record */
   1592      0     stevel 	part = (struct ipart *)BootCod.parts;
   1593      0     stevel 	for (i = 0; i < FD_NUMPART; i++, part++) {
   1594    251      lclee 		(void) memset(part, 0, sizeof (struct ipart));
   1595      0     stevel 	}
   1596      0     stevel 
   1597      0     stevel }
   1598      0     stevel 
   1599      0     stevel /*
   1600      0     stevel  * fill_patt
   1601      0     stevel  * Fill the disk with user/sector number pattern.
   1602      0     stevel  */
   1603    251      lclee static void
   1604    251      lclee fill_patt(void)
   1605      0     stevel {
   1606    251      lclee 	int	*buff_ptr, i;
   1607   6549   bharding 	off_t	*off_ptr;
   1608      0     stevel 	int	io_fpatt = 0;
   1609      0     stevel 	int	io_ipatt = 0;
   1610      0     stevel 
   1611      0     stevel 	if (strncmp(io_fatt, "#", 1) != 0) {
   1612      0     stevel 		io_fpatt++;
   1613      0     stevel 		io_ipatt = strtoul(io_fatt, 0, 0);
   1614      0     stevel 		buff_ptr = (int *)Bootsect;
   1615      0     stevel 		for (i = 0; i < sectsiz; i += 4, buff_ptr++)
   1616   5169      lclee 			*buff_ptr = io_ipatt;
   1617      0     stevel 	}
   1618      0     stevel 
   1619      0     stevel 	/*
   1620      0     stevel 	 * Fill disk with pattern based on block number.
   1621      0     stevel 	 * Write to the disk at absolute relative block io_offset
   1622      0     stevel 	 * for io_size blocks.
   1623      0     stevel 	 */
   1624      0     stevel 	while (io_size--) {
   1625   6549   bharding 		off_ptr = (off_t *)Bootsect;
   1626      0     stevel 		if (!io_fpatt) {
   1627   6549   bharding 			for (i = 0; i < sectsiz;
   1628   6549   bharding 			    i += sizeof (off_t), off_ptr++)
   1629   6549   bharding 				*off_ptr = io_offset;
   1630      0     stevel 		}
   1631      0     stevel 		/* Write the data to disk */
   1632   6549   bharding 		if (lseek(Dev, (off_t)(sectsiz * io_offset++),
   1633   6549   bharding 		    SEEK_SET) == -1) {
   1634    251      lclee 			(void) fprintf(stderr, "fdisk: Error seeking on %s.\n",
   1635   5169      lclee 			    Dfltdev);
   1636      0     stevel 			exit(1);
   1637      0     stevel 		}
   1638      0     stevel 		if (write(Dev, Bootsect, sectsiz) != sectsiz) {
   1639    251      lclee 			(void) fprintf(stderr, "fdisk: Error writing %s.\n",
   1640   5169      lclee 			    Dfltdev);
   1641      0     stevel 			exit(1);
   1642      0     stevel 		}
   1643      0     stevel 	} /* while (--io_size); */
   1644      0     stevel }
   1645      0     stevel 
   1646      0     stevel /*
   1647      0     stevel  * abs_read
   1648      0     stevel  * Read from the disk at absolute relative block io_offset for
   1649      0     stevel  * io_size blocks. Write the data to standard ouput (-r).
   1650      0     stevel  */
   1651    251      lclee static void
   1652    251      lclee abs_read(void)
   1653    251      lclee {
   1654      0     stevel 	int c;
   1655      0     stevel 
   1656      0     stevel 	while (io_size--) {
   1657   6549   bharding 		if (lseek(Dev, (off_t)(sectsiz * io_offset++),
   1658   6549   bharding 		    SEEK_SET) == -1) {
   1659    251      lclee 			(void) fprintf(stderr, "fdisk: Error seeking on %s.\n",
   1660      0     stevel 			    Dfltdev);
   1661      0     stevel 			exit(1);
   1662      0     stevel 		}
   1663      0     stevel 		if (read(Dev, Bootsect, sectsiz) != sectsiz) {
   1664    251      lclee 			(void) fprintf(stderr, "fdisk: Error reading %s.\n",
   1665      0     stevel 			    Dfltdev);
   1666      0     stevel 			exit(1);
   1667      0     stevel 		}
   1668      0     stevel 
   1669      0     stevel 		/* Write to standard ouptut */
   1670    251      lclee 		if ((c = write(1, Bootsect, (unsigned)sectsiz)) != sectsiz) {
   1671      0     stevel 			if (c >= 0) {
   1672      0     stevel 				if (io_debug)
   1673    251      lclee 					(void) fprintf(stderr,
   1674    251      lclee 					    "fdisk: Output warning: %d of %d"
   1675    251      lclee 					    " characters written.\n",
   1676    251      lclee 					    c, sectsiz);
   1677      0     stevel 				exit(2);
   1678      0     stevel 			} else {
   1679      0     stevel 				perror("write error on output file.");
   1680      0     stevel 				exit(2);
   1681      0     stevel 			}
   1682      0     stevel 		} /* if ((c = write(1, Bootsect, (unsigned)sectsiz)) */
   1683      0     stevel 			/* != sectsiz) */
   1684      0     stevel 	} /* while (--io_size); */
   1685      0     stevel 	exit(0);
   1686      0     stevel }
   1687      0     stevel 
   1688      0     stevel /*
   1689      0     stevel  * abs_write
   1690      0     stevel  * Read the data from standard input. Write to the disk at
   1691      0     stevel  * absolute relative block io_offset for io_size blocks (-w).
   1692      0     stevel  */
   1693    251      lclee static void
   1694    251      lclee abs_write(void)
   1695      0     stevel {
   1696      0     stevel 	int c, i;
   1697      0     stevel 
   1698      0     stevel 	while (io_size--) {
   1699      0     stevel 		int part_exit = 0;
   1700      0     stevel 		/* Read from standard input */
   1701      0     stevel 		if ((c = read(0, Bootsect, (unsigned)sectsiz)) != sectsiz) {
   1702      0     stevel 			if (c >= 0) {
   1703      0     stevel 				if (io_debug)
   1704    251      lclee 				(void) fprintf(stderr,
   1705      0     stevel 				    "fdisk: WARNING: Incomplete read (%d of"
   1706      0     stevel 				    " %d characters read) on input file.\n",
   1707   5169      lclee 				    c, sectsiz);
   1708      0     stevel 				/* Fill pattern to mark partial sector in buf */
   1709      0     stevel 				for (i = c; i < sectsiz; ) {
   1710      0     stevel 					Bootsect[i++] = 0x41;
   1711      0     stevel 					Bootsect[i++] = 0x62;
   1712      0     stevel 					Bootsect[i++] = 0x65;
   1713      0     stevel 					Bootsect[i++] = 0;
   1714      0     stevel 				}
   1715      0     stevel 				part_exit++;
   1716      0     stevel 			} else {
   1717      0     stevel 				perror("read error on input file.");
   1718      0     stevel 				exit(2);
   1719      0     stevel 			}
   1720      0     stevel 
   1721      0     stevel 		}
   1722      0     stevel 		/* Write to disk drive */
   1723   6549   bharding 		if (lseek(Dev, (off_t)(sectsiz * io_offset++),
   1724   6549   bharding 		    SEEK_SET) == -1) {
   1725    251      lclee 			(void) fprintf(stderr, "fdisk: Error seeking on %s.\n",
   1726      0     stevel 			    Dfltdev);
   1727      0     stevel 			exit(1);
   1728      0     stevel 		}
   1729      0     stevel 		if (write(Dev, Bootsect, sectsiz) != sectsiz) {
   1730    251      lclee 			(void) fprintf(stderr, "fdisk: Error writing %s.\n",
   1731      0     stevel 			    Dfltdev);
   1732      0     stevel 			exit(1);
   1733      0     stevel 		}
   1734      0     stevel 		if (part_exit)
   1735      0     stevel 		exit(0);
   1736      0     stevel 	} /* while (--io_size); */
   1737      0     stevel 	exit(1);
   1738      0     stevel }
   1739      0     stevel 
   1740    251      lclee 
   1741      0     stevel /*
   1742      0     stevel  * load
   1743      0     stevel  * Load will either read the fdisk table from a file or add or
   1744      0     stevel  * delete an entry (-A, -D, -F).
   1745      0     stevel  */
   1746      0     stevel 
   1747    251      lclee static void
   1748    251      lclee load(int funct, char *file)
   1749      0     stevel {
   1750      0     stevel 	int	id;
   1751      0     stevel 	int	act;
   1752      0     stevel 	int	bhead;
   1753      0     stevel 	int	bsect;
   1754      0     stevel 	int	bcyl;
   1755      0     stevel 	int	ehead;
   1756      0     stevel 	int	esect;
   1757      0     stevel 	int	ecyl;
   1758   7563     Prasad 	uint32_t	rsect;
   1759   7563     Prasad 	uint32_t	numsect;
   1760      0     stevel 	char	line[256];
   1761      0     stevel 	int	i = 0;
   1762      0     stevel 	int	j;
   1763      0     stevel 	FILE *fp;
   1764  10021  Sheshadri #ifdef i386
   1765  10021  Sheshadri 	int 	ext_part_present = 0;
   1766  10021  Sheshadri 	uint32_t	begsec, endsec, relsect;
   1767  10021  Sheshadri 	logical_drive_t *temp;
   1768  10021  Sheshadri 	int part_count = 0, ldcnt = 0;
   1769  10021  Sheshadri 	uint32_t ext_beg_sec, ext_end_sec;
   1770  10021  Sheshadri 	uint32_t old_ext_beg_sec = 0, old_ext_num_sec = 0;
   1771  10021  Sheshadri 	uint32_t new_ext_beg_sec = 0, new_ext_num_sec = 0;
   1772  10021  Sheshadri 	int ext_part_inited = 0;
   1773  10021  Sheshadri 	uchar_t	systid;
   1774  10021  Sheshadri #endif
   1775      0     stevel 
   1776      0     stevel 	switch (funct) {
   1777      0     stevel 
   1778   5169      lclee 	case LOADFILE:
   1779      0     stevel 
   1780      0     stevel 		/*
   1781      0     stevel 		 * Zero out the table before loading it, which will
   1782      0     stevel 		 * force it to be updated on disk later (-F
   1783      0     stevel 		 * fdisk_file).
   1784      0     stevel 		 */
   1785      0     stevel 		nulltbl();
   1786      0     stevel 
   1787      0     stevel 		/* Open the prototype file */
   1788      0     stevel 		if ((fp = fopen(file, "r")) == NULL) {
   1789      0     stevel 			(void) fprintf(stderr,
   1790      0     stevel 			    "fdisk: Cannot open prototype partition file %s.\n",
   1791      0     stevel 			    file);
   1792      0     stevel 			exit(1);
   1793      0     stevel 		}
   1794      0     stevel 
   1795      0     stevel 		/* Read a line from the file */
   1796      0     stevel 		while (fgets(line, sizeof (line) - 1, fp)) {
   1797      0     stevel 			if (pars_fdisk(line, &id, &act, &bhead, &bsect,
   1798      0     stevel 			    &bcyl, &ehead, &esect, &ecyl, &rsect, &numsect)) {
   1799      0     stevel 				continue;
   1800      0     stevel 			}
   1801  10021  Sheshadri #ifdef i386
   1802  10021  Sheshadri 			part_count++;
   1803  10021  Sheshadri 
   1804  10021  Sheshadri 			if (fdisk_is_dos_extended((uchar_t)id)) {
   1805  10021  Sheshadri 				if (ext_part_present) {
   1806  10021  Sheshadri 					fprintf(stderr, "Extended partition"
   1807  10021  Sheshadri 					    " already exists\n");
   1808  10021  Sheshadri 					fprintf(stderr, "fdisk: Error on"
   1809  10021  Sheshadri 					    " entry \"%s\".\n", line);
   1810  10021  Sheshadri 					exit(1);
   1811  10021  Sheshadri 				}
   1812  10021  Sheshadri 				ext_part_present = 1;
   1813  10021  Sheshadri 				/*
   1814  10021  Sheshadri 				 * If the existing extended partition's start
   1815  10021  Sheshadri 				 * and size matches the new one, do not
   1816  10021  Sheshadri 				 * initialize the extended partition EBR
   1817  10021  Sheshadri 				 * (Extended Boot Record) because there could
   1818  10021  Sheshadri 				 * be existing logical drives.
   1819  10021  Sheshadri 				 */
   1820  10021  Sheshadri 				for (i = 0; i < FD_NUMPART; i++) {
   1821  10021  Sheshadri 					systid = Old_Table[i].systid;
   1822  10021  Sheshadri 					if (fdisk_is_dos_extended(systid)) {
   1823  10021  Sheshadri 						old_ext_beg_sec =
   1824  10021  Sheshadri 						    Old_Table[i].relsect;
   1825  10021  Sheshadri 						old_ext_num_sec =
   1826  10021  Sheshadri 						    Old_Table[i].numsect;
   1827  10021  Sheshadri 						break;
   1828  10021  Sheshadri 					}
   1829  10021  Sheshadri 				}
   1830  10021  Sheshadri 				new_ext_beg_sec = rsect;
   1831  10021  Sheshadri 				new_ext_num_sec = numsect;
   1832  10021  Sheshadri 				if ((old_ext_beg_sec != new_ext_beg_sec) ||
   1833  10021  Sheshadri 				    (old_ext_num_sec != new_ext_num_sec)) {
   1834  10021  Sheshadri 					fdisk_init_ext_part(epp,
   1835  10021  Sheshadri 					    new_ext_beg_sec, new_ext_num_sec);
   1836  10021  Sheshadri 					ext_part_inited = 1;
   1837  10021  Sheshadri 				}
   1838  10021  Sheshadri 			}
   1839  10021  Sheshadri 
   1840  10021  Sheshadri 			if (part_count > FD_NUMPART) {
   1841  10021  Sheshadri 				/* This line should be logical drive info */
   1842  10021  Sheshadri 				int offset = MAX_LOGDRIVE_OFFSET;
   1843  10021  Sheshadri 				if (!ext_part_present) {
   1844  10021  Sheshadri 					/* Erroneous input file */
   1845  10021  Sheshadri 					fprintf(stderr, "More than 4 primary"
   1846  10021  Sheshadri 					    " partitions found in input\n");
   1847  10021  Sheshadri 					fprintf(stderr, "Exiting...\n");
   1848  10021  Sheshadri 					exit(1);
   1849  10021  Sheshadri 				}
   1850  10021  Sheshadri 
   1851  10021  Sheshadri 				if (numsect == 0) {
   1852  10021  Sheshadri 					continue;
   1853  10021  Sheshadri 				}
   1854  10021  Sheshadri 
   1855  10021  Sheshadri 				/*
   1856  10021  Sheshadri 				 * If the start and size of the existing
   1857  10021  Sheshadri 				 * extended partition matches the new one and
   1858  10021  Sheshadri 				 * new logical drives are being defined via
   1859  10021  Sheshadri 				 * the input file, initialize the EBR.
   1860  10021  Sheshadri 				 */
   1861  10021  Sheshadri 				if (!ext_part_inited) {
   1862  10021  Sheshadri 					fdisk_init_ext_part(epp,
   1863  10021  Sheshadri 					    new_ext_beg_sec, new_ext_num_sec);
   1864  10021  Sheshadri 					ext_part_inited = 1;
   1865  10021  Sheshadri 				}
   1866  10021  Sheshadri 
   1867  10021  Sheshadri 				begsec = rsect - offset;
   1868  10021  Sheshadri 				if ((ldcnt =
   1869  10021  Sheshadri 				    fdisk_get_logical_drive_count(epp)) == 0) {
   1870  10021  Sheshadri 					/* Adding the first logical drive */
   1871  10021  Sheshadri 					/*
   1872  10021  Sheshadri 					 * Make sure that begsec doesnt wrap
   1873  10021  Sheshadri 					 * around. This can happen if rsect is
   1874  10021  Sheshadri 					 * less than offset.
   1875  10021  Sheshadri 					 */
   1876  10021  Sheshadri 					if (rsect < offset) {
   1877  10021  Sheshadri 						fprintf(stderr, "Minimum of "
   1878  10021  Sheshadri 						    "63 free sectors required "
   1879  10021  Sheshadri 						    "before the beginning of "
   1880  10021  Sheshadri 						    "a logical drive.");
   1881  10021  Sheshadri 						exit(1);
   1882  10021  Sheshadri 					}
   1883  10021  Sheshadri 					/*
   1884  10021  Sheshadri 					 * Check if the first logical drive
   1885  10021  Sheshadri 					 * is out of order. In that case, do
   1886  10021  Sheshadri 					 * not subtract MAX_LOGDRIVE_OFFSET
   1887  10021  Sheshadri 					 * from the given start of partition.
   1888  10021  Sheshadri 					 */
   1889  10021  Sheshadri 					if (begsec != new_ext_beg_sec) {
   1890  10021  Sheshadri 						begsec = rsect;
   1891  10021  Sheshadri 						offset = 0;
   1892  10021  Sheshadri 					}
   1893  10021  Sheshadri 				}
   1894  10021  Sheshadri 				if (ldcnt >= MAX_EXT_PARTS) {
   1895  10021  Sheshadri 					fprintf(stderr, "\nError : Number of "
   1896  10021  Sheshadri 					    "logical drives exceeds limit of "
   1897  10021  Sheshadri 					    "%d.\n", MAX_EXT_PARTS);
   1898  10021  Sheshadri 					exit(1);
   1899  10021  Sheshadri 				}
   1900  10021  Sheshadri 
   1901  10021  Sheshadri 				if (id > FDISK_MAX_VALID_PART_ID) {
   1902  10021  Sheshadri 					fprintf(stderr, "Invalid partition "
   1903  10021  Sheshadri 					    "ID\n");
   1904  10021  Sheshadri 					fprintf(stderr, "fdisk: Error on"
   1905  10021  Sheshadri 					    " entry \"%s\".\n", line);
   1906  10021  Sheshadri 					exit(1);
   1907  10021  Sheshadri 				}
   1908  10021  Sheshadri 
   1909  10021  Sheshadri 				endsec = rsect + numsect - 1;
   1910  10021  Sheshadri 				if (fdisk_validate_logical_drive(epp,
   1911  10021  Sheshadri 				    begsec, offset, numsect) == 0) {
   1912  10021  Sheshadri 					if (id == EFI_PMBR) {
   1913  10021  Sheshadri 						fprintf(stderr, "EFI "
   1914  10021  Sheshadri 						    "partitions not supported "
   1915  10021  Sheshadri 						    "inside extended "
   1916  10021  Sheshadri 						    "partition\n");
   1917  10021  Sheshadri 						exit(1);
   1918  10021  Sheshadri 					}
   1919  10021  Sheshadri 					fdisk_add_logical_drive(epp, begsec,
   1920  10021  Sheshadri 					    endsec, id);
   1921  10021  Sheshadri 					continue;
   1922  10021  Sheshadri 				} else {
   1923  10021  Sheshadri 					fprintf(stderr, "fdisk: Error on"
   1924  10021  Sheshadri 					    " entry \"%s\".\n", line);
   1925  10021  Sheshadri 					exit(1);
   1926  10021  Sheshadri 				}
   1927  10021  Sheshadri 			}
   1928  10021  Sheshadri #endif
   1929      0     stevel 
   1930      0     stevel 			/*
   1931      0     stevel 			 * Validate the partition. It cannot start at sector
   1932      0     stevel 			 * 0 unless it is UNUSED or already exists
   1933      0     stevel 			 */
   1934      0     stevel 			if (validate_part(id, rsect, numsect) < 0) {
   1935      0     stevel 				(void) fprintf(stderr,
   1936      0     stevel 				    "fdisk: Error on entry \"%s\".\n",
   1937      0     stevel 				    line);
   1938      0     stevel 				exit(1);
   1939      0     stevel 			}
   1940   8904      Barry 
   1941   8904      Barry 			if (entry_from_old_table(id, act, bhead, bsect,
   1942   8904      Barry 			    bcyl, ehead, esect, ecyl, rsect, numsect)) {
   1943   8904      Barry 				/*
   1944   8904      Barry 				 * If we got here it means we copied an
   1945   8904      Barry 				 * unmodified entry. So there is no need
   1946   8904      Barry 				 * to insert it in the table or do any
   1947   8904      Barry 				 * checks against disk size.
   1948   8904      Barry 				 *
   1949   8904      Barry 				 * This is a work around on the following
   1950   8904      Barry 				 * situation (for IDE disks, at least):
   1951   8904      Barry 				 * Different operation systems calculate
   1952   8904      Barry 				 * disk size different ways, of which there
   1953   8904      Barry 				 * are two main ways.
   1954   8904      Barry 				 *
   1955   8904      Barry 				 * The first, rounds the disk size to modulo
   1956   8904      Barry 				 * cylinder size (virtual made-up cylinder
   1957   8904      Barry 				 * usually based on maximum number of heads
   1958   8904      Barry 				 * and sectors in partition table fields).
   1959   8904      Barry 				 * Our OS's (for IDE) and most other "Unix"
   1960   8904      Barry 				 * type OS's do this.
   1961   8904      Barry 				 *
   1962   8904      Barry 				 * The second, uses every single block
   1963   8904      Barry 				 * on the disk (to maximize available space).
   1964   8904      Barry 				 * Since disk manufactures do not know about
   1965   8904      Barry 				 * "virtual cylinders", there are some number
   1966   8904      Barry 				 * of blocks that make up a partial cylinder
   1967   8904      Barry 				 * at the end of the disk.
   1968   8904      Barry 				 *
   1969   8904      Barry 				 * The difference between these two methods
   1970   8904      Barry 				 * is where the problem is. When one
   1971   8904      Barry 				 * tries to install Solaris/OpenSolaris on
   1972   8904      Barry 				 * a disk that has another OS using that
   1973   8904      Barry 				 * "partial cylinder", install fails. It fails
   1974   8904      Barry 				 * since fdisk thinks its asked to create a
   1975   8904      Barry 				 * partition with the -F option that contains
   1976   8904      Barry 				 * a partition that runs off the end of the
   1977   8904      Barry 				 * disk.
   1978   8904      Barry 				 */
   1979   8904      Barry 				continue;
   1980   8904      Barry 			}
   1981   8904      Barry 
   1982      0     stevel 			/*
   1983      0     stevel 			 * Find an unused entry to use and put the entry
   1984      0     stevel 			 * in table
   1985      0     stevel 			 */
   1986      0     stevel 			if (insert_tbl(id, act, bhead, bsect, bcyl, ehead,
   1987      0     stevel 			    esect, ecyl, rsect, numsect) < 0) {
   1988      0     stevel 				(void) fprintf(stderr,
   1989      0     stevel 				    "fdisk: Error on entry \"%s\".\n",
   1990      0     stevel 				    line);
   1991      0     stevel 				exit(1);
   1992      0     stevel 			}
   1993      0     stevel 		} /* while (fgets(line, sizeof (line) - 1, fp)) */
   1994      0     stevel 
   1995      0     stevel 		if (verify_tbl() < 0) {
   1996    251      lclee 			(void) fprintf(stderr,
   1997      0     stevel 			    "fdisk: Cannot create partition table\n");
   1998      0     stevel 			exit(1);
   1999      0     stevel 		}
   2000      0     stevel 
   2001    251      lclee 		(void) fclose(fp);
   2002      0     stevel 		return;
   2003      0     stevel 
   2004   5169      lclee 	case LOADDEL:
   2005      0     stevel 
   2006      0     stevel 		/* Parse the user-supplied deletion line (-D) */
   2007    251      lclee 		if (pars_fdisk(file, &id, &act, &bhead, &bsect, &bcyl,
   2008    251      lclee 		    &ehead, &esect, &ecyl, &rsect, &numsect)) {
   2009    251      lclee 			(void) fprintf(stderr,
   2010    251      lclee 			    "fdisk: Syntax error \"%s\"\n", file);
   2011    251      lclee 			exit(1);
   2012    251      lclee 		}
   2013      0     stevel 
   2014      0     stevel 		/* Find the exact entry in the table */
   2015      0     stevel 		for (i = 0; i < FD_NUMPART; i++) {
   2016      0     stevel 			if (Table[i].systid == id &&
   2017      0     stevel 			    Table[i].bootid == act &&
   2018      0     stevel 			    Table[i].beghead == bhead &&
   2019      0     stevel 			    Table[i].begsect == ((bsect & 0x3f) |
   2020   5169      lclee 			    (uchar_t)((bcyl>>2) & 0xc0)) &&
   2021    251      lclee 			    Table[i].begcyl == (uchar_t)(bcyl & 0xff) &&
   2022      0     stevel 			    Table[i].endhead == ehead &&
   2023      0     stevel 			    Table[i].endsect == ((esect & 0x3f) |
   2024   5169      lclee 			    (uchar_t)((ecyl>>2) & 0xc0)) &&
   2025    251      lclee 			    Table[i].endcyl == (uchar_t)(ecyl & 0xff) &&
   2026  10021  Sheshadri 			    Table[i].relsect == LE_32(rsect) &&
   2027  10021  Sheshadri 			    Table[i].numsect == LE_32(numsect)) {
   2028      0     stevel 
   2029      0     stevel 				/*
   2030      0     stevel 				 * Found the entry. Now move rest of
   2031      0     stevel 				 * entries up toward the top of the
   2032      0     stevel 				 * table, leaving available entries at
   2033      0     stevel 				 * the end of the fdisk table.
   2034      0     stevel 				 */
   2035    251      lclee 				for (j = i; j < FD_NUMPART - 1; j++) {
   2036    251      lclee 					Table[j].systid = Table[j + 1].systid;
   2037    251      lclee 					Table[j].bootid = Table[j + 1].bootid;
   2038    251      lclee 					Table[j].beghead = Table[j + 1].beghead;
   2039    251      lclee 					Table[j].begsect = Table[j + 1].begsect;
   2040    251      lclee 					Table[j].begcyl = Table[j + 1].begcyl;
   2041    251      lclee 					Table[j].endhead = Table[j + 1].endhead;
   2042    251      lclee 					Table[j].endsect = Table[j + 1].endsect;
   2043    251      lclee 					Table[j].endcyl = Table[j + 1].endcyl;
   2044    251      lclee 					Table[j].relsect = Table[j + 1].relsect;
   2045    251      lclee 					Table[j].numsect = Table[j + 1].numsect;
   2046      0     stevel 				}
   2047      0     stevel 
   2048      0     stevel 				/*
   2049      0     stevel 				 * Mark the last entry as unused in case
   2050      0     stevel 				 * all table entries were in use prior
   2051      0     stevel 				 * to the deletion.
   2052      0     stevel 				 */
   2053      0     stevel 
   2054    251      lclee 				Table[FD_NUMPART - 1].systid = UNUSED;
   2055    251      lclee 				Table[FD_NUMPART - 1].bootid = 0;
   2056  10021  Sheshadri #ifdef i386
   2057  10021  Sheshadri 				if (fdisk_is_dos_extended(id)) {
   2058  10021  Sheshadri 					fdisk_delete_ext_part(epp);
   2059  10021  Sheshadri 				}
   2060  10021  Sheshadri #endif
   2061  10021  Sheshadri 				return;
   2062  10021  Sheshadri 			}
   2063  10021  Sheshadri 		}
   2064  10021  Sheshadri 
   2065  10021  Sheshadri #ifdef i386
   2066  10021  Sheshadri 		ldcnt = FD_NUMPART + 1;
   2067  10021  Sheshadri 		for (temp = fdisk_get_ld_head(epp); temp != NULL;
   2068  10021  Sheshadri 		    temp = temp->next) {
   2069  10021  Sheshadri 			relsect = temp->abs_secnum + temp->logdrive_offset;
   2070  10021  Sheshadri 			if (temp->parts[0].systid == id &&
   2071  10021  Sheshadri 			    temp->parts[0].bootid == act &&
   2072  10021  Sheshadri 			    temp->parts[0].beghead == bhead &&
   2073  10021  Sheshadri 			    temp->parts[0].begsect == ((bsect & 0x3f) |
   2074  10021  Sheshadri 			    (uchar_t)((bcyl>>2) & 0xc0)) &&
   2075  10021  Sheshadri 			    temp->parts[0].begcyl == (uchar_t)(bcyl & 0xff) &&
   2076  10021  Sheshadri 			    temp->parts[0].endhead == ehead &&
   2077  10021  Sheshadri 			    temp->parts[0].endsect == ((esect & 0x3f) |
   2078  10021  Sheshadri 			    (uchar_t)((ecyl>>2) & 0xc0)) &&
   2079  10021  Sheshadri 			    temp->parts[0].endcyl == (uchar_t)(ecyl & 0xff) &&
   2080  10021  Sheshadri 			    relsect == LE_32(rsect) &&
   2081  10021  Sheshadri 			    temp->parts[0].numsect == LE_32(numsect)) {
   2082  10021  Sheshadri 				fdisk_delete_logical_drive(epp, ldcnt);
   2083  10021  Sheshadri 				return;
   2084  10021  Sheshadri 			}
   2085  10021  Sheshadri 			ldcnt++;
   2086  10021  Sheshadri 		}
   2087  10021  Sheshadri #endif
   2088  10021  Sheshadri 
   2089    251      lclee 		(void) fprintf(stderr,
   2090      0     stevel 		    "fdisk: Entry does not match any existing partition:\n"
   2091      0     stevel 		    "	\"%s\"\n",
   2092      0     stevel 		    file);
   2093      0     stevel 		exit(1);
   2094   8333   Suhasini 		/* FALLTHRU */
   2095      0     stevel 
   2096   5169      lclee 	case LOADADD:
   2097      0     stevel 
   2098      0     stevel 		/* Parse the user-supplied addition line (-A) */
   2099    251      lclee 		if (pars_fdisk(file, &id, &act, &bhead, &bsect, &bcyl, &ehead,
   2100    251      lclee 		    &esect, &ecyl, &rsect, &numsect)) {
   2101    251      lclee 			(void) fprintf(stderr,
   2102    251      lclee 			    "fdisk: Syntax error \"%s\"\n", file);
   2103    251      lclee 			exit(1);
   2104    251      lclee 		}
   2105      0     stevel 
   2106      0     stevel 		/* Validate the partition. It cannot start at sector 0 */
   2107      0     stevel 		if (rsect == 0) {
   2108      0     stevel 			(void) fprintf(stderr,
   2109      0     stevel 			    "fdisk: New partition cannot start at sector 0:\n"
   2110      0     stevel 			    "   \"%s\".\n",
   2111      0     stevel 			    file);
   2112      0     stevel 			exit(1);
   2113      0     stevel 		}
   2114      0     stevel 
   2115      0     stevel 		/*
   2116      0     stevel 		 * if the user wishes to add an EFI partition, we need
   2117      0     stevel 		 * more extensive validation.  rsect should be 1, and
   2118      0     stevel 		 * numsect should equal the entire disk capacity - 1
   2119      0     stevel 		 */
   2120      0     stevel 
   2121      0     stevel 		if (id == EFI_PMBR) {
   2122      0     stevel 			if (rsect != 1) {
   2123      0     stevel 				(void) fprintf(stderr,
   2124      0     stevel 				    "fdisk: EFI partitions must start at sector"
   2125      0     stevel 				    " 1 (input rsect = %d)\n", rsect);
   2126      0     stevel 				exit(1);
   2127      0     stevel 			}
   2128      0     stevel 
   2129   7563     Prasad 
   2130   7563     Prasad 			if (dev_capacity > DK_MAX_2TB) {
   2131   7563     Prasad 				if (numsect != DK_MAX_2TB) {
   2132   7563     Prasad 					(void) fprintf(stderr,
   2133   7563     Prasad 					    "fdisk: EFI partitions must "
   2134   7563     Prasad 					    "encompass the entire maximum 2 TB "
   2135   7563     Prasad 					    "(input numsect: %u - max: %llu)\n",
   2136   7563     Prasad 					    numsect, (diskaddr_t)DK_MAX_2TB);
   2137   7563     Prasad 				exit(1);
   2138   7563     Prasad 				}
   2139   7563     Prasad 			} else if (numsect != dev_capacity - 1) {
   2140      0     stevel 				(void) fprintf(stderr,
   2141      0     stevel 				    "fdisk: EFI partitions must encompass the "
   2142    251      lclee 				    "entire disk\n"
   2143   7563     Prasad 				    "(input numsect: %u - avail: %llu)\n",
   2144    251      lclee 				    numsect,
   2145   5169      lclee 				    dev_capacity - 1);
   2146      0     stevel 				exit(1);
   2147      0     stevel 			}
   2148      0     stevel 		}
   2149   8254  Sheshadri 
   2150  10021  Sheshadri #ifdef i386
   2151  10021  Sheshadri 		if (id > FDISK_MAX_VALID_PART_ID) {
   2152  10021  Sheshadri 			printf("Invalid partition ID\n");
   2153  10021  Sheshadri 			exit(1);
   2154  10021  Sheshadri 		}
   2155  10021  Sheshadri 
   2156  10021  Sheshadri 		if ((fdisk_ext_part_exists(epp)) &&
   2157  10021  Sheshadri 		    (fdisk_is_dos_extended(id))) {
   2158  10021  Sheshadri 			(void) fprintf(stderr,
   2159  10021  Sheshadri 			    "Extended partition already exists.\n");
   2160  10021  Sheshadri 			(void) fprintf(stderr,
   2161  10021  Sheshadri 			    "fdisk: Invalid entry could not be "
   2162  10021  Sheshadri 			    "inserted:\n        \"%s\"\n", file);
   2163  10021  Sheshadri 			exit(1);
   2164  10021  Sheshadri 		}
   2165  10021  Sheshadri 
   2166  10021  Sheshadri 		if (fdisk_ext_part_exists(epp) &&
   2167  10021  Sheshadri 		    (rsect >= (ext_beg_sec = fdisk_get_ext_beg_sec(epp))) &&
   2168  10021  Sheshadri 		    (rsect <= (ext_end_sec = fdisk_get_ext_end_sec(epp)))) {
   2169  10021  Sheshadri 			int offset = MAX_LOGDRIVE_OFFSET;
   2170  10021  Sheshadri 
   2171  10021  Sheshadri 			/*
   2172  10021  Sheshadri 			 * Make sure that begsec doesnt wrap around.
   2173  10021  Sheshadri 			 * This can happen if rsect is less than offset
   2174  10021  Sheshadri 			 */
   2175  10021  Sheshadri 			if (rsect < offset) {
   2176  10021  Sheshadri 				return;
   2177  10021  Sheshadri 			}
   2178  10021  Sheshadri 			begsec = rsect - offset;
   2179  10021  Sheshadri 			if ((ldcnt = fdisk_get_logical_drive_count(epp)) == 0) {
   2180  10021  Sheshadri 				/*
   2181  10021  Sheshadri 				 * Adding the first logical drive
   2182  10021  Sheshadri 				 * Check if the first logical drive
   2183  10021  Sheshadri 				 * is out of order. In that case, do
   2184  10021  Sheshadri 				 * not subtract MAX_LOGDRIVE_OFFSET
   2185  10021  Sheshadri 				 * from the given start of partition.
   2186  10021  Sheshadri 				 */
   2187  10021  Sheshadri 				if (begsec != ext_beg_sec) {
   2188  10021  Sheshadri 					begsec = rsect;
   2189  10021  Sheshadri 					offset = 0;
   2190  10021  Sheshadri 				}
   2191  10021  Sheshadri 			}
   2192  10021  Sheshadri 
   2193  10021  Sheshadri 			if (ldcnt >= MAX_EXT_PARTS) {
   2194  10021  Sheshadri 				printf("\nNumber of logical drives exceeds "
   2195  10021  Sheshadri 				    "limit of %d.\n", MAX_EXT_PARTS);
   2196  10021  Sheshadri 				printf("Failing further additions.\n");
   2197  10021  Sheshadri 				exit(1);
   2198  10021  Sheshadri 			}
   2199  10021  Sheshadri 
   2200  10021  Sheshadri 			if (numsect == 0) {
   2201  10021  Sheshadri 				(void) fprintf(stderr,
   2202  10021  Sheshadri 				    "fdisk: Partition size cannot be zero:\n"
   2203  10021  Sheshadri 				    "   \"%s\".\n",
   2204  10021  Sheshadri 				    file);
   2205  10021  Sheshadri 				exit(1);
   2206  10021  Sheshadri 			}
   2207  10021  Sheshadri 			endsec = rsect + numsect - 1;
   2208  10021  Sheshadri 			if (fdisk_validate_logical_drive(epp, begsec,
   2209  10021  Sheshadri 			    offset, numsect) == 0) {
   2210  10021  Sheshadri 				/* Valid logical drive */
   2211  10021  Sheshadri 				fdisk_add_logical_drive(epp, begsec, endsec,
   2212  10021  Sheshadri 				    id);
   2213  10021  Sheshadri 				return;
   2214  10682  Sheshadri 			} else {
   2215  10682  Sheshadri 				(void) fprintf(stderr,
   2216  10682  Sheshadri 				    "fdisk: Invalid entry could not be "
   2217  10682  Sheshadri 				    "inserted:\n        \"%s\"\n", file);
   2218  10682  Sheshadri 				exit(1);
   2219  10021  Sheshadri 			}
   2220  10021  Sheshadri 		}
   2221  10021  Sheshadri #endif
   2222  10021  Sheshadri 
   2223      0     stevel 		/* Find unused entry for use and put entry in table */
   2224      0     stevel 		if (insert_tbl(id, act, bhead, bsect, bcyl, ehead, esect,
   2225      0     stevel 		    ecyl, rsect, numsect) < 0) {
   2226      0     stevel 			(void) fprintf(stderr,
   2227      0     stevel 			    "fdisk: Invalid entry could not be inserted:\n"
   2228      0     stevel 			    "	\"%s\"\n",
   2229      0     stevel 			    file);
   2230      0     stevel 			exit(1);
   2231      0     stevel 		}
   2232      0     stevel 
   2233      0     stevel 		/* Make sure new entry does not overlap existing entry */
   2234      0     stevel 		if (verify_tbl() < 0) {
   2235    251      lclee 			(void) fprintf(stderr,
   2236    251      lclee 			    "fdisk: Cannot create partition \"%s\"\n", file);
   2237      0     stevel 			exit(1);
   2238      0     stevel 		}
   2239      0     stevel 	} /* switch funct */
   2240      0     stevel }
   2241      0     stevel 
   2242      0     stevel /*
   2243      0     stevel  * Set_Table_CHS_Values
   2244      0     stevel  *
   2245      0     stevel  * This will calculate the CHS values for beginning and ending CHS
   2246      0     stevel  * for a single partition table entry (ti) based on the relsect
   2247      0     stevel  * and numsect values contained in the partion table entry.
   2248      0     stevel  *
   2249      0     stevel  * hba_heads and hba_sectors contain the number of heads and sectors.
   2250      0     stevel  *
   2251      0     stevel  * If the number of cylinders exceeds the MAX_CYL,
   2252      0     stevel  * then maximum values will be placed in the corresponding chs entry.
   2253      0     stevel  */
   2254      0     stevel static void
   2255      0     stevel Set_Table_CHS_Values(int ti)
   2256      0     stevel {
   2257      0     stevel 	uint32_t	lba, cy, hd, sc;
   2258      0     stevel 
   2259      0     stevel 	lba = (uint32_t)Table[ti].relsect;
   2260      0     stevel 	if (lba >= hba_heads * hba_sectors * MAX_CYL) {
   2261      0     stevel 		/*
   2262      0     stevel 		 * the lba address cannot be expressed in CHS value
   2263      0     stevel 		 * so store the maximum CHS field values in the CHS fields.
   2264      0     stevel 		 */
   2265      0     stevel 		cy = MAX_CYL + 1;
   2266      0     stevel 		hd = MAX_HEAD;
   2267      0     stevel 		sc = MAX_SECT;
   2268      0     stevel 	} else {
   2269      0     stevel 		cy = lba / hba_sectors / hba_heads;
   2270      0     stevel 		hd = lba / hba_sectors % hba_heads;
   2271      0     stevel 		sc = lba % hba_sectors + 1;
   2272      0     stevel 	}
   2273      0     stevel 	Table[ti].begcyl = cy & 0xff;
   2274    251      lclee 	Table[ti].beghead = (uchar_t)hd;
   2275    251      lclee 	Table[ti].begsect = (uchar_t)(((cy >> 2) & 0xc0) | sc);
   2276      0     stevel 
   2277      0     stevel 	/*
   2278      0     stevel 	 * This code is identical to the code above
   2279      0     stevel 	 * except that it works on ending CHS values
   2280      0     stevel 	 */
   2281      0     stevel 	lba = (uint32_t)(Table[ti].relsect + Table[ti].numsect - 1);
   2282      0     stevel 	if (lba >= hba_heads * hba_sectors * MAX_CYL) {
   2283      0     stevel 		cy = MAX_CYL + 1;
   2284      0     stevel 		hd = MAX_HEAD;
   2285      0     stevel 		sc = MAX_SECT;
   2286      0     stevel 	} else {
   2287      0     stevel 		cy = lba / hba_sectors / hba_heads;
   2288      0     stevel 		hd = lba / hba_sectors % hba_heads;
   2289      0     stevel 		sc = lba % hba_sectors + 1;
   2290      0     stevel 	}
   2291      0     stevel 	Table[ti].endcyl = cy & 0xff;
   2292    251      lclee 	Table[ti].endhead = (uchar_t)hd;
   2293    251      lclee 	Table[ti].endsect = (uchar_t)(((cy >> 2) & 0xc0) | sc);
   2294      0     stevel }
   2295      0     stevel 
   2296      0     stevel /*
   2297      0     stevel  * insert_tbl
   2298      0     stevel  * 	Insert entry into fdisk table. Check all user-supplied values
   2299      0     stevel  *	for the entry, but not the validity relative to other table
   2300      0     stevel  *	entries!
   2301      0     stevel  */
   2302    251      lclee static int
   2303    251      lclee insert_tbl(
   2304    251      lclee     int id, int act,
   2305    251      lclee     int bhead, int bsect, int bcyl,
   2306    251      lclee     int ehead, int esect, int ecyl,
   2307   7563     Prasad     uint32_t rsect, uint32_t numsect)
   2308      0     stevel {
   2309      0     stevel 	int	i;
   2310      0     stevel 
   2311      0     stevel 	/* validate partition size */
   2312   7563     Prasad 	if (((diskaddr_t)rsect + numsect) > dev_capacity) {
   2313    251      lclee 		(void) fprintf(stderr,
   2314      0     stevel 		    "fdisk: Partition table exceeds the size of the disk.\n");
   2315      0     stevel 		return (-1);
   2316      0     stevel 	}
   2317   7563     Prasad 
   2318      0     stevel 
   2319      0     stevel 	/* find UNUSED partition table entry */
   2320      0     stevel 	for (i = 0; i < FD_NUMPART; i++) {
   2321      0     stevel 		if (Table[i].systid == UNUSED) {
   2322      0     stevel 			break;
   2323      0     stevel 		}
   2324      0     stevel 	}
   2325      0     stevel 	if (i >= FD_NUMPART) {
   2326    251      lclee 		(void) fprintf(stderr, "fdisk: Partition table is full.\n");
   2327      0     stevel 		return (-1);
   2328      0     stevel 	}
   2329      0     stevel 
   2330      0     stevel 
   2331    251      lclee 	Table[i].systid = (uchar_t)id;
   2332    251      lclee 	Table[i].bootid = (uchar_t)act;
   2333  10021  Sheshadri 	Table[i].numsect = LE_32(numsect);
   2334  10021  Sheshadri 	Table[i].relsect = LE_32(rsect);
   2335      0     stevel 
   2336      0     stevel 	/*
   2337      0     stevel 	 * If we have been called with a valid geometry, use it
   2338      0     stevel 	 * valid means non-zero values that fit in the BIOS fields
   2339      0     stevel 	 */
   2340      0     stevel 	if (0 < bsect && bsect <= MAX_SECT &&
   2341      0     stevel 	    0 <= bhead && bhead <= MAX_HEAD &&
   2342      0     stevel 	    0 < esect && esect <= MAX_SECT &&
   2343      0     stevel 	    0 <= ehead && ehead <= MAX_HEAD) {
   2344      0     stevel 		if (bcyl > MAX_CYL)
   2345      0     stevel 			bcyl = MAX_CYL + 1;
   2346      0     stevel 		if (ecyl > MAX_CYL)
   2347      0     stevel 			ecyl = MAX_CYL + 1;
   2348      0     stevel 		Table[i].begcyl = bcyl & 0xff;
   2349      0     stevel 		Table[i].endcyl = ecyl & 0xff;
   2350    251      lclee 		Table[i].beghead = (uchar_t)bhead;
   2351    251      lclee 		Table[i].endhead = (uchar_t)ehead;
   2352    251      lclee 		Table[i].begsect = (uchar_t)(((bcyl >> 2) & 0xc0) | bsect);
   2353      0     stevel 		Table[i].endsect = ((ecyl >> 2) & 0xc0) | esect;
   2354      0     stevel 	} else {
   2355      0     stevel 
   2356      0     stevel 		/*
   2357      0     stevel 		 * The specified values are invalid,
   2358      0     stevel 		 * so calculate the values based on hba_heads, hba_sectors
   2359      0     stevel 		 */
   2360      0     stevel 		Set_Table_CHS_Values(i);
   2361      0     stevel 	}
   2362      0     stevel 
   2363      0     stevel 	/*
   2364      0     stevel 	 * return partition index
   2365      0     stevel 	 */
   2366      0     stevel 	return (i);
   2367      0     stevel }
   2368      0     stevel 
   2369      0     stevel /*
   2370   8904      Barry  * entry_from_old_table
   2371   8904      Barry  *	If the specified entry is in the old table and is not a Solaris entry
   2372   8904      Barry  *	then insert same entry into new fdisk table. If we do this then
   2373   8904      Barry  *	all checks are skipped for that entry!
   2374   8904      Barry  */
   2375   8904      Barry static int
   2376   8904      Barry entry_from_old_table(
   2377   8904      Barry     int id, int act,
   2378   8904      Barry     int bhead, int bsect, int bcyl,
   2379   8904      Barry     int ehead, int esect, int ecyl,
   2380   8904      Barry     uint32_t rsect, uint32_t numsect)
   2381   8904      Barry {
   2382   8904      Barry 	uint32_t	i, j;
   2383   8904      Barry 
   2384   8904      Barry 	if (id == SUNIXOS || id == SUNIXOS2)
   2385   8904      Barry 		return (0);
   2386  10015      Barry 	for (i = 0; i < FD_NUMPART; i++) {
   2387   8904      Barry 		if (Old_Table[i].systid == id &&
   2388   8904      Barry 		    Old_Table[i].bootid == act &&
   2389   8904      Barry 		    Old_Table[i].beghead == bhead &&
   2390   8904      Barry 		    Old_Table[i].begsect == ((bsect & 0x3f) |
   2391   8904      Barry 		    (uchar_t)((bcyl>>2) & 0xc0)) &&
   2392   8904      Barry 		    Old_Table[i].begcyl == (uchar_t)(bcyl & 0xff) &&
   2393   8904      Barry 		    Old_Table[i].endhead == ehead &&
   2394   8904      Barry 		    Old_Table[i].endsect == ((esect & 0x3f) |
   2395   8904      Barry 		    (uchar_t)((ecyl>>2) & 0xc0)) &&
   2396   8904      Barry 		    Old_Table[i].endcyl == (uchar_t)(ecyl & 0xff) &&
   2397   8904      Barry 		    Old_Table[i].relsect == lel(rsect) &&
   2398   8904      Barry 		    Old_Table[i].numsect == lel(numsect)) {
   2399   8904      Barry 			/* find UNUSED partition table entry */
   2400   8904      Barry 			for (j = 0; j < FD_NUMPART; j++) {
   2401   8904      Barry 				if (Table[j].systid == UNUSED) {
   2402   8904      Barry 					(void) memcpy(&Table[j], &Old_Table[i],
   2403   8904      Barry 					    sizeof (Table[0]));
   2404   8904      Barry 					skip_verify[j] = 1;
   2405   8904      Barry 					return (1);
   2406   8904      Barry 
   2407   8904      Barry 				}
   2408   8904      Barry 			}
   2409   8904      Barry 			return (0);
   2410   8904      Barry 		}
   2411   8904      Barry 
   2412   8904      Barry 	}
   2413   8904      Barry 	return (0);
   2414   8904      Barry }
   2415   8904      Barry 
   2416   8904      Barry /*
   2417      0     stevel  * verify_tbl
   2418      0     stevel  * Verify that no partition entries overlap or exceed the size of
   2419      0     stevel  * the disk.
   2420      0     stevel  */
   2421    251      lclee static int
   2422    251      lclee verify_tbl(void)
   2423      0     stevel {
   2424   7563     Prasad 	uint32_t	i, j, rsect, numsect;
   2425      0     stevel 	int	noMoreParts = 0;
   2426      0     stevel 	int	numParts = 0;
   2427      0     stevel 
   2428      0     stevel 	/* Make sure new entry does not overlap an existing entry */
   2429    251      lclee 	for (i = 0; i < FD_NUMPART - 1; i++) {
   2430      0     stevel 		if (Table[i].systid != UNUSED) {
   2431      0     stevel 			numParts++;
   2432      0     stevel 			/*
   2433      0     stevel 			 * No valid partitions allowed after an UNUSED  or
   2434      0     stevel 			 * EFI_PMBR part
   2435      0     stevel 			 */
   2436      0     stevel 			if (noMoreParts) {
   2437      0     stevel 				return (-1);
   2438      0     stevel 			}
   2439      0     stevel 
   2440      0     stevel 			/*
   2441      0     stevel 			 * EFI_PMBR partitions must be the only partition
   2442      0     stevel 			 * and must be Table entry 0
   2443      0     stevel 			 */
   2444      0     stevel 			if (Table[i].systid == EFI_PMBR) {
   2445      0     stevel 				if (i == 0) {
   2446      0     stevel 					noMoreParts = 1;
   2447      0     stevel 				} else {
   2448      0     stevel 					return (-1);
   2449      0     stevel 				}
   2450      0     stevel 
   2451      0     stevel 				if (Table[i].relsect != 1) {
   2452    251      lclee 					(void) fprintf(stderr, "ERROR: "
   2453      0     stevel 					    "Invalid starting sector "
   2454      0     stevel 					    "for EFI_PMBR partition:\n"
   2455      0     stevel 					    "relsect %d "
   2456      0     stevel 					    "(should be 1)\n",
   2457      0     stevel 					    Table[i].relsect);
   2458      0     stevel 
   2459      0     stevel 					return (-1);
   2460      0     stevel 				}
   2461      0     stevel 
   2462   5169      lclee 				if (Table[i].numsect != dev_capacity - 1) {
   2463    251      lclee 					(void) fprintf(stderr, "ERROR: "
   2464      0     stevel 					    "EFI_PMBR partition must "
   2465      0     stevel 					    "encompass the entire "
   2466    251      lclee 					    "disk.\n numsect %d - "
   2467   5169      lclee 					    "actual %llu\n",
   2468      0     stevel 					    Table[i].numsect,
   2469   5169      lclee 					    dev_capacity - 1);
   2470      0     stevel 
   2471      0     stevel 					return (-1);
   2472      0     stevel 				}
   2473      0     stevel 			}
   2474      0     stevel 
   2475      0     stevel 			/* make sure the partition isn't larger than the disk */
   2476  10021  Sheshadri 			rsect = LE_32(Table[i].relsect);
   2477  10021  Sheshadri 			numsect = LE_32(Table[i].numsect);
   2478   7563     Prasad 
   2479   7563     Prasad 			if ((((diskaddr_t)rsect + numsect) > dev_capacity) ||
   2480   7563     Prasad 			    (((diskaddr_t)rsect + numsect) > DK_MAX_2TB)) {
   2481   8904      Barry 				if (!skip_verify[i])
   2482   8904      Barry 					return (-1);
   2483      0     stevel 			}
   2484      0     stevel 
   2485    251      lclee 			for (j = i + 1; j < FD_NUMPART; j++) {
   2486      0     stevel 				if (Table[j].systid != UNUSED) {
   2487   7563     Prasad 					uint32_t t_relsect =
   2488  10021  Sheshadri 					    LE_32(Table[j].relsect);
   2489   7563     Prasad 					uint32_t t_numsect =
   2490  10021  Sheshadri 					    LE_32(Table[j].numsect);
   2491      0     stevel 
   2492      0     stevel 					if (noMoreParts) {
   2493    251      lclee 						(void) fprintf(stderr,
   2494      0     stevel 						    "Cannot add partition to "
   2495      0     stevel 						    "table; no more partitions "
   2496      0     stevel 						    "allowed\n");
   2497      0     stevel 
   2498      0     stevel 						if (io_debug) {
   2499    251      lclee 							(void) fprintf(stderr,
   2500      0     stevel 							    "DEBUG: Current "
   2501      0     stevel 							    "partition:\t"
   2502      0     stevel 							    "%d:%d:%d:%d:%d:"
   2503    251      lclee 							    "%d:%d:%d:%d:%d\n"
   2504      0     stevel 							    "       Next "
   2505      0     stevel 							    "partition:\t\t"
   2506      0     stevel 							    "%d:%d:%d:%d:%d:"
   2507    251      lclee 							    "%d:%d:%d:%d:%d\n",
   2508      0     stevel 							    Table[i].systid,
   2509      0     stevel 							    Table[i].bootid,
   2510      0     stevel 							    Table[i].begcyl,
   2511      0     stevel 							    Table[i].beghead,
   2512      0     stevel 							    Table[i].begsect,
   2513      0     stevel 							    Table[i].endcyl,
   2514      0     stevel 							    Table[i].endhead,
   2515      0     stevel 							    Table[i].endsect,
   2516      0     stevel 							    Table[i].relsect,
   2517      0     stevel 							    Table[i].numsect,
   2518      0     stevel 							    Table[j].systid,
   2519      0     stevel 							    Table[j].bootid,
   2520      0     stevel 							    Table[j].begcyl,
   2521      0     stevel 							    Table[j].beghead,
   2522      0     stevel 							    Table[j].begsect,
   2523      0     stevel 							    Table[j].endcyl,
   2524      0     stevel 							    Table[j].endhead,
   2525      0     stevel 							    Table[j].endsect,
   2526      0     stevel 							    Table[j].relsect,
   2527      0     stevel 							    Table[j].numsect);
   2528      0     stevel 						}
   2529      0     stevel 
   2530      0     stevel 						return (-1);
   2531      0     stevel 					}
   2532      0     stevel 					if ((rsect >=
   2533      0     stevel 					    (t_relsect + t_numsect)) ||
   2534    251      lclee 					    ((rsect + numsect) <= t_relsect)) {
   2535      0     stevel 						continue;
   2536      0     stevel 					} else {
   2537    251      lclee 						(void) fprintf(stderr, "ERROR: "
   2538      0     stevel 						    "current partition overlaps"
   2539      0     stevel 						    " following partition\n");
   2540      0     stevel 
   2541      0     stevel 						return (-1);
   2542      0     stevel 					}
   2543      0     stevel 				}
   2544      0     stevel 			}
   2545      0     stevel 		} else {
   2546      0     stevel 			noMoreParts = 1;
   2547      0     stevel 		}
   2548      0     stevel 	}
   2549      0     stevel 	if (Table[i].systid != UNUSED) {
   2550   8904      Barry 		if (noMoreParts)
   2551   8904      Barry 			return (-1);
   2552   8904      Barry 		if (!skip_verify[i] &&
   2553   8904      Barry 		    ((((diskaddr_t)lel(Table[i].relsect) +
   2554   8333   Suhasini 		    lel(Table[i].numsect)) > dev_capacity) ||
   2555   8333   Suhasini 		    (((diskaddr_t)lel(Table[i].relsect) +
   2556   8904      Barry 		    lel(Table[i].numsect)) > DK_MAX_2TB))) {
   2557      0     stevel 			return (-1);
   2558      0     stevel 		}
   2559      0     stevel 	}
   2560      0     stevel 
   2561      0     stevel 	return (numParts);
   2562      0     stevel }
   2563      0     stevel 
   2564      0     stevel /*
   2565      0     stevel  * pars_fdisk
   2566      0     stevel  * Parse user-supplied data to set up fdisk partitions
   2567      0     stevel  * (-A, -D, -F).
   2568      0     stevel  */
   2569    251      lclee static int
   2570    251      lclee pars_fdisk(
   2571    251      lclee     char *line,
   2572    251      lclee     int *id, int *act,
   2573    251      lclee     int *bhead, int *bsect, int *bcyl,
   2574    251      lclee     int *ehead, int *esect, int *ecyl,
   2575   7563     Prasad     uint32_t *rsect, uint32_t *numsect)
   2576      0     stevel {
   2577      0     stevel 	int	i;
   2578  10021  Sheshadri 	int64_t test;
   2579  10021  Sheshadri 	char *tok, *p;
   2580  10021  Sheshadri 	char buf[256];
   2581  10021  Sheshadri 
   2582      0     stevel 	if (line[0] == '\0' || line[0] == '\n' || line[0] == '*')
   2583   5169      lclee 		return (1);
   2584      0     stevel 	line[strlen(line)] = '\0';
   2585      0     stevel 	for (i = 0; i < strlen(line); i++) {
   2586      0     stevel 		if (line[i] == '\0') {
   2587      0     stevel 			break;
   2588      0     stevel 		} else if (line[i] == ':') {
   2589      0     stevel 			line[i] = ' ';
   2590      0     stevel 		}
   2591   8254  Sheshadri 	}
   2592  10021  Sheshadri 	strncpy(buf, line, 256);
   2593  10021  Sheshadri 	errno = 0;
   2594  10021  Sheshadri 	tok = strtok(buf, ": \t\n");
   2595  10021  Sheshadri 	while (tok != NULL) {
   2596  10021  Sheshadri 		for (p = tok; *p != '\0'; p++) {
   2597  10021  Sheshadri 			if (!isdigit(*p)) {
   2598  10021  Sheshadri 				printf("Invalid input %s in line %s.\n",
   2599  10021  Sheshadri 				    tok, line);
   2600  10021  Sheshadri 				exit(1);
   2601  10021  Sheshadri 			}
   2602  10021  Sheshadri 		}
   2603  10021  Sheshadri 
   2604  10021  Sheshadri 		test = strtoll(tok, (char **)NULL, 10);
   2605  10021  Sheshadri 		if ((test < 0) || (test > 0xFFFFFFFF) || (errno != 0)) {
   2606  10021  Sheshadri 			printf("Invalid input %s in line %s.\n", tok, line);
   2607  10021  Sheshadri 			exit(1);
   2608  10021  Sheshadri 		}
   2609  10021  Sheshadri 		tok = strtok(NULL, ": \t\n");
   2610  10021  Sheshadri 	}
   2611   7563     Prasad 	if (sscanf(line, "%d %d %d %d %d %d %d %d %u %u",
   2612      0     stevel 	    id, act, bhead, bsect, bcyl, ehead, esect, ecyl,
   2613      0     stevel 	    rsect, numsect) != 10) {
   2614      0     stevel 		(void) fprintf(stderr, "Syntax error:\n	\"%s\".\n", line);
   2615      0     stevel 		exit(1);
   2616      0     stevel 	}
   2617      0     stevel 	return (0);
   2618      0     stevel }
   2619      0     stevel 
   2620      0     stevel /*
   2621      0     stevel  * validate_part
   2622      0     stevel  * Validate that a new partition does not start at sector 0. Only UNUSED
   2623      0     stevel  * partitions and previously existing partitions are allowed to start at 0.
   2624      0     stevel  */
   2625    251      lclee static int
   2626   7563     Prasad validate_part(int id, uint32_t rsect, uint32_t numsect)
   2627      0     stevel {
   2628      0     stevel 	int i;
   2629      0     stevel 	if ((id != UNUSED) && (rsect == 0)) {
   2630      0     stevel 		for (i = 0; i < FD_NUMPART; i++) {
   2631      0     stevel 			if ((Old_Table[i].systid == id) &&
   2632  10021  Sheshadri 			    (Old_Table[i].relsect == LE_32(rsect)) &&
   2633  10021  Sheshadri 			    (Old_Table[i].numsect == LE_32(numsect)))
   2634   5169      lclee 				return (0);
   2635      0     stevel 		}
   2636    251      lclee 		(void) fprintf(stderr,
   2637    251      lclee 		    "New partition cannot start at sector 0\n");
   2638      0     stevel 		return (-1);
   2639      0     stevel 	}
   2640  10021  Sheshadri #ifdef i386
   2641  10021  Sheshadri 	if (id > FDISK_MAX_VALID_PART_ID) {
   2642  10021  Sheshadri 		fprintf(stderr, "Invalid partition ID\n");
   2643  10021  Sheshadri 		return (-1);
   2644  10021  Sheshadri 	}
   2645  10021  Sheshadri #endif
   2646      0     stevel 	return (0);
   2647      0     stevel }
   2648      0     stevel 
   2649      0     stevel /*
   2650      0     stevel  * stage0
   2651      0     stevel  * Print out interactive menu and process user input.
   2652      0     stevel  */
   2653    251      lclee static void
   2654    251      lclee stage0(void)
   2655      0     stevel {
   2656  10021  Sheshadri #ifdef i386
   2657  10021  Sheshadri 	int rval;
   2658  10021  Sheshadri #endif
   2659    251      lclee 	dispmenu();
   2660    251      lclee 	for (;;) {
   2661    251      lclee 		(void) printf(Q_LINE);
   2662    251      lclee 		(void) printf("Enter Selection: ");
   2663   9786      Barry 		(void) fgets(s, sizeof (s), stdin);
   2664      0     stevel 		rm_blanks(s);
   2665  10021  Sheshadri #ifdef i386
   2666  10021  Sheshadri 		while (!((s[0] > '0') && (s[0] < '8') &&
   2667  10021  Sheshadri 		    ((s[1] == '\0') || (s[1] == '\n')))) {
   2668  10021  Sheshadri #else
   2669   9786      Barry 		while (!((s[0] > '0') && (s[0] < '7') &&
   2670   9786      Barry 		    ((s[1] == '\0') || (s[1] == '\n')))) {
   2671  10021  Sheshadri #endif
   2672    251      lclee 			(void) printf(E_LINE); /* Clear any previous error */
   2673  10021  Sheshadri #ifdef i386
   2674  10021  Sheshadri 			(void) printf(
   2675  10021  Sheshadri 			    "Enter a one-digit number between 1 and 7.");
   2676  10021  Sheshadri #else
   2677    251      lclee 			(void) printf(
   2678    251      lclee 			    "Enter a one-digit number between 1 and 6.");
   2679  10021  Sheshadri #endif
   2680    251      lclee 			(void) printf(Q_LINE);
   2681    251      lclee 			(void) printf("Enter Selection: ");
   2682   9786      Barry 			(void) fgets(s, sizeof (s), stdin);
   2683      0     stevel 			rm_blanks(s);
   2684      0     stevel 		}
   2685    251      lclee 		(void) printf(E_LINE);
   2686      0     stevel 		switch (s[0]) {
   2687      0     stevel 			case '1':
   2688      0     stevel 				if (pcreate() == -1)
   2689      0     stevel 					return;
   2690      0     stevel 				break;
   2691      0     stevel 			case '2':
   2692      0     stevel 				if (pchange() == -1)
   2693      0     stevel 					return;
   2694      0     stevel 				break;
   2695      0     stevel 			case '3':
   2696      0     stevel 				if (pdelete() == -1)
   2697      0     stevel 					return;
   2698      0     stevel 				break;
   2699      0     stevel 			case '4':
   2700      0     stevel 				if (ppartid() == -1)
   2701      0     stevel 					return;
   2702      0     stevel 				break;
   2703  10021  Sheshadri #ifdef i386
   2704  10021  Sheshadri 			case '5':
   2705  10021  Sheshadri 				if (fdisk_ext_part_exists(epp)) {
   2706  10021  Sheshadri 					ext_part_menu();
   2707  10021  Sheshadri 				} else {
   2708  10021  Sheshadri 					printf(Q_LINE);
   2709  10021  Sheshadri 					printf("\nNo extended partition found"
   2710  10021  Sheshadri 					    "\n");
   2711  10021  Sheshadri 					printf("Press enter to continue\n");
   2712  10021  Sheshadri 					ext_read_input(s);
   2713  10021  Sheshadri 				}
   2714  10021  Sheshadri 				break;
   2715  10021  Sheshadri 			case '6':
   2716  10021  Sheshadri 				/* update disk partition table, if changed */
   2717  10021  Sheshadri 				if (TableChanged() == 1) {
   2718  10021  Sheshadri 					copy_Table_to_Bootblk();
   2719  10021  Sheshadri 					dev_mboot_write(0, Bootsect, sectsiz);
   2720  10021  Sheshadri 				}
   2721  10021  Sheshadri 
   2722  10021  Sheshadri 				/*
   2723  10021  Sheshadri 				 * If the VTOC table is wrong fix it
   2724  10021  Sheshadri 				 * (truncate only)
   2725  10021  Sheshadri 				 */
   2726  10021  Sheshadri 				if (io_adjt) {
   2727  10021  Sheshadri 					fix_slice();
   2728  10021  Sheshadri 				}
   2729  10021  Sheshadri 				if (!io_readonly) {
   2730  10021  Sheshadri 					rval = fdisk_commit_ext_part(epp);
   2731  10021  Sheshadri 					switch (rval) {
   2732  10021  Sheshadri 						case FDISK_SUCCESS:
   2733  10021  Sheshadri 							/* Success */
   2734  10021  Sheshadri 							/* Fallthrough */
   2735  10021  Sheshadri 						case FDISK_ENOEXTPART:
   2736  10021  Sheshadri 							/* Nothing to do */
   2737  10021  Sheshadri 							break;
   2738  10021  Sheshadri 						case FDISK_EMOUNTED:
   2739  10021  Sheshadri 							printf(Q_LINE);
   2740  10021  Sheshadri 							preach_and_continue();
   2741  10021  Sheshadri 							continue;
   2742  10021  Sheshadri 						default:
   2743  10021  Sheshadri 							perror("Commit failed");
   2744  10021  Sheshadri 							exit(1);
   2745  10021  Sheshadri 					}
   2746  10021  Sheshadri 					libfdisk_fini(&epp);
   2747  10021  Sheshadri 				}
   2748  10021  Sheshadri 				(void) close(Dev);
   2749  10021  Sheshadri 				exit(0);
   2750  10021  Sheshadri #else
   2751      0     stevel 			case '5':
   2752      0     stevel 				/* update disk partition table, if changed */
   2753      0     stevel 				if (TableChanged() == 1) {
   2754      0     stevel 					copy_Table_to_Bootblk();
   2755      0     stevel 					dev_mboot_write(0, Bootsect, sectsiz);
   2756      0     stevel 				}
   2757      0     stevel 				/*
   2758      0     stevel 				 * If the VTOC table is wrong fix it
   2759      0     stevel 				 * (truncate only)
   2760      0     stevel 				 */
   2761      0     stevel 				if (io_adjt) {
   2762      0     stevel 					fix_slice();
   2763      0     stevel 				}
   2764    251      lclee 				(void) close(Dev);
   2765      0     stevel 				exit(0);
   2766    251      lclee 				/* FALLTHRU */
   2767  10021  Sheshadri #endif
   2768  10021  Sheshadri #ifdef i386
   2769  10021  Sheshadri 			case '7':
   2770  10021  Sheshadri #else
   2771      0     stevel 			case '6':
   2772  10021  Sheshadri #endif
   2773      0     stevel 				/*
   2774      0     stevel 				 * If the VTOC table is wrong fix it
   2775      0     stevel 				 * (truncate only)
   2776      0     stevel 				 */
   2777      0     stevel 				if (io_adjt) {
   2778      0     stevel 					fix_slice();
   2779      0     stevel 				}
   2780    251      lclee 				(void) close(Dev);
   2781      0     stevel 				exit(0);
   2782    251      lclee 				/* FALLTHRU */
   2783      0     stevel 			default:
   2784      0     stevel 				break;
   2785      0     stevel 		}
   2786      0     stevel 		copy_Table_to_Bootblk();
   2787      0     stevel 		disptbl();
   2788    251      lclee 		dispmenu();
   2789      0     stevel 	}
   2790      0     stevel }
   2791      0     stevel 
   2792      0     stevel /*
   2793      0     stevel  * pcreate
   2794      0     stevel  * Create partition entry in the table (interactive mode).
   2795      0     stevel  */
   2796    251      lclee static int
   2797    251      lclee pcreate(void)
   2798      0     stevel {
   2799    251      lclee 	uchar_t tsystid = 'z';
   2800      0     stevel 	int i, j;
   2801   7563     Prasad 	uint32_t numsect;
   2802      0     stevel 	int retCode = 0;
   2803  10021  Sheshadri #ifdef i386
   2804  10021  Sheshadri 	int ext_part_present = 0;
   2805  10021  Sheshadri #endif
   2806      0     stevel 
   2807      0     stevel 	i = 0;
   2808    251      lclee 	for (;;) {
   2809      0     stevel 		if (i == FD_NUMPART) {
   2810    251      lclee 			(void) printf(E_LINE);
   2811    251      lclee 			(void) printf(
   2812    251      lclee 			    "The partition table is full!\n"
   2813    251      lclee 			    "You must delete a partition before creating"
   2814      0     stevel 			    " a new one.\n");
   2815      0     stevel 			return (-1);
   2816      0     stevel 		}
   2817      0     stevel 		if (Table[i].systid == UNUSED) {
   2818      0     stevel 			break;
   2819      0     stevel 		}
   2820      0     stevel 		i++;
   2821      0     stevel 	}
   2822      0     stevel 
   2823   7563     Prasad 	numsect = 0;
   2824      0     stevel 	for (i = 0; i < FD_NUMPART; i++) {
   2825      0     stevel 		if (Table[i].systid != UNUSED) {
   2826  10021  Sheshadri 			numsect += LE_32(Table[i].numsect);
   2827  10021  Sheshadri 		}
   2828  10021  Sheshadri #ifdef i386
   2829  10021  Sheshadri 		/* Check if an extended partition already exists */
   2830  10021  Sheshadri 		if (fdisk_is_dos_extended(Table[i].systid)) {
   2831  10021  Sheshadri 			ext_part_present = 1;
   2832  10021  Sheshadri 		}
   2833  10021  Sheshadri #endif
   2834   7563     Prasad 		if (numsect >= chs_capacity) {
   2835    251      lclee 			(void) printf(E_LINE);
   2836    251      lclee 			(void) printf("There is no more room on the disk for"
   2837      0     stevel 			    " another partition.\n");
   2838    251      lclee 			(void) printf(
   2839    251      lclee 			    "You must delete a partition before creating"
   2840      0     stevel 			    " a new one.\n");
   2841      0     stevel 			return (-1);
   2842      0     stevel 		}
   2843      0     stevel 	}
   2844      0     stevel 	while (tsystid == 'z') {
   2845   7563     Prasad 
   2846   7563     Prasad 		/*
   2847   7563     Prasad 		 * The question here is expanding to more than what is
   2848   7563     Prasad 		 * allocated for question lines (Q_LINE) which garbles
   2849   7563     Prasad 		 * at least warning line. Clearing warning line as workaround
   2850   7563     Prasad 		 * for now.
   2851   7563     Prasad 		 */
   2852   7563     Prasad 
   2853   7563     Prasad 		(void) printf(W_LINE);
   2854    251      lclee 		(void) printf(Q_LINE);
   2855    251      lclee 		(void) printf(
   2856    251      lclee 		    "Select the partition type to create:\n"
   2857    251      lclee 		    "   1=SOLARIS2  2=UNIX        3=PCIXOS     4=Other\n"
   2858    251      lclee 		    "   5=DOS12     6=DOS16       7=DOSEXT     8=DOSBIG\n"
   2859    251      lclee 		    "   9=DOS16LBA  A=x86 Boot    B=Diagnostic C=FAT32\n"
   2860    251      lclee 		    "   D=FAT32LBA  E=DOSEXTLBA   F=EFI        0=Exit? ");
   2861   9786      Barry 		(void) fgets(s, sizeof (s), stdin);
   2862      0     stevel 		rm_blanks(s);
   2863   9786      Barry 		if ((s[1] != '\0') && (s[1] != '\n')) {
   2864    251      lclee 			(void) printf(E_LINE);
   2865    251      lclee 			(void) printf("Invalid selection, try again.");
   2866      0     stevel 			continue;
   2867      0     stevel 		}
   2868      0     stevel 		switch (s[0]) {
   2869      0     stevel 		case '0':		/* exit */
   2870   5169      lclee 			(void) printf(E_LINE);
   2871   5169      lclee 			return (-1);
   2872      0     stevel 		case '1':		/* Solaris partition */
   2873   5169      lclee 			tsystid = SUNIXOS2;
   2874   5169      lclee 			break;
   2875      0     stevel 		case '2':		/* UNIX partition */
   2876   5169      lclee 			tsystid = UNIXOS;
   2877   5169      lclee 			break;
   2878      0     stevel 		case '3':		/* PCIXOS partition */
   2879   5169      lclee 			tsystid = PCIXOS;
   2880   5169      lclee 			break;
   2881      0     stevel 		case '4':		/* OTHEROS System partition */
   2882   5169      lclee 			tsystid = OTHEROS;
   2883   5169      lclee 			break;
   2884      0     stevel 		case '5':
   2885   5169      lclee 			tsystid = DOSOS12; /* DOS 12 bit fat */
   2886   5169      lclee 			break;
   2887      0     stevel 		case '6':
   2888   5169      lclee 			tsystid = DOSOS16; /* DOS 16 bit fat */
   2889   5169      lclee 			break;
   2890      0     stevel 		case '7':
   2891  10021  Sheshadri #ifdef i386
   2892  10021  Sheshadri 			if (ext_part_present) {
   2893  10021  Sheshadri 				printf(Q_LINE);
   2894  10021  Sheshadri 				printf(E_LINE);
   2895  10021  Sheshadri 				fprintf(stderr,
   2896  10021  Sheshadri 				    "Extended partition already exists\n");
   2897  10021  Sheshadri 				fprintf(stderr, "Press enter to continue\n");
   2898  10021  Sheshadri 				ext_read_input(s);
   2899  10021  Sheshadri 				continue;
   2900  10021  Sheshadri 			}
   2901  10021  Sheshadri #endif
   2902   5169      lclee 			tsystid = EXTDOS;
   2903   5169      lclee 			break;
   2904      0     stevel 		case '8':
   2905   5169      lclee 			tsystid = DOSHUGE;
   2906   5169      lclee 			break;
   2907      0     stevel 		case '9':
   2908   5169      lclee 			tsystid = FDISK_FAT95;  /* FAT16, need extended int13 */
   2909   5169      lclee 			break;
   2910      0     stevel 		case 'a':		/* x86 Boot partition */
   2911      0     stevel 		case 'A':
   2912   5169      lclee 			tsystid = X86BOOT;
   2913   5169      lclee 			break;
   2914      0     stevel 		case 'b':		/* Diagnostic boot partition */
   2915      0     stevel 		case 'B':
   2916   5169      lclee 			tsystid = DIAGPART;
   2917   5169      lclee 			break;
   2918      0     stevel 		case 'c':		/* FAT32 */
   2919      0     stevel 		case 'C':
   2920   5169      lclee 			tsystid = FDISK_WINDOWS;
   2921   5169      lclee 			break;
   2922      0     stevel 		case 'd':		/* FAT32 and need extended int13 */
   2923      0     stevel 		case 'D':
   2924   5169      lclee 			tsystid = FDISK_EXT_WIN;
   2925   5169      lclee 			break;
   2926      0     stevel 		case 'e':	/* Extended partition, need extended int13 */
   2927      0     stevel 		case 'E':
   2928  10682  Sheshadri #ifdef i386
   2929  10682  Sheshadri 			if (ext_part_present) {
   2930  10682  Sheshadri 				printf(Q_LINE);
   2931  10682  Sheshadri 				printf(E_LINE);
   2932  10682  Sheshadri 				fprintf(stderr,
   2933  10682  Sheshadri 				    "Extended partition already exists\n");
   2934  10682  Sheshadri 				fprintf(stderr, "Press enter to continue\n");
   2935  10682  Sheshadri 				ext_read_input(s);
   2936  10682  Sheshadri 				continue;
   2937  10682  Sheshadri 			}
   2938  10682  Sheshadri #endif
   2939   5169      lclee 			tsystid = FDISK_EXTLBA;
   2940   5169      lclee 			break;
   2941      0     stevel 		case 'f':
   2942      0     stevel 		case 'F':
   2943   5169      lclee 			tsystid = EFI_PMBR;
   2944   5169      lclee 			break;
   2945      0     stevel 		default:
   2946   5169      lclee 			(void) printf(E_LINE);
   2947   5169      lclee 			(void) printf("Invalid selection, try again.");
   2948   5169      lclee 			continue;
   2949      0     stevel 		}
   2950      0     stevel 	}
   2951      0     stevel 
   2952    251      lclee 	(void) printf(E_LINE);
   2953      0     stevel 
   2954      0     stevel 	if (tsystid != EFI_PMBR) {
   2955   7563     Prasad 		(void) printf(W_LINE);
   2956   7563     Prasad 		if ((dev_capacity > DK_MAX_2TB))
   2957   7563     Prasad 			(void) printf("WARNING: Disk is larger than 2 TB. "
   2958   7563     Prasad 			    "Upper limit is 2 TB for non-EFI partition ID\n");
   2959   7563     Prasad 
   2960      0     stevel 		/* create the new partition */
   2961      0     stevel 		i = specify(tsystid);
   2962      0     stevel 
   2963      0     stevel 		if (i != -1) {
   2964      0     stevel 			/* see if it should be the active partition */
   2965    251      lclee 			(void) printf(E_LINE);
   2966    251      lclee 			(void) printf(Q_LINE);
   2967      0     stevel 
   2968    251      lclee 			(void) printf(
   2969    251      lclee 			    "Should this become the active partition? If "
   2970    251      lclee 			    "yes, it  will be activated\n"
   2971    251      lclee 			    "each time the computer is reset or turned on.\n"
   2972    251      lclee 			    "Please type \"y\" or \"n\". ");
   2973      0     stevel 
   2974      0     stevel 			if (yesno()) {
   2975    251      lclee 				(void) printf(E_LINE);
   2976      0     stevel 				for (j = 0; j < FD_NUMPART; j++) {
   2977      0     stevel 					if (j == i) {
   2978      0     stevel 						Table[j].bootid = ACTIVE;
   2979    251      lclee 						(void) printf(E_LINE);
   2980    251      lclee 						(void) printf(
   2981    251      lclee 						    "Partition %d is now "
   2982      0     stevel 						    "the active partition.",
   2983    251      lclee 						    j + 1);
   2984      0     stevel 					} else {
   2985      0     stevel 						Table[j].bootid = 0;
   2986      0     stevel 					}
   2987      0     stevel 				}
   2988      0     stevel 			} else {
   2989      0     stevel 				Table[i].bootid = 0;
   2990      0     stevel 			}
   2991      0     stevel 
   2992  10021  Sheshadri #ifdef i386
   2993  10021  Sheshadri 			/*
   2994  10021  Sheshadri 			 * If partition created is an extended partition, null
   2995  10021  Sheshadri 			 * out the first sector of the first cylinder of the
   2996  10021  Sheshadri 			 * extended partition
   2997  10021  Sheshadri 			 */
   2998  10021  Sheshadri 			if (fdisk_is_dos_extended(Table[i].systid)) {
   2999  10021  Sheshadri 				fdisk_init_ext_part(epp,
   3000  10021  Sheshadri 				    LE_32(Table[i].relsect),
   3001  10021  Sheshadri 				    LE_32(Table[i].numsect));
   3002  10021  Sheshadri 			}
   3003  10021  Sheshadri #endif
   3004      0     stevel 			/* set up the return code */
   3005      0     stevel 			i = 1;
   3006      0     stevel 		}
   3007      0     stevel 	} else {
   3008      0     stevel 		/*
   3009      0     stevel 		 * partitions of type EFI_PMBR must be the only partitions in
   3010      0     stevel 		 * the table
   3011      0     stevel 		 *
   3012      0     stevel 		 * First, make sure there were no errors the table is
   3013      0     stevel 		 * empty
   3014      0     stevel 		 */
   3015      0     stevel 		retCode = verify_tbl();
   3016      0     stevel 
   3017      0     stevel 		if (retCode < 0) {
   3018    251      lclee 			(void) fprintf(stderr,
   3019      0     stevel 			    "fdisk: Cannot create EFI partition table; \n"
   3020      0     stevel 			    "current partition table is invalid.\n");
   3021      0     stevel 			return (-1);
   3022      0     stevel 		} else if (retCode > 0) {
   3023    251      lclee 			(void) printf(
   3024    251      lclee 			    "An EFI partition must be the only partition on "
   3025    251      lclee 			    "disk.  You may manually delete existing\n"
   3026    251      lclee 			    "partitions, or fdisk can do it.\n"
   3027    251      lclee 			    "Do you want fdisk to destroy existing "
   3028    251      lclee 			    "partitions?\n"
   3029    251      lclee 			    "Please type \"y\" or \"n\". ");
   3030      0     stevel 
   3031      0     stevel 			if (yesno()) {
   3032      0     stevel 				nulltbl();
   3033      0     stevel 			} else {
   3034      0     stevel 				return (-1);
   3035      0     stevel 			}
   3036      0     stevel 		}
   3037      0     stevel 
   3038      0     stevel 		/* create the table entry - i should be 0 */
   3039   7563     Prasad 		i = insert_tbl(tsystid, 0, 0, 0, 0, 0, 0, 0, 1,
   3040   7563     Prasad 		    (dev_capacity > DK_MAX_2TB) ? DK_MAX_2TB:
   3041   7563     Prasad 		    (dev_capacity - 1));
   3042      0     stevel 
   3043      0     stevel 		if (i != 0) {
   3044    251      lclee 			(void) printf("Error creating EFI partition!!!\n");
   3045      0     stevel 			i = -1;
   3046      0     stevel 		} else {
   3047      0     stevel 
   3048      0     stevel 			/* EFI partitions are currently never active */
   3049      0     stevel 			Table[i].bootid = 0;
   3050      0     stevel 
   3051      0     stevel 			/* set up the return code */
   3052      0     stevel 			i = 1;
   3053      0     stevel 		}
   3054      0     stevel 	}
   3055      0     stevel 
   3056      0     stevel 	return (i);
   3057      0     stevel }
   3058      0     stevel 
   3059      0     stevel /*
   3060      0     stevel  * specify
   3061      0     stevel  * Query the user to specify the size of the new partition in
   3062      0     stevel  * terms of percentage of the disk or by specifying the starting
   3063      0     stevel  * cylinder and length in cylinders.
   3064      0     stevel  */
   3065    251      lclee static int
   3066    251      lclee specify(uchar_t tsystid)
   3067      0     stevel {
   3068   5169      lclee 	int	i, j, percent = -1;
   3069   7563     Prasad 	int	cyl, cylen;
   3070   7563     Prasad 	diskaddr_t first_free, size_free;
   3071   7563     Prasad 	diskaddr_t max_free;
   3072   5169      lclee 	int	cyl_size;
   3073      0     stevel 	struct ipart *partition[FD_NUMPART];
   3074   5169      lclee 
   3075   5169      lclee 	cyl_size = heads * sectors;
   3076   5169      lclee 
   3077   5169      lclee 	/*
   3078   5169      lclee 	 * make a local copy of the partition table
   3079   5169      lclee 	 * and sort it into relsect order
   3080   5169      lclee 	 */
   3081   5169      lclee 	for (i = 0; i < FD_NUMPART; i++)
   3082   5169      lclee 		partition[i] = &Table[i];
   3083   5169      lclee 
   3084   5169      lclee 	for (i = 0; i < FD_NUMPART - 1; i++) {
   3085   5169      lclee 		if (partition[i]->systid == UNUSED)
   3086   5169      lclee 			break;
   3087   5169      lclee 		for (j = i + 1; j < FD_NUMPART; j++) {
   3088   5169      lclee 			if (partition[j]->systid == UNUSED)
   3089   5169      lclee 				break;
   3090  10021  Sheshadri 			if (LE_32(partition[j]->relsect) <
   3091  10021  Sheshadri 			    LE_32(partition[i]->relsect)) {
   3092   5169      lclee 				struct ipart *temp = partition[i];
   3093   5169      lclee 				partition[i] = partition[j];
   3094   5169      lclee 				partition[j] = temp;
   3095   5169      lclee 			}
   3096   5169      lclee 		}
   3097   5169      lclee 	}
   3098   7563     Prasad 
   3099      0     stevel 
   3100    251      lclee 	(void) printf(Q_LINE);
   3101    251      lclee 	(void) printf(
   3102    251      lclee 	    "Specify the percentage of disk to use for this partition\n"
   3103    251      lclee 	    "(or type \"c\" to specify the size in cylinders). ");
   3104   9786      Barry 	(void) fgets(s, sizeof (s), stdin);
   3105      0     stevel 	rm_blanks(s);
   3106      0     stevel 	if (s[0] != 'c') {	/* Specify size in percentage of disk */
   3107   5169      lclee 		i = 0;
   3108   9786      Barry 		while ((s[i] != '\0') && (s[i] != '\n')) {
   3109   5169      lclee 			if (s[i] < '0' || s[i] > '9') {
   3110   5169      lclee 				(void) printf(E_LINE);
   3111   5169      lclee 				(void) printf("Invalid percentage value "
   3112   5169      lclee 				    "specified; retry the operation.");
   3113   5169      lclee 				return (-1);
   3114   5169      lclee 			}
   3115   5169      lclee 			i++;
   3116   5169      lclee 			if (i > 3) {
   3117   5169      lclee 				(void) printf(E_LINE);
   3118   5169      lclee 				(void) printf("Invalid percentage value "
   3119   5169      lclee 				    "specified; retry the operation.");
   3120   5169      lclee 				return (-1);
   3121   5169      lclee 			}
   3122      0     stevel 		}
   3123   5169      lclee 		if ((percent = atoi(s)) > 100) {
   3124   5169      lclee 			(void) printf(E_LINE);
   3125   5169      lclee 			(void) printf(
   3126   5169      lclee 			    "Percentage value is too large. The value must be"
   3127   5169      lclee 			    " between 1 and 100;\nretry the operation.\n");
   3128   5169      lclee 			return (-1);
   3129      0     stevel 		}
   3130   5169      lclee 		if (percent < 1) {
   3131   5169      lclee 			(void) printf(E_LINE);
   3132   5169      lclee 			(void) printf(
   3133   5169      lclee 			    "Percentage value is too small. The value must be"
   3134   5169      lclee 			    " between 1 and 100;\nretry the operation.\n");
   3135   5169      lclee 			return (-1);
   3136   5169      lclee 		}
   3137   5169      lclee 
   3138   5169      lclee 		if (percent == 100)
   3139   7563     Prasad 			cylen = Numcyl_usable - 1;
   3140   5169      lclee 		else
   3141   7563     Prasad 			cylen = (Numcyl_usable * percent) / 100;
   3142   5169      lclee 
   3143   5169      lclee 		/* Verify DOS12 partition doesn't exceed max size of 32MB. */
   3144   5169      lclee 		if ((tsystid == DOSOS12) &&
   3145   5169      lclee 		    ((long)((long)cylen * cyl_size) > MAXDOS)) {
   3146   5169      lclee 			int n;
   3147   7563     Prasad 			n = MAXDOS * 100 / (int)(cyl_size) / Numcyl_usable;
   3148   5169      lclee 			(void) printf(E_LINE);
   3149   5169      lclee 			(void) printf("Maximum size for a DOS partition "
   3150   5169      lclee 			    "is %d%%; retry the operation.",
   3151   5169      lclee 			    n <= 100 ? n : 100);
   3152   5169      lclee 			return (-1);
   3153   5169      lclee 		}
   3154   5169      lclee 
   3155   5169      lclee 
   3156   5169      lclee 		max_free = 0;
   3157   5169      lclee 		for (i = 0; i < FD_NUMPART; i++) {
   3158   5169      lclee 
   3159   5169      lclee 			/*
   3160   5169      lclee 			 * check for free space before partition i
   3161   5169      lclee 			 * where i varies from 0 to 3
   3162   5169      lclee 			 *
   3163   5169      lclee 			 * freespace after partition 3 is unusable
   3164   5169      lclee 			 * because there are no free partitions
   3165   5169      lclee 			 *
   3166   5169      lclee 			 * freespace begins at the end of previous partition
   3167   5169      lclee 			 * or cylinder 1
   3168   5169      lclee 			 */
   3169   5169      lclee 			if (i) {
   3170   5169      lclee 				/* Not an empty table */
   3171  10021  Sheshadri 				first_free = LE_32(partition[i - 1]->relsect) +
   3172  10021  Sheshadri 				    LE_32(partition[i - 1]->numsect);
   3173   5169      lclee 			} else {
   3174   5169      lclee 				first_free = cyl_size;
   3175   5169      lclee 			}
   3176   5169      lclee 
   3177   5169      lclee 			/*
   3178   5169      lclee 			 * freespace ends before the current partition
   3179   5169      lclee 			 * or the end of the disk (chs end)
   3180   5169      lclee 			 */
   3181   5169      lclee 			if (partition[i]->systid == UNUSED) {
   3182   5169      lclee 				size_free = chs_capacity - first_free;
   3183   5169      lclee 			} else {
   3184   8148   Shidokht 				/*
   3185   8148   Shidokht 				 * Partition might start before cylinder 1.
   3186   8148   Shidokht 				 * Make sure free space is not negative.
   3187   8148   Shidokht 				 */
   3188   5169      lclee 				size_free =
   3189  10021  Sheshadri 				    (LE_32(partition[i]->relsect > first_free))
   3190  10021  Sheshadri 				    ? (LE_32(partition[i]->relsect) -
   3191  10021  Sheshadri 				    first_free) : 0;
   3192   5169      lclee 			}
   3193   5169      lclee 
   3194   5169      lclee 			/* save largest free space */
   3195   5169      lclee 			if (max_free < size_free)
   3196   5169      lclee 				max_free = size_free;
   3197   5169      lclee 
   3198   7563     Prasad 			if (((uint64_t)cylen * cyl_size) <= size_free) {
   3199   5169      lclee 				/* We found a place to use */
   3200   5169      lclee 				break;
   3201   5169      lclee 			}
   3202   5169      lclee 			if (partition[i]->systid == UNUSED) {
   3203   5169      lclee 				(void) printf(E_LINE);
   3204   5169      lclee 				max_free /= (cyl_size);
   3205   5169      lclee 				(void) fprintf(stderr, "fdisk: "
   3206   7563     Prasad 				    "Maximum percentage available is %lld\n",
   3207   7563     Prasad 				    100 * max_free / Numcyl_usable);
   3208   5169      lclee 				return (-1);
   3209   5169      lclee 			}
   3210   5169      lclee 		}
   3211   5169      lclee 
   3212    251      lclee 		(void) printf(E_LINE);
   3213   5169      lclee 		if (i >= FD_NUMPART) {
   3214   5169      lclee 			(void) fprintf(stderr,
   3215   5169      lclee 			    "fdisk: Partition table is full.\n");
   3216   5169      lclee 			return (-1);
   3217   5169      lclee 		}
   3218   5169      lclee 
   3219   5169      lclee 		if ((i = insert_tbl(tsystid, 0, 0, 0, 0, 0, 0, 0,
   3220   5169      lclee 		    first_free, cylen * cyl_size)) >= 0)  {
   3221   5169      lclee 			return (i);
   3222   5169      lclee 		}
   3223      0     stevel 		return (-1);
   3224   5169      lclee 	} else {
   3225   5169      lclee 
   3226   5169      lclee 		/* Specifying size in cylinders */
   3227    251      lclee 		(void) printf(E_LINE);
   3228   5169      lclee 		(void) printf(Q_LINE);
   3229   5169      lclee 		(void) printf("Enter starting cylinder number: ");
   3230   5169      lclee 		if ((cyl = getcyl()) == -1) {
   3231   5169      lclee 			(void) printf(E_LINE);
   3232   5169      lclee 			(void) printf("Invalid number; retry the operation.");
   3233   5169      lclee 			return (-1);
   3234   5169      lclee 		}
   3235   5169      lclee 		if (cyl == 0) {
   3236   5169      lclee 			(void) printf(E_LINE);
   3237   5169