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 §siz) != 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