1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This file contains functions that implement the fdisk menu commands. 28 */ 29 #include "global.h" 30 #include <errno.h> 31 #include <sys/time.h> 32 #include <sys/resource.h> 33 #include <sys/wait.h> 34 #include <signal.h> 35 #include <string.h> 36 #include <fcntl.h> 37 #include <stdlib.h> 38 #include <sys/dktp/fdisk.h> 39 #include <sys/stat.h> 40 #include <sys/dklabel.h> 41 #ifdef i386 42 #include <libfdisk.h> 43 #endif 44 45 #include "main.h" 46 #include "analyze.h" 47 #include "menu.h" 48 #include "menu_command.h" 49 #include "menu_defect.h" 50 #include "menu_partition.h" 51 #include "menu_fdisk.h" 52 #include "param.h" 53 #include "misc.h" 54 #include "label.h" 55 #include "startup.h" 56 #include "partition.h" 57 #include "prompts.h" 58 #include "checkdev.h" 59 #include "io.h" 60 #include "ctlr_scsi.h" 61 #include "auto_sense.h" 62 63 extern struct menu_item menu_fdisk[]; 64 65 /* 66 * Byte swapping macros for accessing struct ipart 67 * to resolve little endian on Sparc. 68 */ 69 #if defined(sparc) 70 #define les(val) ((((val)&0xFF)<<8)|(((val)>>8)&0xFF)) 71 #define lel(val) (((unsigned)(les((val)&0x0000FFFF))<<16) | \ 72 (les((unsigned)((val)&0xffff0000)>>16))) 73 74 #elif defined(i386) 75 76 #define les(val) (val) 77 #define lel(val) (val) 78 79 #else /* defined(sparc) */ 80 81 #error No Platform defined 82 83 #endif /* defined(sparc) */ 84 85 86 /* Function prototypes */ 87 #ifdef __STDC__ 88 89 #if defined(sparc) 90 91 static int getbyte(uchar_t **); 92 static int getlong(uchar_t **); 93 94 #endif /* defined(sparc) */ 95 96 static int get_solaris_part(int fd, struct ipart *ipart); 97 98 #else /* __STDC__ */ 99 100 #if defined(sparc) 101 102 static int getbyte(); 103 static int getlong(); 104 105 #endif /* defined(sparc) */ 106 107 static int get_solaris_part(); 108 109 #endif /* __STDC__ */ 110 111 #ifdef i386 112 int extpart_init(ext_part_t **epp); 113 #endif 114 /* 115 * Handling the alignment problem of struct ipart. 116 */ 117 static void 118 fill_ipart(char *bootptr, struct ipart *partp) 119 { 120 #if defined(sparc) 121 /* 122 * Sparc platform: 123 * 124 * Packing short/word for struct ipart to resolve 125 * little endian on Sparc since it is not 126 * properly aligned on Sparc. 127 */ 128 partp->bootid = getbyte((uchar_t **)&bootptr); 129 partp->beghead = getbyte((uchar_t **)&bootptr); 130 partp->begsect = getbyte((uchar_t **)&bootptr); 131 partp->begcyl = getbyte((uchar_t **)&bootptr); 132 partp->systid = getbyte((uchar_t **)&bootptr); 133 partp->endhead = getbyte((uchar_t **)&bootptr); 134 partp->endsect = getbyte((uchar_t **)&bootptr); 135 partp->endcyl = getbyte((uchar_t **)&bootptr); 136 partp->relsect = getlong((uchar_t **)&bootptr); 137 partp->numsect = getlong((uchar_t **)&bootptr); 138 #elif defined(i386) 139 /* 140 * i386 platform: 141 * 142 * The fdisk table does not begin on a 4-byte boundary within 143 * the master boot record; so, we need to recopy its contents 144 * to another data structure to avoid an alignment exception. 145 */ 146 (void) bcopy(bootptr, partp, sizeof (struct ipart)); 147 #else 148 #error No Platform defined 149 #endif /* defined(sparc) */ 150 } 151 152 /* 153 * Get a correct byte/short/word routines for Sparc platform. 154 */ 155 #if defined(sparc) 156 static int 157 getbyte(uchar_t **bp) 158 { 159 int b; 160 161 b = **bp; 162 *bp = *bp + 1; 163 return (b); 164 } 165 166 #ifdef DEADCODE 167 static int 168 getshort(uchar_t **bp) 169 { 170 int b; 171 172 b = ((**bp) << 8) | *(*bp + 1); 173 *bp += 2; 174 return (b); 175 } 176 #endif /* DEADCODE */ 177 178 static int 179 getlong(uchar_t **bp) 180 { 181 int b, bh, bl; 182 183 bh = ((**bp) << 8) | *(*bp + 1); 184 *bp += 2; 185 bl = ((**bp) << 8) | *(*bp + 1); 186 *bp += 2; 187 188 b = (bh << 16) | bl; 189 return (b); 190 } 191 #endif /* defined(sparc) */ 192 193 /* 194 * Convert cn[tn]dn to cn[tn]dns2 path 195 */ 196 static void 197 get_sname(char *name) 198 { 199 char buf[MAXPATHLEN]; 200 char *devp = "/dev/dsk"; 201 char *rdevp = "/dev/rdsk"; 202 char np[MAXNAMELEN]; 203 char *npt; 204 205 /* 206 * If it is a full path /dev/[r]dsk/cn[tn]dn, use this path 207 */ 208 (void) strcpy(np, cur_disk->disk_name); 209 if (strncmp(rdevp, cur_disk->disk_name, strlen(rdevp)) == 0 || 210 strncmp(devp, cur_disk->disk_name, strlen(devp)) == 0) { 211 /* 212 * Skip if the path is already included with sN 213 */ 214 if (strchr(np, 's') == strrchr(np, 's')) { 215 npt = strrchr(np, 'p'); 216 /* If pN is found, do not include it */ 217 if (npt != NULL) { 218 *npt = '\0'; 219 } 220 (void) snprintf(buf, sizeof (buf), "%ss2", np); 221 } else { 222 (void) snprintf(buf, sizeof (buf), "%s", np); 223 } 224 } else { 225 (void) snprintf(buf, sizeof (buf), "/dev/rdsk/%ss2", np); 226 } 227 (void) strcpy(name, buf); 228 } 229 230 /* 231 * Convert cn[tn]dnsn to cn[tn]dnp0 path 232 */ 233 static void 234 get_pname(char *name) 235 { 236 char buf[MAXPATHLEN]; 237 char *devp = "/dev/dsk"; 238 char *rdevp = "/dev/rdsk"; 239 char np[MAXNAMELEN]; 240 char *npt; 241 242 /* 243 * If it is a full path /dev/[r]dsk/cn[tn]dnsn, use this path 244 */ 245 if (cur_disk == NULL) { 246 (void) strcpy(np, x86_devname); 247 } else { 248 (void) strcpy(np, cur_disk->disk_name); 249 } 250 251 if (strncmp(rdevp, np, strlen(rdevp)) == 0 || 252 strncmp(devp, np, strlen(devp)) == 0) { 253 /* 254 * Skip if the path is already included with pN 255 */ 256 if (strchr(np, 'p') == NULL) { 257 npt = strrchr(np, 's'); 258 /* If sN is found, do not include it */ 259 if (isdigit(*++npt)) { 260 *--npt = '\0'; 261 } 262 (void) snprintf(buf, sizeof (buf), "%sp0", np); 263 } else { 264 (void) snprintf(buf, sizeof (buf), "%s", np); 265 } 266 } else { 267 (void) snprintf(buf, sizeof (buf), "/dev/rdsk/%sp0", np); 268 } 269 (void) strcpy(name, buf); 270 } 271 272 /* 273 * Open file descriptor for current disk (cur_file) 274 * with "p0" path or cur_disk->disk_path 275 */ 276 void 277 open_cur_file(int mode) 278 { 279 char *dkpath; 280 char pbuf[MAXPATHLEN]; 281 282 switch (mode) { 283 case FD_USE_P0_PATH: 284 (void) get_pname(&pbuf[0]); 285 dkpath = pbuf; 286 break; 287 case FD_USE_CUR_DISK_PATH: 288 if (cur_disk->fdisk_part.systid == SUNIXOS || 289 cur_disk->fdisk_part.systid == SUNIXOS2) { 290 (void) get_sname(&pbuf[0]); 291 dkpath = pbuf; 292 } else { 293 dkpath = cur_disk->disk_path; 294 } 295 break; 296 default: 297 err_print("Error: Invalid mode option for opening " 298 "cur_file\n"); 299 fullabort(); 300 } 301 302 /* Close previous cur_file */ 303 (void) close(cur_file); 304 /* Open cur_file with the required path dkpath */ 305 if ((cur_file = open_disk(dkpath, O_RDWR | O_NDELAY)) < 0) { 306 err_print( 307 "Error: can't open selected disk '%s'.\n", dkpath); 308 fullabort(); 309 } 310 } 311 312 313 /* 314 * This routine implements the 'fdisk' command. It simply runs 315 * the fdisk command on the current disk. 316 * Use of this is restricted to interactive mode only. 317 */ 318 int 319 c_fdisk() 320 { 321 322 char buf[MAXPATHLEN]; 323 char pbuf[MAXPATHLEN]; 324 struct stat statbuf; 325 326 /* 327 * We must be in interactive mode to use the fdisk command 328 */ 329 if (option_f != (char *)NULL || isatty(0) != 1 || isatty(1) != 1) { 330 err_print("Fdisk command is for interactive use only!\n"); 331 return (-1); 332 } 333 334 /* 335 * There must be a current disk type and a current disk 336 */ 337 if (cur_dtype == NULL) { 338 err_print("Current Disk Type is not set.\n"); 339 return (-1); 340 } 341 342 /* 343 * Before running the fdisk command, get file status of 344 * /dev/rdsk/cn[tn]dnp0 path to see if this disk 345 * supports fixed disk partition table. 346 */ 347 (void) get_pname(&pbuf[0]); 348 if (stat(pbuf, (struct stat *)&statbuf) == -1 || 349 !S_ISCHR(statbuf.st_mode)) { 350 err_print( 351 "Disk does not support fixed disk partition table\n"); 352 return (0); 353 } 354 355 /* 356 * Run the fdisk program. 357 */ 358 (void) snprintf(buf, sizeof (buf), "fdisk %s\n", pbuf); 359 (void) system(buf); 360 361 /* 362 * Open cur_file with "p0" path for accessing the fdisk table 363 */ 364 (void) open_cur_file(FD_USE_P0_PATH); 365 366 /* 367 * Get solaris partition information in the fdisk partition table 368 */ 369 if (get_solaris_part(cur_file, &cur_disk->fdisk_part) == -1) { 370 err_print("No fdisk solaris partition found\n"); 371 cur_disk->fdisk_part.numsect = 0; /* No Solaris */ 372 } 373 374 /* 375 * Restore cur_file with cur_disk->disk_path 376 */ 377 (void) open_cur_file(FD_USE_CUR_DISK_PATH); 378 379 return (0); 380 } 381 382 /* 383 * Read MBR on the disk 384 * if the Solaris partition has changed, 385 * reread the vtoc 386 */ 387 #ifdef DEADCODE 388 static void 389 update_cur_parts() 390 { 391 392 int i; 393 register struct partition_info *parts; 394 395 for (i = 0; i < NDKMAP; i++) { 396 #if defined(_SUNOS_VTOC_16) 397 if (cur_parts->vtoc.v_part[i].p_tag && 398 cur_parts->vtoc.v_part[i].p_tag != V_ALTSCTR) { 399 cur_parts->vtoc.v_part[i].p_start = 0; 400 cur_parts->vtoc.v_part[i].p_size = 0; 401 402 #endif 403 cur_parts->pinfo_map[i].dkl_nblk = 0; 404 cur_parts->pinfo_map[i].dkl_cylno = 0; 405 cur_parts->vtoc.v_part[i].p_tag = 406 default_vtoc_map[i].p_tag; 407 cur_parts->vtoc.v_part[i].p_flag = 408 default_vtoc_map[i].p_flag; 409 #if defined(_SUNOS_VTOC_16) 410 } 411 #endif 412 } 413 cur_parts->pinfo_map[C_PARTITION].dkl_nblk = ncyl * spc(); 414 415 #if defined(_SUNOS_VTOC_16) 416 /* 417 * Adjust for the boot partitions 418 */ 419 cur_parts->pinfo_map[I_PARTITION].dkl_nblk = spc(); 420 cur_parts->pinfo_map[I_PARTITION].dkl_cylno = 0; 421 cur_parts->vtoc.v_part[C_PARTITION].p_start = 422 cur_parts->pinfo_map[C_PARTITION].dkl_cylno * nhead * nsect; 423 cur_parts->vtoc.v_part[C_PARTITION].p_size = 424 cur_parts->pinfo_map[C_PARTITION].dkl_nblk; 425 426 cur_parts->vtoc.v_part[I_PARTITION].p_start = 427 cur_parts->pinfo_map[I_PARTITION].dkl_cylno; 428 cur_parts->vtoc.v_part[I_PARTITION].p_size = 429 cur_parts->pinfo_map[I_PARTITION].dkl_nblk; 430 431 #endif /* defined(_SUNOS_VTOC_16) */ 432 parts = cur_dtype->dtype_plist; 433 cur_dtype->dtype_ncyl = ncyl; 434 cur_dtype->dtype_plist = cur_parts; 435 parts->pinfo_name = cur_parts->pinfo_name; 436 cur_disk->disk_parts = cur_parts; 437 cur_ctype->ctype_dlist = cur_dtype; 438 439 } 440 #endif /* DEADCODE */ 441 442 static int 443 get_solaris_part(int fd, struct ipart *ipart) 444 { 445 int i; 446 struct ipart ip; 447 int status; 448 char *mbr; 449 char *bootptr; 450 struct dk_label update_label; 451 ushort_t found = 0; 452 #ifdef i386 453 uint32_t relsec, numsec; 454 int pno, rval, ext_part_found = 0; 455 ext_part_t *epp; 456 #endif 457 458 (void) lseek(fd, 0, 0); 459 460 /* 461 * We may get mbr of different size, but the first 512 bytes 462 * are valid information. 463 */ 464 mbr = malloc(cur_blksz); 465 if (mbr == NULL) { 466 err_print("No memory available.\n"); 467 return (-1); 468 } 469 status = read(fd, mbr, cur_blksz); 470 471 if (status != cur_blksz) { 472 err_print("Bad read of fdisk partition. Status = %x\n", status); 473 err_print("Cannot read fdisk partition information.\n"); 474 free(mbr); 475 return (-1); 476 } 477 478 (void) memcpy(&boot_sec, mbr, sizeof (struct mboot)); 479 free(mbr); 480 481 for (i = 0; i < FD_NUMPART; i++) { 482 int ipc; 483 484 ipc = i * sizeof (struct ipart); 485 486 /* Handling the alignment problem of struct ipart */ 487 bootptr = &boot_sec.parts[ipc]; 488 (void) fill_ipart(bootptr, &ip); 489 490 #ifdef i386 491 if (fdisk_is_dos_extended(ip.systid) && (ext_part_found == 0)) { 492 /* We support only one extended partition per disk */ 493 ext_part_found = 1; 494 (void) extpart_init(&epp); 495 rval = fdisk_get_solaris_part(epp, &pno, &relsec, 496 &numsec); 497 if (rval == FDISK_SUCCESS) { 498 /* 499 * Found a solaris partition inside the 500 * extended partition. Update the statistics. 501 */ 502 if (nhead != 0 && nsect != 0) { 503 pcyl = numsec / (nhead * nsect); 504 xstart = relsec / (nhead * nsect); 505 ncyl = pcyl - acyl; 506 } 507 solaris_offset = relsec; 508 found = 2; 509 ip.bootid = 0; 510 ip.beghead = ip.begsect = ip.begcyl = 0xff; 511 ip.endhead = ip.endsect = ip.endcyl = 0xff; 512 ip.systid = SUNIXOS2; 513 ip.relsect = relsec; 514 ip.numsect = numsec; 515 ipart->bootid = ip.bootid; 516 status = bcmp(&ip, ipart, 517 sizeof (struct ipart)); 518 bcopy(&ip, ipart, sizeof (struct ipart)); 519 } 520 libfdisk_fini(&epp); 521 continue; 522 } 523 #endif 524 525 /* 526 * we are interested in Solaris and EFI partition types 527 */ 528 if (ip.systid == SUNIXOS || 529 ip.systid == SUNIXOS2 || 530 ip.systid == EFI_PMBR) { 531 /* 532 * if the disk has an EFI label, nhead and nsect may 533 * be zero. This test protects us from FPE's, and 534 * format still seems to work fine 535 */ 536 if (nhead != 0 && nsect != 0) { 537 pcyl = lel(ip.numsect) / (nhead * nsect); 538 xstart = lel(ip.relsect) / (nhead * nsect); 539 ncyl = pcyl - acyl; 540 } 541 #ifdef DEBUG 542 else { 543 err_print("Critical geometry values are zero:\n" 544 "\tnhead = %d; nsect = %d\n", nhead, nsect); 545 } 546 #endif /* DEBUG */ 547 548 solaris_offset = (uint_t)lel(ip.relsect); 549 found = 1; 550 break; 551 } 552 } 553 554 if (!found) { 555 err_print("Solaris fdisk partition not found\n"); 556 return (-1); 557 } else if (found == 1) { 558 /* 559 * Found a primary solaris partition. 560 * compare the previous and current Solaris partition 561 * but don't use bootid in determination of Solaris partition 562 * changes 563 */ 564 ipart->bootid = ip.bootid; 565 status = bcmp(&ip, ipart, sizeof (struct ipart)); 566 567 bcopy(&ip, ipart, sizeof (struct ipart)); 568 } 569 570 /* if the disk partitioning has changed - get the VTOC */ 571 if (status) { 572 struct extvtoc exvtoc; 573 struct vtoc vtoc; 574 575 status = ioctl(fd, DKIOCGEXTVTOC, &exvtoc); 576 if (status == -1) { 577 i = errno; 578 /* Try the old ioctl DKIOCGVTOC */ 579 status = ioctl(fd, DKIOCGVTOC, &vtoc); 580 if (status == -1) { 581 err_print("Bad ioctl DKIOCGEXTVTOC.\n"); 582 err_print("errno=%d %s\n", i, strerror(i)); 583 err_print("Cannot read vtoc information.\n"); 584 return (-1); 585 } 586 } 587 588 status = read_label(fd, &update_label); 589 if (status == -1) { 590 err_print("Cannot read label information.\n"); 591 return (-1); 592 } 593 594 /* copy vtoc information */ 595 cur_parts->vtoc = update_label.dkl_vtoc; 596 597 #if defined(_SUNOS_VTOC_16) 598 /* 599 * this is to update the slice table on x86 600 * we don't care about VTOC8 here 601 */ 602 for (i = 0; i < NDKMAP; i ++) { 603 cur_parts->pinfo_map[i].dkl_cylno = 604 update_label.dkl_vtoc.v_part[i].p_start / 605 ((int)(update_label.dkl_nhead * 606 update_label.dkl_nsect)); 607 cur_parts->pinfo_map[i].dkl_nblk = 608 update_label.dkl_vtoc.v_part[i].p_size; 609 } 610 #endif /* defined(_SUNOS_VTOC_16) */ 611 612 cur_dtype->dtype_ncyl = update_label.dkl_ncyl; 613 cur_dtype->dtype_pcyl = update_label.dkl_pcyl; 614 cur_dtype->dtype_acyl = update_label.dkl_acyl; 615 cur_dtype->dtype_nhead = update_label.dkl_nhead; 616 cur_dtype->dtype_nsect = update_label.dkl_nsect; 617 ncyl = cur_dtype->dtype_ncyl; 618 acyl = cur_dtype->dtype_acyl; 619 pcyl = cur_dtype->dtype_pcyl; 620 nsect = cur_dtype->dtype_nsect; 621 nhead = cur_dtype->dtype_nhead; 622 } 623 return (0); 624 } 625 626 627 int 628 copy_solaris_part(struct ipart *ipart) 629 { 630 631 int status, i, fd; 632 struct mboot mboot; 633 char *mbr; 634 struct ipart ip; 635 char buf[MAXPATHLEN]; 636 char *bootptr; 637 struct stat statbuf; 638 #ifdef i386 639 uint32_t relsec, numsec; 640 int pno, rval, ext_part_found = 0; 641 ext_part_t *epp; 642 #endif 643 644 (void) get_pname(&buf[0]); 645 if (stat(buf, &statbuf) == -1 || 646 !S_ISCHR(statbuf.st_mode) || 647 ((cur_label == L_TYPE_EFI) && 648 (cur_disk->disk_flags & DSK_LABEL_DIRTY))) { 649 /* 650 * Make sure to reset solaris_offset to zero if it is 651 * previously set by a selected disk that 652 * supports the fdisk table. 653 */ 654 solaris_offset = 0; 655 /* 656 * Return if this disk does not support fdisk table or 657 * if it uses an EFI label but has not yet been labelled. 658 * If the EFI label has not been written then the open 659 * on the partition will fail. 660 */ 661 return (0); 662 } 663 664 if ((fd = open(buf, O_RDONLY)) < 0) { 665 err_print("Error: can't open disk '%s'.\n", buf); 666 return (-1); 667 } 668 669 /* 670 * We may get mbr of different size, but the first 512 bytes 671 * are valid information. 672 */ 673 mbr = malloc(cur_blksz); 674 if (mbr == NULL) { 675 err_print("No memory available.\n"); 676 return (-1); 677 } 678 status = read(fd, mbr, cur_blksz); 679 680 if (status != cur_blksz) { 681 err_print("Bad read of fdisk partition.\n"); 682 (void) close(fd); 683 free(mbr); 684 return (-1); 685 } 686 687 (void) memcpy(&mboot, mbr, sizeof (struct mboot)); 688 689 for (i = 0; i < FD_NUMPART; i++) { 690 int ipc; 691 692 ipc = i * sizeof (struct ipart); 693 694 /* Handling the alignment problem of struct ipart */ 695 bootptr = &mboot.parts[ipc]; 696 (void) fill_ipart(bootptr, &ip); 697 698 #ifdef i386 699 if (fdisk_is_dos_extended(ip.systid) && (ext_part_found == 0)) { 700 /* We support only one extended partition per disk */ 701 ext_part_found = 1; 702 (void) extpart_init(&epp); 703 rval = fdisk_get_solaris_part(epp, &pno, &relsec, 704 &numsec); 705 if (rval == FDISK_SUCCESS) { 706 /* 707 * Found a solaris partition inside the 708 * extended partition. Update the statistics. 709 */ 710 if (nhead != 0 && nsect != 0) { 711 pcyl = numsec / (nhead * nsect); 712 ncyl = pcyl - acyl; 713 } 714 solaris_offset = relsec; 715 ip.bootid = 0; 716 ip.beghead = ip.begsect = ip.begcyl = 0xff; 717 ip.endhead = ip.endsect = ip.endcyl = 0xff; 718 ip.systid = SUNIXOS2; 719 ip.relsect = relsec; 720 ip.numsect = numsec; 721 bcopy(&ip, ipart, sizeof (struct ipart)); 722 } 723 libfdisk_fini(&epp); 724 continue; 725 } 726 #endif 727 728 if (ip.systid == SUNIXOS || 729 ip.systid == SUNIXOS2 || 730 ip.systid == EFI_PMBR) { 731 solaris_offset = lel(ip.relsect); 732 bcopy(&ip, ipart, sizeof (struct ipart)); 733 734 /* 735 * if the disk has an EFI label, we typically won't 736 * have values for nhead and nsect. format seems to 737 * work without them, and we need to protect ourselves 738 * from FPE's 739 */ 740 if (nhead != 0 && nsect != 0) { 741 pcyl = lel(ip.numsect) / (nhead * nsect); 742 ncyl = pcyl - acyl; 743 } 744 #ifdef DEBUG 745 else { 746 err_print("Critical geometry values are zero:\n" 747 "\tnhead = %d; nsect = %d\n", nhead, nsect); 748 } 749 #endif /* DEBUG */ 750 751 break; 752 } 753 } 754 755 (void) close(fd); 756 free(mbr); 757 return (0); 758 } 759 760 #if defined(_FIRMWARE_NEEDS_FDISK) 761 int 762 auto_solaris_part(struct dk_label *label) 763 { 764 765 int status, i, fd; 766 struct mboot mboot; 767 char *mbr; 768 struct ipart ip; 769 char *bootptr; 770 char pbuf[MAXPATHLEN]; 771 #ifdef i386 772 uint32_t relsec, numsec; 773 int pno, rval, ext_part_found = 0; 774 ext_part_t *epp; 775 #endif 776 777 (void) get_pname(&pbuf[0]); 778 if ((fd = open_disk(pbuf, O_RDONLY)) < 0) { 779 err_print("Error: can't open selected disk '%s'.\n", pbuf); 780 return (-1); 781 } 782 783 /* 784 * We may get mbr of different size, but the first 512 bytes 785 * are valid information. 786 */ 787 mbr = malloc(cur_blksz); 788 if (mbr == NULL) { 789 err_print("No memory available.\n"); 790 return (-1); 791 } 792 status = read(fd, mbr, cur_blksz); 793 794 if (status != cur_blksz) { 795 err_print("Bad read of fdisk partition.\n"); 796 free(mbr); 797 return (-1); 798 } 799 800 (void) memcpy(&mboot, mbr, sizeof (struct mboot)); 801 802 for (i = 0; i < FD_NUMPART; i++) { 803 int ipc; 804 805 ipc = i * sizeof (struct ipart); 806 807 /* Handling the alignment problem of struct ipart */ 808 bootptr = &mboot.parts[ipc]; 809 (void) fill_ipart(bootptr, &ip); 810 811 #ifdef i386 812 if (fdisk_is_dos_extended(ip.systid) && (ext_part_found == 0)) { 813 /* We support only one extended partition per disk */ 814 ext_part_found = 1; 815 (void) extpart_init(&epp); 816 rval = fdisk_get_solaris_part(epp, &pno, &relsec, 817 &numsec); 818 if (rval == FDISK_SUCCESS) { 819 /* 820 * Found a solaris partition inside the 821 * extended partition. Update the statistics. 822 */ 823 if ((label->dkl_nhead != 0) && 824 (label->dkl_nsect != 0)) { 825 label->dkl_pcyl = 826 numsec / (label->dkl_nhead * 827 label->dkl_nsect); 828 label->dkl_ncyl = label->dkl_pcyl - 829 label->dkl_acyl; 830 } 831 solaris_offset = relsec; 832 } 833 libfdisk_fini(&epp); 834 continue; 835 } 836 #endif 837 838 /* 839 * if the disk has an EFI label, the nhead and nsect fields 840 * the label may be zero. This protects us from FPE's, and 841 * format still seems to work happily 842 */ 843 if (ip.systid == SUNIXOS || 844 ip.systid == SUNIXOS2 || 845 ip.systid == EFI_PMBR) { 846 if ((label->dkl_nhead != 0) && 847 (label->dkl_nsect != 0)) { 848 label->dkl_pcyl = lel(ip.numsect) / 849 (label->dkl_nhead * label->dkl_nsect); 850 label->dkl_ncyl = label->dkl_pcyl - 851 label->dkl_acyl; 852 } 853 #ifdef DEBUG 854 else { 855 err_print("Critical label fields aren't " 856 "non-zero:\n" 857 "\tlabel->dkl_nhead = %d; " 858 "label->dkl_nsect = " 859 "%d\n", label->dkl_nhead, 860 label->dkl_nsect); 861 } 862 #endif /* DEBUG */ 863 864 solaris_offset = lel(ip.relsect); 865 break; 866 } 867 } 868 869 (void) close(fd); 870 free(mbr); 871 return (0); 872 } 873 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 874 875 876 int 877 good_fdisk() 878 { 879 char buf[MAXPATHLEN]; 880 struct stat statbuf; 881 882 (void) get_pname(&buf[0]); 883 if (stat(buf, &statbuf) == -1 || 884 !S_ISCHR(statbuf.st_mode) || 885 cur_label == L_TYPE_EFI) { 886 /* 887 * Return if this disk does not support fdisk table or 888 * if the disk is labeled with EFI. 889 */ 890 return (1); 891 } 892 893 if (lel(cur_disk->fdisk_part.numsect) > 0) { 894 return (1); 895 } else { 896 err_print("WARNING - "); 897 err_print("This disk may be in use by an application " 898 "that has\n\t modified the fdisk table. Ensure " 899 "that this disk is\n\t not currently in use " 900 "before proceeding to use fdisk.\n"); 901 return (0); 902 } 903 } 904 905 #ifdef i386 906 int 907 extpart_init(ext_part_t **epp) 908 { 909 int rval, lf_op_flag = 0; 910 char p0_path[MAXPATHLEN]; 911 912 get_pname(&p0_path[0]); 913 lf_op_flag |= FDISK_READ_DISK; 914 if ((rval = libfdisk_init(epp, p0_path, NULL, lf_op_flag)) != 915 FDISK_SUCCESS) { 916 switch (rval) { 917 /* 918 * FDISK_EBADLOGDRIVE and FDISK_ENOLOGDRIVE can 919 * be considered as soft errors and hence 920 * we do not exit 921 */ 922 case FDISK_EBADLOGDRIVE: 923 break; 924 case FDISK_ENOLOGDRIVE: 925 break; 926 case FDISK_ENOVGEOM: 927 err_print("Could not get virtual geometry for" 928 " this device\n"); 929 fullabort(); 930 break; 931 case FDISK_ENOPGEOM: 932 err_print("Could not get physical geometry for" 933 " this device\n"); 934 fullabort(); 935 break; 936 case FDISK_ENOLGEOM: 937 err_print("Could not get label geometry for " 938 " this device\n"); 939 fullabort(); 940 break; 941 default: 942 err_print("Failed to initialise libfdisk.\n"); 943 fullabort(); 944 break; 945 } 946 } 947 return (0); 948 } 949 #endif 950