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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This file contains functions that implement the command menu commands. 28 */ 29 30 #include "global.h" 31 #include <time.h> 32 #include <sys/time.h> 33 #include <sys/resource.h> 34 #include <sys/wait.h> 35 #include <strings.h> 36 #include <signal.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #if defined(sparc) 41 #include <sys/hdio.h> 42 #endif /* defined(sparc) */ 43 44 #include "main.h" 45 #include "analyze.h" 46 #include "menu.h" 47 #include "menu_command.h" 48 #include "menu_defect.h" 49 #include "menu_partition.h" 50 #include "param.h" 51 #include "misc.h" 52 #include "label.h" 53 #include "startup.h" 54 #include "partition.h" 55 #include "prompts.h" 56 #include "checkdev.h" 57 #include "io.h" 58 #include "ctlr_scsi.h" 59 #include "auto_sense.h" 60 #include "modify_partition.h" 61 62 63 extern struct menu_item menu_partition[]; 64 extern struct menu_item menu_analyze[]; 65 extern struct menu_item menu_defect[]; 66 67 /* 68 * Choices for the p_tag vtoc field 69 */ 70 slist_t ptag_choices[] = { 71 { "unassigned", "", V_UNASSIGNED }, 72 { "boot", "", V_BOOT }, 73 { "root", "", V_ROOT }, 74 { "swap", "", V_SWAP }, 75 { "usr", "", V_USR }, 76 { "backup", "", V_BACKUP }, 77 { "stand", "", V_STAND }, 78 { "var", "", V_VAR }, 79 { "home", "", V_HOME }, 80 { "alternates", "", V_ALTSCTR }, 81 { "reserved", "", V_RESERVED }, 82 { NULL } 83 }; 84 85 86 /* 87 * Choices for the p_flag vtoc field 88 */ 89 slist_t pflag_choices[] = { 90 { "wm", "read-write, mountable", 0 }, 91 { "wu", "read-write, unmountable", V_UNMNT }, 92 { "rm", "read-only, mountable", V_RONLY }, 93 { "ru", "read-only, unmountable", V_RONLY|V_UNMNT }, 94 { NULL } 95 }; 96 97 98 /* 99 * This routine implements the 'disk' command. It allows the user to 100 * select a disk to be current. The list of choices is the list of 101 * disks that were found at startup time. 102 */ 103 int 104 c_disk() 105 { 106 struct disk_info *disk; 107 u_ioparam_t ioparam; 108 int i; 109 int ndisks = 0; 110 int blind_select = 0; 111 int deflt; 112 int index; 113 int *defltptr = NULL; 114 int more = 0; 115 int more_quit = 0; 116 int one_line = 0; 117 int tty_lines; 118 119 /* 120 * This buffer holds the check() prompt that verifies we've got the right 121 * disk when performing a blind selection. The size should be sufficient 122 * to hold the prompt string, plus 256 characters for the disk name - 123 * way more than should ever be necessary. See the #define in misc.h. 124 */ 125 char chk_buf[BLIND_SELECT_VER_PROMPT]; 126 127 if (istokenpresent()) { 128 /* 129 * disk number to be selected is already in the 130 * input stream . 131 */ 132 TOKEN token, cleantoken; 133 134 /* 135 * Get the disk number the user has given. 136 */ 137 i = 0; 138 for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 139 i++; 140 } 141 142 ioparam.io_bounds.lower = 0; 143 ioparam.io_bounds.upper = i - 1; 144 (void) gettoken(token); 145 clean_token(cleantoken, token); 146 147 /* 148 * Convert the token into an integer. 149 */ 150 if (geti(cleantoken, &index, (int *)NULL)) 151 return (0); 152 153 /* 154 * Check to be sure it is within the legal bounds. 155 */ 156 if ((index < 0) || (index >= i)) { 157 err_print("`%d' is out of range.\n", index); 158 return (0); 159 } 160 goto checkdisk; 161 } 162 163 fmt_print("\n\nAVAILABLE DISK SELECTIONS:\n"); 164 165 i = 0; 166 if ((option_f == (char *)NULL) && isatty(0) == 1 && isatty(1) == 1) { 167 /* 168 * We have a real terminal for std input and output, enable 169 * more style of output for disk selection list. 170 */ 171 more = 1; 172 tty_lines = get_tty_lines(); 173 enter_critical(); 174 echo_off(); 175 charmode_on(); 176 exit_critical(); 177 } 178 179 /* 180 * Loop through the list of found disks. 181 */ 182 for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 183 /* 184 * If using more output, account 2 lines for each disk. 185 */ 186 if (more && !more_quit && i && (one_line || 187 ((2 * i + 1) % (tty_lines - 2) <= 1))) { 188 int c; 189 190 /* 191 * Get the next character. 192 */ 193 fmt_print("- hit space for more or s to select - "); 194 c = getchar(); 195 fmt_print("\015"); 196 one_line = 0; 197 /* 198 * Handle display one line command 199 * (return key) 200 */ 201 if (c == '\012') { 202 one_line++; 203 } 204 /* Handle Quit command */ 205 if (c == 'q') { 206 fmt_print( 207 " \015"); 208 more_quit++; 209 } 210 /* Handle ^D command */ 211 if (c == '\004') 212 fullabort(); 213 /* or get on with the show */ 214 if (c == 's' || c == 'S') { 215 fmt_print("%80s\n", " "); 216 break; 217 } 218 } 219 /* 220 * If this is the current disk, mark it as 221 * the default. 222 */ 223 if (cur_disk == disk) { 224 deflt = i; 225 defltptr = &deflt; 226 } 227 if (!more || !more_quit) 228 pr_diskline(disk, i); 229 i++; 230 } 231 if (more) { 232 enter_critical(); 233 charmode_off(); 234 echo_on(); 235 exit_critical(); 236 } 237 238 /* 239 * Determine total number of disks, and ask the user which disk he 240 * would like to make current. 241 */ 242 243 for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 244 ndisks++; 245 } 246 247 ioparam.io_bounds.lower = 0; 248 ioparam.io_bounds.upper = ndisks - 1; 249 index = input(FIO_INT, "Specify disk (enter its number)", ':', 250 &ioparam, defltptr, DATA_INPUT); 251 252 if (index >= i) { 253 blind_select = 1; 254 } 255 256 /* 257 * Find the disk chosen. Search through controllers/disks 258 * in the same original order, so we match what the user 259 * chose. 260 */ 261 checkdisk: 262 i = 0; 263 for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 264 if (i == index) 265 goto found; 266 i++; 267 } 268 /* 269 * Should never happen. 270 */ 271 impossible("no disk found"); 272 273 found: 274 if (blind_select) { 275 (void) snprintf(chk_buf, sizeof (chk_buf), 276 "Disk %s selected - is this the desired disk? ", disk->disk_name); 277 if (check(chk_buf)) { 278 return (-1); 279 } 280 } 281 282 /* 283 * Update the state. We lock out interrupts so the state can't 284 * get half-updated. 285 */ 286 287 enter_critical(); 288 init_globals(disk); 289 exit_critical(); 290 291 /* 292 * If type unknown and interactive, ask user to specify type. 293 * Also, set partition table (best guess) too. 294 */ 295 if (!option_f && ncyl == 0 && nhead == 0 && nsect == 0 && 296 (disk->label_type != L_TYPE_EFI)) { 297 (void) c_type(); 298 } 299 300 /* 301 * Get the Solaris Fdisk Partition information 302 */ 303 if (nhead != 0 && nsect != 0) 304 (void) copy_solaris_part(&cur_disk->fdisk_part); 305 306 if ((cur_disk->label_type == L_TYPE_EFI) && 307 (cur_disk->disk_parts->etoc->efi_flags & 308 EFI_GPT_PRIMARY_CORRUPT)) { 309 err_print("Reading the primary EFI GPT label "); 310 err_print("failed. Using backup label.\n"); 311 err_print("Use the 'backup' command to restore "); 312 err_print("the primary label.\n"); 313 } 314 315 #if defined(_SUNOS_VTOC_16) 316 /* 317 * If there is no fdisk solaris partition. 318 */ 319 if (cur_disk->fdisk_part.numsect == 0) { 320 err_print("No Solaris fdisk partition found.\n"); 321 goto exit; 322 } 323 #endif /* defined(_SUNOS_VTOC_16) */ 324 325 /* 326 * If the label of the disk is marked dirty, 327 * see if they'd like to label the disk now. 328 */ 329 if (cur_disk->disk_flags & DSK_LABEL_DIRTY) { 330 if (check("Disk not labeled. Label it now") == 0) { 331 if (write_label()) { 332 err_print("Write label failed\n"); 333 } else { 334 cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 335 } 336 } 337 } 338 exit: 339 return (0); 340 } 341 342 /* 343 * This routine implements the 'type' command. It allows the user to 344 * specify the type of the current disk. It should be necessary only 345 * if the disk was not labelled or was somehow labelled incorrectly. 346 * The list of legal types for the disk comes from information that was 347 * in the data file. 348 */ 349 int 350 c_type() 351 { 352 struct disk_type *type, *tptr, *oldtype; 353 u_ioparam_t ioparam; 354 int i, index, deflt, *defltptr = NULL; 355 struct disk_type disk_type; 356 struct disk_type *d = &disk_type; 357 int first_disk; 358 int auto_conf_choice; 359 int other_choice; 360 struct dk_label label; 361 struct efi_info efi_info; 362 uint64_t maxLBA; 363 char volname[LEN_DKL_VVOL]; 364 int volinit = 0; 365 366 /* 367 * There must be a current disk. 368 */ 369 if (cur_disk == NULL) { 370 err_print("Current Disk is not set.\n"); 371 return (-1); 372 } 373 oldtype = cur_disk->disk_type; 374 type = cur_ctype->ctype_dlist; 375 /* 376 * Print out the list of choices. 377 */ 378 fmt_print("\n\nAVAILABLE DRIVE TYPES:\n"); 379 first_disk = 0; 380 if (cur_ctype->ctype_ctype == DKC_SCSI_CCS) { 381 auto_conf_choice = 0; 382 fmt_print(" %d. Auto configure\n", first_disk++); 383 } else { 384 auto_conf_choice = -1; 385 } 386 i = first_disk; 387 for (tptr = type; tptr != NULL; tptr = tptr->dtype_next) { 388 /* 389 * If we pass the current type, mark it to be the default. 390 */ 391 if (cur_dtype == tptr) { 392 deflt = i; 393 defltptr = &deflt; 394 } 395 if (cur_disk->label_type == L_TYPE_EFI) { 396 continue; 397 } 398 if (tptr->dtype_asciilabel) 399 fmt_print(" %d. %s\n", i++, tptr->dtype_asciilabel); 400 } 401 other_choice = i; 402 fmt_print(" %d. other\n", i); 403 ioparam.io_bounds.lower = 0; 404 ioparam.io_bounds.upper = i; 405 /* 406 * Ask the user which type the disk is. 407 */ 408 index = input(FIO_INT, "Specify disk type (enter its number)", ':', 409 &ioparam, defltptr, DATA_INPUT); 410 /* 411 * Find the type s/he chose. 412 */ 413 if (index == auto_conf_choice) { 414 float scaled; 415 diskaddr_t nblks; 416 int nparts; 417 418 /* 419 * User chose "auto configure". 420 */ 421 (void) strcpy(x86_devname, cur_disk->disk_name); 422 switch (cur_disk->label_type) { 423 case L_TYPE_SOLARIS: 424 if ((tptr = auto_sense(cur_file, 1, &label)) == NULL) { 425 err_print("Auto configure failed\n"); 426 return (-1); 427 } 428 fmt_print("%s: configured with capacity of ", 429 cur_disk->disk_name); 430 nblks = (diskaddr_t)tptr->dtype_ncyl * tptr->dtype_nhead * 431 tptr->dtype_nsect; 432 scaled = bn2mb(nblks); 433 if (scaled > 1024.0) { 434 fmt_print("%1.2fGB\n", scaled/1024.0); 435 } else { 436 fmt_print("%1.2fMB\n", scaled); 437 } 438 fmt_print("<%s cyl %d alt %d hd %d sec %d>\n", 439 tptr->dtype_asciilabel, tptr->dtype_ncyl, 440 tptr->dtype_acyl, tptr->dtype_nhead, 441 tptr->dtype_nsect); 442 break; 443 case L_TYPE_EFI: 444 if ((tptr = auto_efi_sense(cur_file, &efi_info)) == NULL) { 445 err_print("Auto configure failed\n"); 446 return (-1); 447 } 448 fmt_print("%s: configured with capacity of ", 449 cur_disk->disk_name); 450 scaled = bn2mb(efi_info.capacity); 451 if (scaled > 1024.0) { 452 fmt_print("%1.2fGB\n", scaled/1024.0); 453 } else { 454 fmt_print("%1.2fMB\n", scaled); 455 } 456 print_efi_string(efi_info.vendor, efi_info.product, 457 efi_info.revision, efi_info.capacity); 458 fmt_print("\n"); 459 for (nparts = 0; nparts < cur_parts->etoc->efi_nparts; 460 nparts++) { 461 if (cur_parts->etoc->efi_parts[nparts].p_tag == 462 V_RESERVED) { 463 if (cur_parts->etoc->efi_parts[nparts].p_name) { 464 (void) strcpy(volname, 465 cur_parts->etoc->efi_parts[nparts].p_name); 466 volinit = 1; 467 } 468 break; 469 } 470 } 471 enter_critical(); 472 if (delete_disk_type(cur_disk->disk_type) != 0) { 473 fmt_print("Autoconfiguration failed.\n"); 474 return (-1); 475 } 476 cur_disk->disk_type = tptr; 477 cur_disk->disk_parts = tptr->dtype_plist; 478 init_globals(cur_disk); 479 exit_critical(); 480 if (volinit) { 481 for (nparts = 0; nparts < cur_parts->etoc->efi_nparts; 482 nparts++) { 483 if (cur_parts->etoc->efi_parts[nparts].p_tag == 484 V_RESERVED) { 485 (void) strcpy( 486 cur_parts->etoc->efi_parts[nparts].p_name, 487 volname); 488 (void) strlcpy(cur_disk->v_volume, volname, 489 LEN_DKL_VVOL); 490 break; 491 } 492 } 493 } 494 return (0); 495 break; 496 default: 497 /* Should never happen */ 498 return (-1); 499 } 500 } else if ((index == other_choice) && (cur_label == L_TYPE_SOLARIS)) { 501 /* 502 * User chose "other". 503 * Get the standard information on the new type. 504 * Put all information in a tmp structure, in 505 * case user aborts. 506 */ 507 bzero((char *)d, sizeof (struct disk_type)); 508 509 d->dtype_ncyl = get_ncyl(); 510 d->dtype_acyl = get_acyl(d->dtype_ncyl); 511 d->dtype_pcyl = get_pcyl(d->dtype_ncyl, d->dtype_acyl); 512 d->dtype_nhead = get_nhead(); 513 d->dtype_phead = get_phead(d->dtype_nhead, &d->dtype_options); 514 d->dtype_nsect = get_nsect(); 515 d->dtype_psect = get_psect(&d->dtype_options); 516 d->dtype_bpt = get_bpt(d->dtype_nsect, &d->dtype_options); 517 d->dtype_rpm = get_rpm(); 518 d->dtype_fmt_time = get_fmt_time(&d->dtype_options); 519 d->dtype_cyl_skew = get_cyl_skew(&d->dtype_options); 520 d->dtype_trk_skew = get_trk_skew(&d->dtype_options); 521 d->dtype_trks_zone = get_trks_zone(&d->dtype_options); 522 d->dtype_atrks = get_atrks(&d->dtype_options); 523 d->dtype_asect = get_asect(&d->dtype_options); 524 d->dtype_cache = get_cache(&d->dtype_options); 525 d->dtype_threshold = get_threshold(&d->dtype_options); 526 d->dtype_prefetch_min = get_min_prefetch(&d->dtype_options); 527 d->dtype_prefetch_max = get_max_prefetch(d->dtype_prefetch_min, 528 &d->dtype_options); 529 d->dtype_bps = get_bps(); 530 #if defined(sparc) 531 d->dtype_dr_type = 0; 532 #endif /* defined(sparc) */ 533 534 d->dtype_asciilabel = get_asciilabel(); 535 536 /* 537 * Add the new type to the list of possible types for 538 * this controller. We lock out interrupts so the lists 539 * can't get munged. We put off actually allocating the 540 * structure till here in case the user wanted to 541 * interrupt while still inputting information. 542 */ 543 enter_critical(); 544 tptr = (struct disk_type *)zalloc(sizeof (struct disk_type)); 545 if (type == NULL) 546 cur_ctype->ctype_dlist = tptr; 547 else { 548 while (type->dtype_next != NULL) 549 type = type->dtype_next; 550 type->dtype_next = tptr; 551 } 552 bcopy((char *)d, (char *)tptr, sizeof (disk_type)); 553 tptr->dtype_next = NULL; 554 /* 555 * the new disk type does not have any defined 556 * partition table . Hence copy the current partition 557 * table if possible else create a default 558 * paritition table. 559 */ 560 new_partitiontable(tptr, oldtype); 561 } else if ((index == other_choice) && (cur_label == L_TYPE_EFI)) { 562 maxLBA = get_mlba(); 563 cur_parts->etoc->efi_last_lba = maxLBA; 564 cur_parts->etoc->efi_last_u_lba = maxLBA - 34; 565 for (i = 0; i < cur_parts->etoc->efi_nparts; i++) { 566 cur_parts->etoc->efi_parts[i].p_start = 0; 567 cur_parts->etoc->efi_parts[i].p_size = 0; 568 cur_parts->etoc->efi_parts[i].p_tag = V_UNASSIGNED; 569 } 570 cur_parts->etoc->efi_parts[8].p_start = 571 maxLBA - 34 - (1024 * 16); 572 cur_parts->etoc->efi_parts[8].p_size = (1024 * 16); 573 cur_parts->etoc->efi_parts[8].p_tag = V_RESERVED; 574 if (write_label()) { 575 err_print("Write label failed\n"); 576 } else { 577 cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 578 } 579 return (0); 580 } else { 581 /* 582 * User picked an existing disk type. 583 */ 584 i = first_disk; 585 tptr = type; 586 while (i < index) { 587 if (tptr->dtype_asciilabel) { 588 i++; 589 } 590 tptr = tptr->dtype_next; 591 } 592 if ((tptr->dtype_asciilabel == NULL) && 593 (tptr->dtype_next != NULL)) { 594 while (tptr->dtype_asciilabel == NULL) { 595 tptr = tptr->dtype_next; 596 } 597 } 598 } 599 /* 600 * Check for mounted file systems in the format zone. 601 * One potential problem with this would be that check() 602 * always returns 'yes' when running out of a file. However, 603 * it is actually ok because we don't let the program get 604 * started if there are mounted file systems and we are 605 * running from a file. 606 */ 607 if ((tptr != oldtype) && 608 checkmount((diskaddr_t)-1, (diskaddr_t)-1)) { 609 err_print( 610 "Cannot set disk type while it has mounted partitions.\n\n"); 611 return (-1); 612 } 613 /* 614 * check for partitions being used for swapping in format zone 615 */ 616 if ((tptr != oldtype) && 617 checkswap((diskaddr_t)-1, (diskaddr_t)-1)) { 618 err_print("Cannot set disk type while its partition are \ 619 currently being used for swapping.\n"); 620 return (-1); 621 } 622 623 /* 624 * Check for partitions being used in SVM, VxVM or LU devices 625 */ 626 627 if ((tptr != oldtype) && 628 checkdevinuse(cur_disk->disk_name, (diskaddr_t)-1, 629 (diskaddr_t)-1, 0, 0)) { 630 err_print("Cannot set disk type while its " 631 "partitions are currently in use.\n"); 632 return (-1); 633 } 634 /* 635 * If the type selected is different from the previous type, 636 * mark the disk as not labelled and reload the current 637 * partition info. This is not essential but probably the 638 * right thing to do, since the size of the disk has probably 639 * changed. 640 */ 641 enter_critical(); 642 if (tptr != oldtype) { 643 cur_disk->disk_type = tptr; 644 cur_disk->disk_parts = NULL; 645 cur_disk->disk_flags &= ~DSK_LABEL; 646 } 647 /* 648 * Initialize the state of the current disk. 649 */ 650 init_globals(cur_disk); 651 (void) get_partition(); 652 exit_critical(); 653 654 /* 655 * If the label of the disk is marked dirty, 656 * see if they'd like to label the disk now. 657 */ 658 if (cur_disk->disk_flags & DSK_LABEL_DIRTY) { 659 if (check("Disk not labeled. Label it now") == 0) { 660 if (write_label()) { 661 err_print("Write label failed\n"); 662 } else { 663 cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 664 } 665 } 666 } 667 668 return (0); 669 } 670 671 /* 672 * This routine implements the 'partition' command. It simply runs 673 * the partition menu. 674 */ 675 int 676 c_partition() 677 { 678 679 /* 680 * There must be a current disk type and a current disk 681 */ 682 if (cur_dtype == NULL) { 683 err_print("Current Disk Type is not set.\n"); 684 return (-1); 685 } 686 /* 687 * Check for a valid fdisk table entry for Solaris 688 */ 689 if (!good_fdisk()) { 690 return (-1); 691 } 692 693 cur_menu++; 694 last_menu = cur_menu; 695 696 #ifdef not 697 /* 698 * If there is no current partition table, make one. This is 699 * so the commands within the menu never have to check for 700 * a non-existent table. 701 */ 702 if (cur_parts == NULL) 703 err_print("making partition.\n"); 704 make_partition(); 705 #endif /* not */ 706 707 /* 708 * Run the menu. 709 */ 710 run_menu(menu_partition, "PARTITION", "partition", 0); 711 cur_menu--; 712 return (0); 713 } 714 715 /* 716 * This routine implements the 'current' command. It describes the 717 * current disk. 718 */ 719 int 720 c_current() 721 { 722 723 /* 724 * If there is no current disk, say so. Note that this is 725 * not an error since it is a legitimate response to the inquiry. 726 */ 727 if (cur_disk == NULL) { 728 fmt_print("No Current Disk.\n"); 729 return (0); 730 } 731 /* 732 * Print out the info we have on the current disk. 733 */ 734 fmt_print("Current Disk = %s", cur_disk->disk_name); 735 if (chk_volname(cur_disk)) { 736 fmt_print(": "); 737 print_volname(cur_disk); 738 } 739 fmt_print("\n"); 740 if (cur_disk->devfs_name != NULL) { 741 if (cur_dtype == NULL) { 742 fmt_print("<type unknown>\n"); 743 } else if (cur_label == L_TYPE_SOLARIS) { 744 fmt_print("<%s cyl %d alt %d hd %d sec %d>\n", 745 cur_dtype->dtype_asciilabel, ncyl, 746 acyl, nhead, nsect); 747 } else if (cur_label == L_TYPE_EFI) { 748 print_efi_string(cur_dtype->vendor, 749 cur_dtype->product, cur_dtype->revision, 750 cur_dtype->capacity); 751 fmt_print("\n"); 752 } 753 fmt_print("%s\n", cur_disk->devfs_name); 754 } else { 755 fmt_print("%s%d: <", cur_ctlr->ctlr_dname, 756 cur_disk->disk_dkinfo.dki_unit); 757 if (cur_dtype == NULL) { 758 fmt_print("type unknown"); 759 } else if (cur_label == L_TYPE_SOLARIS) { 760 fmt_print("%s cyl %d alt %d hd %d sec %d", 761 cur_dtype->dtype_asciilabel, ncyl, 762 acyl, nhead, nsect); 763 } else if (cur_label == L_TYPE_EFI) { 764 print_efi_string(cur_dtype->vendor, 765 cur_dtype->product, cur_dtype->revision, 766 cur_dtype->capacity); 767 fmt_print("\n"); 768 } 769 fmt_print(">\n"); 770 } 771 fmt_print("\n"); 772 return (0); 773 } 774 /* 775 * This routine implements the 'format' command. It allows the user 776 * to format and verify any portion of the disk. 777 */ 778 int 779 c_format() 780 { 781 diskaddr_t start, end; 782 time_t clock; 783 int format_time, format_tracks, format_cyls; 784 int format_interval; 785 diskaddr_t deflt; 786 int status; 787 u_ioparam_t ioparam; 788 789 /* 790 * There must be a current disk type and a current disk 791 */ 792 if (cur_dtype == NULL) { 793 err_print("Current Disk Type is not set.\n"); 794 return (-1); 795 } 796 797 /* 798 * There must be a format routine in cur_ops structure to have 799 * this routine work. 800 */ 801 if (cur_ops->op_format == NULL) { 802 err_print( 803 "Cannot format this drive. Please use your Manufacturer supplied formatting " 804 "utility.\n"); 805 return (-1); 806 } 807 808 /* 809 * There must be a current defect list. Except for 810 * unformatted SCSI disks. For them the defect list 811 * can only be retrieved after formatting the disk. 812 */ 813 if ((cur_ctype->ctype_flags & CF_SCSI) && !EMBEDDED_SCSI && 814 (cur_ctype->ctype_flags & CF_DEFECTS) && 815 ! (cur_flags & DISK_FORMATTED)) { 816 cur_list.flags |= LIST_RELOAD; 817 818 } else if (cur_list.list == NULL && !EMBEDDED_SCSI) { 819 err_print("Current Defect List must be initialized.\n"); 820 return (-1); 821 } 822 /* 823 * Ask for the bounds of the format. We always use the whole 824 * disk as the default, since that is the most likely case. 825 * Note, for disks which must be formatted accross the whole disk, 826 * don't bother the user. 827 */ 828 ioparam.io_bounds.lower = start = 0; 829 if (cur_label == L_TYPE_SOLARIS) { 830 if (cur_ctype->ctype_flags & CF_SCSI) { 831 ioparam.io_bounds.upper = end = datasects() - 1; 832 } else { 833 ioparam.io_bounds.upper = end = physsects() - 1; 834 } 835 } else { 836 ioparam.io_bounds.upper = end = cur_parts->etoc->efi_last_lba; 837 } 838 839 if (! (cur_ctlr->ctlr_flags & DKI_FMTVOL)) { 840 deflt = ioparam.io_bounds.lower; 841 start = input(FIO_BN, 842 "Enter starting block number", ':', 843 &ioparam, (int *)&deflt, DATA_INPUT); 844 ioparam.io_bounds.lower = start; 845 deflt = ioparam.io_bounds.upper; 846 end = input(FIO_BN, 847 "Enter ending block number", ':', 848 &ioparam, (int *)&deflt, DATA_INPUT); 849 } 850 /* 851 * Some disks can format tracks. Make sure the whole track is 852 * specified for them. 853 */ 854 if (cur_ctlr->ctlr_flags & DKI_FMTTRK) { 855 if (bn2s(start) != 0 || 856 bn2s(end) != sectors(bn2h(end)) - 1) { 857 err_print("Controller requires formatting of "); 858 err_print("entire tracks.\n"); 859 return (-1); 860 } 861 } 862 /* 863 * Check for mounted file systems in the format zone, and if we 864 * find any, make sure they are really serious. One potential 865 * problem with this would be that check() always returns 'yes' 866 * when running out of a file. However, it is actually ok 867 * because we don't let the program get started if there are 868 * mounted file systems and we are running from a file. 869 */ 870 if (checkmount(start, end)) { 871 err_print( 872 "Cannot format disk while it has mounted partitions.\n\n"); 873 return (-1); 874 } 875 /* 876 * check for partitions being used for swapping in format zone 877 */ 878 if (checkswap(start, end)) { 879 err_print("Cannot format disk while its partition are \ 880 currently being used for swapping.\n"); 881 return (-1); 882 } 883 /* 884 * Check for partitions being used in SVM, VxVM or LU devices 885 * in this format zone 886 */ 887 if (checkdevinuse(cur_disk->disk_name, start, end, 0, 0)) { 888 err_print("Cannot format disk while its partitions " 889 "are currently in use.\n"); 890 return (-1); 891 } 892 893 if (SCSI && (format_time = scsi_format_time()) > 0) { 894 fmt_print( 895 "Ready to format. Formatting cannot be interrupted\n" 896 "and takes %d minutes (estimated). ", format_time); 897 898 } else if (cur_dtype->dtype_options & SUP_FMTTIME) { 899 /* 900 * Formatting time is (2 * time of 1 spin * number of 901 * tracks) + (step rate * number of cylinders) rounded 902 * up to the nearest minute. Note, a 10% fudge factor 903 * is thrown in for insurance. 904 */ 905 if (cur_dtype->dtype_fmt_time == 0) 906 cur_dtype->dtype_fmt_time = 2; 907 908 format_tracks = ((end-start) / cur_dtype->dtype_nsect) + 1; 909 format_cyls = format_tracks / cur_dtype->dtype_nhead; 910 format_tracks = format_tracks * cur_dtype->dtype_fmt_time; 911 912 /* 913 * ms. 914 */ 915 format_time = ((60000 / cur_dtype->dtype_rpm) +1) * 916 format_tracks + format_cyls * 7; 917 /* 918 * 20% done tick (sec) 919 */ 920 format_interval = format_time / 5000; 921 /* 922 * min. 923 */ 924 format_time = (format_time + 59999) / 60000; 925 926 /* 927 * Check format time values and make adjustments 928 * to prevent sleeping too long (forever?) or 929 * too short. 930 */ 931 if (format_time <= 1) { 932 /* 933 * Format time is less than 1 min.. 934 */ 935 format_time = 1; 936 } 937 938 if (format_interval < 11) { 939 /* Format time is less than 1 minute. */ 940 if (format_interval < 2) 941 format_interval = 2; /* failsafe */ 942 format_interval = 10; 943 } else { 944 /* Format time is greater than 1 minute. */ 945 format_interval -= 10; 946 } 947 948 fmt_print( 949 "Ready to format. Formatting cannot be interrupted\n" 950 "and takes %d minutes (estimated). ", format_time); 951 } else { 952 fmt_print( 953 "Ready to format. Formatting cannot be interrupted.\n"); 954 } 955 if (check("Continue")) { 956 return (-1); 957 } 958 959 /* 960 * Print the time so that the user will know when format started. 961 * Lock out interrupts. This could be a problem, since it could 962 * cause the user to sit for quite awhile with no control, but we 963 * don't have any other good way of keeping his gun from going off. 964 */ 965 clock = time((time_t *)0); 966 fmt_print("Beginning format. The current time is %s\n", 967 ctime(&clock)); 968 enter_critical(); 969 /* 970 * Mark the defect list dirty so it will be rewritten when we are 971 * done. It is possible to qualify this so it doesn't always 972 * get rewritten, but it's not worth the trouble. 973 * Note: no defect lists for embedded scsi drives. 974 */ 975 if (!EMBEDDED_SCSI) { 976 cur_list.flags |= LIST_DIRTY; 977 } 978 /* 979 * If we are formatting over any of the labels, mark the label 980 * dirty so it will be rewritten. 981 */ 982 if (cur_disk->label_type == L_TYPE_SOLARIS) { 983 if (start < totalsects() && end >= datasects()) { 984 if (cur_disk->disk_flags & DSK_LABEL) 985 cur_flags |= LABEL_DIRTY; 986 } 987 } else if (cur_disk->label_type == L_TYPE_EFI) { 988 if (start < 34) { 989 if (cur_disk->disk_flags & DSK_LABEL) 990 cur_flags |= LABEL_DIRTY; 991 } 992 } 993 if (start == 0) { 994 cur_flags |= LABEL_DIRTY; 995 } 996 /* 997 * Do the format. bugid 1009138 removed the use of fork to 998 * background the format and print a tick. 999 */ 1000 1001 status = (*cur_ops->op_format)(start, end, &cur_list); 1002 if (status) { 1003 exit_critical(); 1004 err_print("failed\n"); 1005 return (-1); 1006 } 1007 fmt_print("done\n"); 1008 if (option_msg && diag_msg) { 1009 clock = time((time_t *)0); 1010 fmt_print("The current time is %s\n", ctime(&clock)); 1011 } 1012 cur_flags |= DISK_FORMATTED; 1013 /* 1014 * If the defect list or label is dirty, write them out again. 1015 * Note, for SCSI we have to wait til now to load defect list 1016 * since we can't access it until after formatting a virgin disk. 1017 */ 1018 /* enter_critical(); */ 1019 if (cur_list.flags & LIST_RELOAD) { 1020 assert(!EMBEDDED_SCSI); 1021 if (*cur_ops->op_ex_man == NULL || 1022 (*cur_ops->op_ex_man)(&cur_list)) { 1023 err_print("Warning: unable to reload defect list\n"); 1024 cur_list.flags &= ~LIST_DIRTY; 1025 return (-1); 1026 } 1027 cur_list.flags |= LIST_DIRTY; 1028 } 1029 1030 if (cur_list.flags & LIST_DIRTY) { 1031 assert(!EMBEDDED_SCSI); 1032 write_deflist(&cur_list); 1033 cur_list.flags = 0; 1034 } 1035 if (cur_flags & LABEL_DIRTY) { 1036 (void) write_label(); 1037 cur_flags &= ~LABEL_DIRTY; 1038 } 1039 /* 1040 * Come up for air, since the verify step does not need to 1041 * be atomic (it does it's own lockouts when necessary). 1042 */ 1043 exit_critical(); 1044 /* 1045 * If we are supposed to verify, we do the 'write' test over 1046 * the format zone. The rest of the analysis parameters are 1047 * left the way they were. 1048 */ 1049 if (scan_auto) { 1050 scan_entire = 0; 1051 scan_lower = start; 1052 scan_upper = end; 1053 fmt_print("\nVerifying media..."); 1054 status = do_scan(SCAN_PATTERN, F_SILENT); 1055 } 1056 /* 1057 * If the defect list or label is dirty, write them out again. 1058 */ 1059 if (cur_list.flags & LIST_DIRTY) { 1060 assert(!EMBEDDED_SCSI); 1061 cur_list.flags = 0; 1062 write_deflist(&cur_list); 1063 } 1064 if (cur_flags & LABEL_DIRTY) { 1065 cur_flags &= ~LABEL_DIRTY; 1066 (void) write_label(); 1067 } 1068 return (status); 1069 } 1070 1071 /* 1072 * This routine implements the 'repair' command. It allows the user 1073 * to reallocate sectors on the disk that have gone bad. 1074 */ 1075 int 1076 c_repair() 1077 { 1078 diskaddr_t bn; 1079 int status; 1080 u_ioparam_t ioparam; 1081 char buf[SECSIZE]; 1082 int buf_is_good; 1083 int block_has_error; 1084 int i; 1085 1086 /* 1087 * There must be a current disk type (and therefore a current disk). 1088 */ 1089 if (cur_dtype == NULL) { 1090 err_print("Current Disk Type is not set.\n"); 1091 return (-1); 1092 } 1093 /* 1094 * The current disk must be formatted for repair to work. 1095 */ 1096 if (!(cur_flags & DISK_FORMATTED)) { 1097 err_print("Current Disk is unformatted.\n"); 1098 return (-1); 1099 } 1100 /* 1101 * Check for a valid fdisk table entry for Solaris 1102 */ 1103 if (!good_fdisk()) { 1104 return (-1); 1105 } 1106 /* 1107 * Repair is an optional command for controllers, so it may 1108 * not be supported. 1109 */ 1110 if (cur_ops->op_repair == NULL) { 1111 err_print("Controller does not support repairing.\n"); 1112 err_print("or disk supports automatic defect management.\n"); 1113 return (-1); 1114 } 1115 /* 1116 * There must be a defect list for non-embedded scsi devices, 1117 * since we will add to it. 1118 */ 1119 if (!EMBEDDED_SCSI && cur_list.list == NULL) { 1120 err_print("Current Defect List must be initialized.\n"); 1121 return (-1); 1122 } 1123 /* 1124 * Ask the user which sector has gone bad. 1125 */ 1126 ioparam.io_bounds.lower = 0; 1127 if (cur_disk->label_type == L_TYPE_SOLARIS) { 1128 ioparam.io_bounds.upper = physsects() - 1; 1129 } else { 1130 ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; 1131 } 1132 bn = input(FIO_BN, 1133 "Enter absolute block number of defect", ':', 1134 &ioparam, (int *)NULL, DATA_INPUT); 1135 /* 1136 * Check to see if there is a mounted file system over the 1137 * specified sector. If there is, make sure the user is 1138 * really serious. 1139 */ 1140 if (checkmount(bn, bn)) { 1141 if (check("Repair is in a mounted partition, continue")) 1142 return (-1); 1143 } 1144 /* 1145 * check for partitions being used for swapping in format zone 1146 */ 1147 if (checkswap(bn, bn)) { 1148 if (check("Repair is in a partition which is currently \ 1149 being used for swapping.\ncontinue")) 1150 return (-1); 1151 } 1152 1153 if (checkdevinuse(cur_disk->disk_name, bn, bn, 0, 0)) { 1154 if (check("Repair is in a partition which is currently " 1155 "in use.\ncontinue")) 1156 return (-1); 1157 } 1158 1159 /* 1160 * Try to read the sector before repairing it. If we can 1161 * get good data out of it, we can write that data back 1162 * after the repair. If the sector looks ok, ask the 1163 * user to confirm the repair, since it doesn't appear 1164 * necessary. Try reading the block several times to 1165 * see if we can read it consistently. 1166 * 1167 * First, let's see if the block appears to have problems... 1168 */ 1169 block_has_error = 1; 1170 for (i = 0; i < 5; i++) { 1171 status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, 1172 1, buf, (F_SILENT | F_ALLERRS), NULL); 1173 if (status) 1174 break; /* one of the tries failed */ 1175 } 1176 if (status == 0) { 1177 block_has_error = 0; 1178 if (check("\ 1179 This block doesn't appear to be bad. Repair it anyway")) { 1180 return (0); 1181 } 1182 } 1183 /* 1184 * Last chance... 1185 */ 1186 if (check("Ready to repair defect, continue")) { 1187 return (-1); 1188 } 1189 /* 1190 * We're committed to repairing it. Try to get any good 1191 * data out of the block if possible. Note that we do 1192 * not set the F_ALLERRS flag. 1193 */ 1194 buf_is_good = 0; 1195 for (i = 0; i < 5; i++) { 1196 status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, 1197 1, buf, F_SILENT, NULL); 1198 if (status == 0) { 1199 buf_is_good = 1; 1200 break; 1201 } 1202 } 1203 /* 1204 * Lock out interrupts so the disk can't get out of sync with 1205 * the defect list. 1206 */ 1207 enter_critical(); 1208 1209 fmt_print("Repairing "); 1210 if (block_has_error) { 1211 fmt_print("%s error on ", buf_is_good ? "soft" : "hard"); 1212 } 1213 fmt_print("block %llu (", bn); 1214 pr_dblock(fmt_print, bn); 1215 fmt_print(")..."); 1216 /* 1217 * Do the repair. 1218 */ 1219 status = (*cur_ops->op_repair)(bn, F_NORMAL); 1220 if (status) { 1221 fmt_print("failed.\n\n"); 1222 } else { 1223 /* 1224 * The repair worked. Write the old data to the new 1225 * block if we were able to read it, otherwise 1226 * zero out the new block. If it looks like the 1227 * new block is bad, let the user know that, too. 1228 * Should we attempt auto-repair in this case? 1229 */ 1230 fmt_print("ok.\n"); 1231 if (!buf_is_good) { 1232 bzero(buf, SECSIZE); 1233 } 1234 status = (*cur_ops->op_rdwr)(DIR_WRITE, cur_file, bn, 1235 1, buf, (F_SILENT | F_ALLERRS), NULL); 1236 if (status == 0) { 1237 status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, 1238 bn, 1, buf, (F_SILENT | F_ALLERRS), NULL); 1239 } 1240 if (status) { 1241 fmt_print("The new block %llu (", bn); 1242 pr_dblock(fmt_print, bn); 1243 fmt_print(") also appears defective.\n"); 1244 } 1245 fmt_print("\n"); 1246 /* 1247 * Add the bad sector to the defect list, write out 1248 * the defect list, and kill off the working list so 1249 * it will get synced up with the current defect list 1250 * next time we need it. 1251 * 1252 * For embedded scsi, we don't require a defect list. 1253 * However, if we have one, add the defect if the 1254 * list includes the grown list. If not, kill it 1255 * to force a resync if we need the list later. 1256 */ 1257 if (EMBEDDED_SCSI) { 1258 if (cur_list.list != NULL) { 1259 if (cur_list.flags & LIST_PGLIST) { 1260 add_ldef(bn, &cur_list); 1261 } else { 1262 kill_deflist(&cur_list); 1263 } 1264 } 1265 } else if (cur_ctype->ctype_flags & CF_WLIST) { 1266 kill_deflist(&cur_list); 1267 if (*cur_ops->op_ex_cur != NULL) { 1268 (*cur_ops->op_ex_cur)(&cur_list); 1269 fmt_print("Current list updated\n"); 1270 } 1271 } else { 1272 add_ldef(bn, &cur_list); 1273 write_deflist(&cur_list); 1274 } 1275 kill_deflist(&work_list); 1276 } 1277 exit_critical(); 1278 /* 1279 * Return status. 1280 */ 1281 return (status); 1282 } 1283 1284 /* 1285 * This routine implements the 'show' command. It translates a disk 1286 * block given in any format into decimal, hexadecimal, and 1287 * cylinder/head/sector format. 1288 */ 1289 int 1290 c_show() 1291 { 1292 u_ioparam_t ioparam; 1293 diskaddr_t bn; 1294 1295 /* 1296 * There must be a current disk type, so we will know the geometry. 1297 */ 1298 if (cur_dtype == NULL) { 1299 err_print("Current Disk Type is not set.\n"); 1300 return (-1); 1301 } 1302 /* 1303 * Ask the user for a disk block. 1304 */ 1305 ioparam.io_bounds.lower = 0; 1306 if (cur_disk->label_type == L_TYPE_SOLARIS) { 1307 ioparam.io_bounds.upper = physsects() - 1; 1308 } else { 1309 ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; 1310 } 1311 bn = input(FIO_BN, "Enter a disk block", ':', 1312 &ioparam, (int *)NULL, DATA_INPUT); 1313 /* 1314 * Echo it back. 1315 */ 1316 fmt_print("Disk block = %lld = 0x%llx = (", bn, bn); 1317 pr_dblock(fmt_print, bn); 1318 fmt_print(")\n\n"); 1319 return (0); 1320 } 1321 1322 /* 1323 * This routine implements the 'label' command. It writes the 1324 * primary and backup labels onto the current disk. 1325 */ 1326 int 1327 c_label() 1328 { 1329 int status; 1330 int deflt, *defltptr = NULL; 1331 1332 /* 1333 * There must be a current disk type (and therefore a current disk). 1334 */ 1335 if (cur_dtype == NULL) { 1336 err_print("Current Disk Type is not set.\n"); 1337 return (-1); 1338 } 1339 /* 1340 * The current disk must be formatted to label it. 1341 */ 1342 if (!(cur_flags & DISK_FORMATTED)) { 1343 err_print("Current Disk is unformatted.\n"); 1344 return (-1); 1345 } 1346 /* 1347 * Check for a valid fdisk table entry for Solaris 1348 */ 1349 if (!good_fdisk()) { 1350 return (-1); 1351 } 1352 /* 1353 * Check to see if there are any mounted file systems anywhere 1354 * on the current disk. If so, refuse to label the disk, but 1355 * only if the partitions would change for the mounted partitions. 1356 * 1357 */ 1358 if (checkmount((diskaddr_t)-1, (diskaddr_t)-1)) { 1359 /* Bleagh, too descriptive */ 1360 if (check_label_with_mount()) { 1361 err_print("Cannot label disk while it has " 1362 "mounted partitions.\n\n"); 1363 return (-1); 1364 } 1365 } 1366 1367 /* 1368 * check to see if there any partitions being used for swapping 1369 * on the current disk. If so, refuse to label the disk, but 1370 * only if the partitions would change for the mounted partitions. 1371 */ 1372 if (checkswap((diskaddr_t)-1, (diskaddr_t)-1)) { 1373 if (check_label_with_swap()) { 1374 err_print("Cannot label disk while its " 1375 "partitions are currently being used for " 1376 "swapping.\n"); 1377 return (-1); 1378 } 1379 } 1380 1381 /* 1382 * Check to see if any partitions used for svm, vxvm or live upgrade 1383 * are on the disk. If so, refuse to label the disk, but only 1384 * if we are trying to shrink a partition in use. 1385 */ 1386 if (checkdevinuse(cur_disk->disk_name, (diskaddr_t)-1, 1387 (diskaddr_t)-1, 0, 1)) { 1388 err_print("Cannot label disk when " 1389 "partitions are in use as described.\n"); 1390 return (-1); 1391 } 1392 1393 /* 1394 * If there is not a current partition map, warn the user we 1395 * are going to use the default. The default is the first 1396 * partition map we encountered in the data file. If there is 1397 * no default we give up. 1398 */ 1399 if (cur_parts == NULL) { 1400 fmt_print("Current Partition Table is not set, " 1401 "using default.\n"); 1402 cur_disk->disk_parts = cur_parts = cur_dtype->dtype_plist; 1403 if (cur_parts == NULL) { 1404 err_print("No default available, cannot label.\n"); 1405 return (-1); 1406 } 1407 } 1408 /* 1409 * If expert (-e) mode, then ask user if they wish 1410 * to change the current solaris label into an EFI one 1411 */ 1412 if (expert_mode) { 1413 #if defined(_SUNOS_VTOC_8) 1414 int i; 1415 #endif 1416 int choice; 1417 u_ioparam_t ioparam; 1418 struct extvtoc vtoc; 1419 struct dk_label label; 1420 struct dk_gpt *vtoc64; 1421 struct efi_info efinfo; 1422 struct disk_type *dptr; 1423 1424 /* Ask user what label to use */ 1425 fmt_print("[0] SMI Label\n"); 1426 fmt_print("[1] EFI Label\n"); 1427 ioparam.io_bounds.lower = 0; 1428 ioparam.io_bounds.upper = 1; 1429 if (cur_label == L_TYPE_SOLARIS) 1430 deflt = 0; 1431 else 1432 deflt = 1; 1433 defltptr = &deflt; 1434 choice = input(FIO_INT, "Specify Label type", ':', 1435 &ioparam, defltptr, DATA_INPUT); 1436 if ((choice == 0) && (cur_label == L_TYPE_SOLARIS)) { 1437 goto expert_end; 1438 } else if ((choice == 1) && (cur_label == L_TYPE_EFI)) { 1439 goto expert_end; 1440 } 1441 switch (choice) { 1442 case 0: 1443 /* 1444 * EFI label to SMI label 1445 */ 1446 if (cur_dtype->capacity > INFINITY) { 1447 fmt_print("Warning: SMI labels only support up to 2 TB.\n"); 1448 } 1449 1450 if (cur_disk->fdisk_part.systid == EFI_PMBR) { 1451 fmt_print("Warning: This disk has an EFI label. Changing to" 1452 " SMI label will erase all\ncurrent partitions.\n"); 1453 if (check("Continue")) 1454 return (-1); 1455 #if defined(_FIRMWARE_NEEDS_FDISK) 1456 fmt_print("You must use fdisk to delete the current " 1457 "EFI partition and create a new\n" 1458 "Solaris partition before you can convert the " 1459 "label.\n"); 1460 return (-1); 1461 #endif 1462 } 1463 1464 #if defined(_FIRMWARE_NEEDS_FDISK) 1465 if (!(((cur_disk->fdisk_part.systid != SUNIXOS) || 1466 (cur_disk->fdisk_part.systid != SUNIXOS2)) && 1467 (cur_disk->fdisk_part.numsect > 0))) { 1468 fmt_print("You must use fdisk to create a Solaris " 1469 "partition before you can convert the label.\n"); 1470 return (-1); 1471 } 1472 #endif 1473 1474 (void) memset((char *)&label, 0, sizeof (struct dk_label)); 1475 1476 (void) strcpy(x86_devname, cur_disk->disk_name); 1477 if (cur_ctype->ctype_ctype == DKC_DIRECT) 1478 dptr = auto_direct_get_geom_label(cur_file, &label); 1479 else 1480 dptr = auto_sense(cur_file, 1, &label); 1481 if (dptr == NULL) { 1482 fmt_print("Autoconfiguration failed.\n"); 1483 return (-1); 1484 } 1485 1486 pcyl = label.dkl_pcyl; 1487 ncyl = label.dkl_ncyl; 1488 acyl = label.dkl_acyl; 1489 nhead = label.dkl_nhead; 1490 nsect = label.dkl_nsect; 1491 1492 if (delete_disk_type(cur_disk->disk_type) == 0) { 1493 cur_label = L_TYPE_SOLARIS; 1494 cur_disk->label_type = L_TYPE_SOLARIS; 1495 cur_disk->disk_type = dptr; 1496 cur_disk->disk_parts = dptr->dtype_plist; 1497 cur_dtype = dptr; 1498 cur_parts = dptr->dtype_plist; 1499 1500 if (status = write_label()) 1501 err_print("Label failed.\n"); 1502 else 1503 cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 1504 1505 return (status); 1506 } else { 1507 err_print("Label failed.\n"); 1508 return (-1); 1509 } 1510 1511 1512 case 1: 1513 /* 1514 * SMI label to EFI label 1515 */ 1516 1517 1518 fmt_print("Warning: This disk has an SMI label. Changing to " 1519 "EFI label will erase all\ncurrent partitions.\n"); 1520 1521 if (check("Continue")) { 1522 return (-1); 1523 } 1524 1525 if (get_disk_info(cur_file, &efinfo) != 0) { 1526 return (-1); 1527 } 1528 (void) memset((char *)&label, 0, sizeof (struct dk_label)); 1529 label.dkl_pcyl = pcyl; 1530 label.dkl_ncyl = ncyl; 1531 label.dkl_acyl = acyl; 1532 #if defined(_SUNOS_VTOC_16) 1533 label.dkl_bcyl = bcyl; 1534 #endif /* defined(_SUNOC_VTOC_16) */ 1535 label.dkl_nhead = nhead; 1536 label.dkl_nsect = nsect; 1537 #if defined(_SUNOS_VTOC_8) 1538 for (i = 0; i < NDKMAP; i++) { 1539 label.dkl_map[i] = cur_parts->pinfo_map[i]; 1540 } 1541 #endif /* defined(_SUNOS_VTOC_8) */ 1542 label.dkl_magic = DKL_MAGIC; 1543 label.dkl_vtoc = cur_parts->vtoc; 1544 if (label_to_vtoc(&vtoc, &label) == -1) { 1545 return (-1); 1546 } 1547 if (SMI_vtoc_to_EFI(cur_file, &vtoc64) == -1) { 1548 return (-1); 1549 } 1550 if (efi_write(cur_file, vtoc64) != 0) { 1551 err_check(vtoc64); 1552 err_print("Warning: error writing EFI.\n"); 1553 return (-1); 1554 } else { 1555 cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 1556 } 1557 /* 1558 * copy over the EFI vtoc onto the SMI vtoc and return 1559 * okay. 1560 */ 1561 dptr = auto_efi_sense(cur_file, &efinfo); 1562 if (dptr == NULL) { 1563 fmt_print("Autoconfiguration failed.\n"); 1564 return (-1); 1565 } 1566 1567 cur_label = L_TYPE_EFI; 1568 cur_disk->label_type = L_TYPE_EFI; 1569 cur_disk->disk_type = dptr; 1570 cur_disk->disk_parts = dptr->dtype_plist; 1571 cur_dtype = dptr; 1572 cur_parts = dptr->dtype_plist; 1573 cur_parts->etoc = vtoc64; 1574 1575 ncyl = pcyl = nsect = psect = acyl = phead = 0; 1576 1577 /* 1578 * Get the Solais Fdisk Partition information. 1579 */ 1580 (void) copy_solaris_part(&cur_disk->fdisk_part); 1581 1582 return (0); 1583 } 1584 } 1585 1586 expert_end: 1587 /* 1588 * Make sure the user is serious. 1589 */ 1590 if (check("Ready to label disk, continue")) { 1591 return (-1); 1592 } 1593 /* 1594 * Write the labels out (this will also notify unix) and 1595 * return status. 1596 */ 1597 fmt_print("\n"); 1598 if (status = write_label()) 1599 err_print("Label failed.\n"); 1600 return (status); 1601 } 1602 1603 /* 1604 * This routine implements the 'analyze' command. It simply runs 1605 * the analyze menu. 1606 */ 1607 int 1608 c_analyze() 1609 { 1610 1611 /* 1612 * There must be a current disk type (and therefor a current disk). 1613 */ 1614 if (cur_dtype == NULL) { 1615 err_print("Current Disk Type is not set.\n"); 1616 return (-1); 1617 } 1618 cur_menu++; 1619 last_menu = cur_menu; 1620 1621 /* 1622 * Run the menu. 1623 */ 1624 run_menu(menu_analyze, "ANALYZE", "analyze", 0); 1625 cur_menu--; 1626 return (0); 1627 } 1628 1629 /* 1630 * This routine implements the 'defect' command. It simply runs 1631 * the defect menu. 1632 */ 1633 int 1634 c_defect() 1635 { 1636 int i; 1637 1638 /* 1639 * There must be a current disk type (and therefor a current disk). 1640 */ 1641 if (cur_dtype == NULL) { 1642 err_print("Current Disk Type is not set.\n"); 1643 return (-1); 1644 } 1645 1646 /* 1647 * Check for the defect management and list management ops and 1648 * display appropriate message. 1649 */ 1650 if ((cur_ops->op_ex_man == NULL) && (cur_ops->op_ex_cur == NULL) && 1651 (cur_ops->op_create == NULL) && (cur_ops->op_wr_cur == NULL)) { 1652 err_print("Controller does not support defect management\n"); 1653 err_print("or disk supports automatic defect management.\n"); 1654 return (-1); 1655 } 1656 cur_menu++; 1657 last_menu = cur_menu; 1658 1659 /* 1660 * Lock out interrupt while we manipulate the defect lists. 1661 */ 1662 enter_critical(); 1663 /* 1664 * If the working list is null but there is a current list, 1665 * update the working list to be a copy of the current list. 1666 */ 1667 if ((work_list.list == NULL) && (cur_list.list != NULL)) { 1668 work_list.header = cur_list.header; 1669 work_list.list = (struct defect_entry *)zalloc( 1670 LISTSIZE(work_list.header.count) * SECSIZE); 1671 for (i = 0; i < work_list.header.count; i++) 1672 *(work_list.list + i) = *(cur_list.list + i); 1673 work_list.flags = cur_list.flags & LIST_PGLIST; 1674 } 1675 exit_critical(); 1676 /* 1677 * Run the menu. 1678 */ 1679 run_menu(menu_defect, "DEFECT", "defect", 0); 1680 cur_menu--; 1681 1682 /* 1683 * If the user has modified the working list but not committed 1684 * it, warn him that he is probably making a mistake. 1685 */ 1686 if (work_list.flags & LIST_DIRTY) { 1687 if (!EMBEDDED_SCSI) { 1688 err_print( 1689 "Warning: working defect list modified; but not committed.\n"); 1690 if (!check( 1691 "Do you wish to commit changes to current defect list")) 1692 (void) do_commit(); 1693 } 1694 } 1695 return (0); 1696 } 1697 1698 /* 1699 * This routine implements the 'backup' command. It allows the user 1700 * to search for backup labels on the current disk. This is useful 1701 * if the primary label was lost and the user wishes to recover the 1702 * partition information for the disk. The disk is relabeled and 1703 * the current defect list is written out if a backup label is found. 1704 */ 1705 int 1706 c_backup() 1707 { 1708 struct dk_label label; 1709 struct disk_type *dtype; 1710 struct partition_info *parts, *plist; 1711 diskaddr_t bn; 1712 int sec, head, i; 1713 1714 /* 1715 * There must be a current disk type (and therefore a current disk). 1716 */ 1717 if (cur_dtype == NULL) { 1718 err_print("Current Disk Type is not set.\n"); 1719 return (-1); 1720 } 1721 /* 1722 * The disk must be formatted to read backup labels. 1723 */ 1724 if (!(cur_flags & DISK_FORMATTED)) { 1725 err_print("Current Disk is unformatted.\n"); 1726 return (-1); 1727 } 1728 /* 1729 * Check for a valid fdisk table entry for Solaris 1730 */ 1731 if (!good_fdisk()) { 1732 return (-1); 1733 } 1734 /* 1735 * If we found a primary label on this disk, make sure 1736 * the user is serious. 1737 */ 1738 if (cur_disk->label_type == L_TYPE_EFI) { 1739 if (((cur_disk->disk_parts->etoc->efi_flags & 1740 EFI_GPT_PRIMARY_CORRUPT) == 0) && 1741 check("Disk has a primary label, still continue")) 1742 return (-1); 1743 fmt_print("Restoring primary label.\n"); 1744 if (write_label()) { 1745 err_print("Failed\n"); 1746 return (-1); 1747 } 1748 return (0); 1749 } else if (((cur_disk->disk_flags & (DSK_LABEL | DSK_LABEL_DIRTY)) == 1750 DSK_LABEL) && 1751 (check("Disk has a primary label, still continue"))) { 1752 return (-1); 1753 } 1754 fmt_print("Searching for backup labels..."); 1755 (void) fflush(stdout); 1756 /* 1757 * Some disks have the backup labels in a strange place. 1758 */ 1759 if (cur_ctype->ctype_flags & CF_BLABEL) 1760 head = 2; 1761 else 1762 head = nhead - 1; 1763 /* 1764 * Loop through each copy of the backup label. 1765 */ 1766 for (sec = 1; ((sec < BAD_LISTCNT * 2 + 1) && (sec < nsect)); 1767 sec += 2) { 1768 bn = chs2bn(ncyl + acyl - 1, head, sec) + solaris_offset; 1769 /* 1770 * Attempt to read it. 1771 */ 1772 if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, 1773 1, (char *)&label, F_NORMAL, NULL)) { 1774 continue; 1775 } 1776 /* 1777 * Verify that it is a reasonable label. 1778 */ 1779 if (!checklabel(&label)) 1780 continue; 1781 if (trim_id(label.dkl_asciilabel)) 1782 continue; 1783 /* 1784 * Lock out interrupts while we manipulate lists. 1785 */ 1786 enter_critical(); 1787 fmt_print("found.\n"); 1788 /* 1789 * Find out which disk type the backup label claims. 1790 */ 1791 for (dtype = cur_ctype->ctype_dlist; dtype != NULL; 1792 dtype = dtype->dtype_next) 1793 if (dtype_match(&label, dtype)) 1794 break; 1795 /* 1796 * If it disagrees with our current type, something 1797 * real bad is happening. 1798 */ 1799 if (dtype != cur_dtype) { 1800 if (dtype == NULL) { 1801 fmt_print("\ 1802 Unknown disk type in backup label\n"); 1803 exit_critical(); 1804 return (-1); 1805 } 1806 fmt_print("Backup label claims different type:\n"); 1807 fmt_print(" <%s cyl %d alt %d hd %d sec %d>\n", 1808 label.dkl_asciilabel, label.dkl_ncyl, 1809 label.dkl_acyl, label.dkl_nhead, 1810 label.dkl_nsect); 1811 if (check("Continue")) { 1812 exit_critical(); 1813 return (-1); 1814 } 1815 cur_dtype = dtype; 1816 } 1817 /* 1818 * Try to match the partition map with a known map. 1819 */ 1820 for (parts = dtype->dtype_plist; parts != NULL; 1821 parts = parts->pinfo_next) 1822 if (parts_match(&label, parts)) 1823 break; 1824 /* 1825 * If we couldn't match it, allocate space for a new one, 1826 * fill in the info, and add it to the list. The name 1827 * for the new map is derived from the disk name. 1828 */ 1829 if (parts == NULL) { 1830 parts = (struct partition_info *) 1831 zalloc(sizeof (struct partition_info)); 1832 plist = dtype->dtype_plist; 1833 if (plist == NULL) 1834 dtype->dtype_plist = parts; 1835 else { 1836 while (plist->pinfo_next != NULL) 1837 plist = plist->pinfo_next; 1838 plist->pinfo_next = parts; 1839 } 1840 parts->pinfo_name = alloc_string("original"); 1841 for (i = 0; i < NDKMAP; i++) 1842 1843 #if defined(_SUNOS_VTOC_8) 1844 parts->pinfo_map[i] = label.dkl_map[i]; 1845 1846 #elif defined(_SUNOS_VTOC_16) 1847 parts->pinfo_map[i].dkl_cylno = 1848 label.dkl_vtoc.v_part[i].p_start / spc(); 1849 parts->pinfo_map[i].dkl_nblk = 1850 label.dkl_vtoc.v_part[i].p_size; 1851 #else 1852 #error No VTOC layout defined. 1853 #endif /* defined(_SUNOS_VTOC_8) */ 1854 parts->vtoc = label.dkl_vtoc; 1855 } 1856 /* 1857 * We now have a partition map. Make it the current map. 1858 */ 1859 cur_disk->disk_parts = cur_parts = parts; 1860 exit_critical(); 1861 /* 1862 * Rewrite the labels and defect lists, as appropriate. 1863 */ 1864 if (EMBEDDED_SCSI) { 1865 fmt_print("Restoring primary label.\n"); 1866 if (write_label()) 1867 return (-1); 1868 } else { 1869 fmt_print("Restoring primary label and defect list.\n"); 1870 if (write_label()) 1871 return (-1); 1872 if (cur_list.list != NULL) 1873 write_deflist(&cur_list); 1874 } 1875 fmt_print("\n"); 1876 return (0); 1877 } 1878 /* 1879 * If we didn't find any backup labels, say so. 1880 */ 1881 fmt_print("not found.\n\n"); 1882 return (0); 1883 } 1884 1885 /* 1886 * This routine is called by c_verify() for an EFI labeled disk 1887 */ 1888 static int 1889 c_verify_efi() 1890 { 1891 struct efi_info efi_info; 1892 struct partition_info tmp_pinfo; 1893 int status; 1894 1895 status = read_efi_label(cur_file, &efi_info); 1896 if (status != 0) { 1897 err_print("Warning: Could not read label.\n"); 1898 return (-1); 1899 } 1900 if (cur_parts->etoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) { 1901 err_print("Reading the primary EFI GPT label "); 1902 err_print("failed. Using backup label.\n"); 1903 err_print("Use the 'backup' command to restore "); 1904 err_print("the primary label.\n"); 1905 } 1906 tmp_pinfo.etoc = efi_info.e_parts; 1907 fmt_print("\n"); 1908 if (cur_parts->etoc->efi_parts[8].p_name) { 1909 fmt_print("Volume name = <%8s>\n", 1910 cur_parts->etoc->efi_parts[8].p_name); 1911 } else { 1912 fmt_print("Volume name = < >\n"); 1913 } 1914 fmt_print("ascii name = "); 1915 print_efi_string(efi_info.vendor, efi_info.product, 1916 efi_info.revision, efi_info.capacity); 1917 fmt_print("\n"); 1918 1919 fmt_print("bytes/sector = %d\n", DEV_BSIZE); 1920 fmt_print("sectors = %llu\n", cur_parts->etoc->efi_last_lba); 1921 fmt_print("accessible sectors = %llu\n", 1922 cur_parts->etoc->efi_last_u_lba); 1923 1924 print_map(&tmp_pinfo); 1925 return (0); 1926 } 1927 1928 /* 1929 * This routine implements the 'verify' command. It allows the user 1930 * to read the labels on the current disk. 1931 */ 1932 int 1933 c_verify() 1934 { 1935 struct dk_label p_label, b_label, *label; 1936 struct partition_info tmp_pinfo; 1937 diskaddr_t bn; 1938 int sec, head, i, status; 1939 int p_label_bad = 0; 1940 int b_label_bad = 0; 1941 int p_label_found = 0; 1942 int b_label_found = 0; 1943 char id_str[128]; 1944 1945 /* 1946 * There must be a current disk type (and therefore a current disk). 1947 */ 1948 if (cur_dtype == NULL) { 1949 err_print("Current Disk Type is not set.\n"); 1950 return (-1); 1951 } 1952 /* 1953 * The disk must be formatted to read labels. 1954 */ 1955 if (!(cur_flags & DISK_FORMATTED)) { 1956 err_print("Current Disk is unformatted.\n"); 1957 return (-1); 1958 } 1959 /* 1960 * Check for a valid fdisk table entry for Solaris 1961 */ 1962 if (!good_fdisk()) { 1963 return (-1); 1964 } 1965 /* 1966 * Branch off here if the disk is EFI labelled. 1967 */ 1968 if (cur_label == L_TYPE_EFI) { 1969 return (c_verify_efi()); 1970 } 1971 /* 1972 * Attempt to read the primary label. 1973 */ 1974 status = read_label(cur_file, &p_label); 1975 if (status == -1) { 1976 err_print("Warning: Could not read primary label.\n"); 1977 p_label_bad = 1; 1978 } else { 1979 /* 1980 * Verify that it is a reasonable label. 1981 */ 1982 /* 1983 * Save complete ascii string for printing later. 1984 */ 1985 (void) strncpy(id_str, p_label.dkl_asciilabel, 128); 1986 1987 if ((!checklabel((struct dk_label *)&p_label)) || 1988 (trim_id(p_label.dkl_asciilabel))) { 1989 err_print("\ 1990 Warning: Primary label appears to be corrupt.\n"); 1991 p_label_bad = 1; 1992 } else { 1993 p_label_found = 1; 1994 /* 1995 * Make sure it matches current label 1996 */ 1997 if ((!dtype_match(&p_label, cur_dtype)) || 1998 (!parts_match(&p_label, cur_parts))) { 1999 err_print("\ 2000 Warning: Primary label on disk appears to be different from\ncurrent label.\n"); 2001 p_label_bad = 1; 2002 } 2003 } 2004 } 2005 2006 /* 2007 * Read backup labels. 2008 * Some disks have the backup labels in a strange place. 2009 */ 2010 if (cur_ctype->ctype_flags & CF_BLABEL) 2011 head = 2; 2012 else 2013 head = nhead - 1; 2014 /* 2015 * Loop through each copy of the backup label. 2016 */ 2017 for (sec = 1; ((sec < BAD_LISTCNT * 2 + 1) && (sec < nsect)); 2018 sec += 2) { 2019 bn = chs2bn(ncyl + acyl - 1, head, sec) + solaris_offset; 2020 /* 2021 * Attempt to read it. 2022 */ 2023 if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, 2024 1, (char *)&b_label, F_NORMAL, NULL)) 2025 continue; 2026 /* 2027 * Verify that it is a reasonable label. 2028 */ 2029 if (!checklabel(&b_label)) 2030 continue; 2031 2032 /* 2033 * Save complete label only if no primary label exists 2034 */ 2035 if (!p_label_found) 2036 (void) strncpy(id_str, b_label.dkl_asciilabel, 128); 2037 2038 if (trim_id(b_label.dkl_asciilabel)) 2039 continue; 2040 b_label_found = 1; 2041 /* 2042 * Compare against primary label 2043 */ 2044 if (p_label_found) { 2045 if ((strcmp(b_label.dkl_asciilabel, 2046 p_label.dkl_asciilabel) != 0) || 2047 (b_label.dkl_ncyl != p_label.dkl_ncyl) || 2048 (b_label.dkl_acyl != p_label.dkl_acyl) || 2049 (b_label.dkl_nhead != p_label.dkl_nhead) || 2050 (b_label.dkl_nsect != p_label.dkl_nsect)) { 2051 b_label_bad = 1; 2052 } else { 2053 for (i = 0; i < NDKMAP; i++) { 2054 #if defined(_SUNOS_VTOC_8) 2055 if ((b_label.dkl_map[i].dkl_cylno != 2056 p_label.dkl_map[i].dkl_cylno) || 2057 (b_label.dkl_map[i].dkl_nblk != 2058 p_label.dkl_map[i].dkl_nblk)) { 2059 b_label_bad = 1; 2060 break; 2061 } 2062 2063 #elif defined(_SUNOS_VTOC_16) 2064 if ((b_label.dkl_vtoc.v_part[i].p_tag != 2065 p_label.dkl_vtoc.v_part[i].p_tag) || 2066 (b_label.dkl_vtoc.v_part[i].p_flag != 2067 p_label.dkl_vtoc.v_part[i].p_flag) || 2068 (b_label.dkl_vtoc.v_part[i].p_start != 2069 p_label.dkl_vtoc.v_part[i].p_start) || 2070 (b_label.dkl_vtoc.v_part[i].p_size != 2071 p_label.dkl_vtoc.v_part[i].p_size)) { 2072 b_label_bad = 1; 2073 break; 2074 } 2075 #else 2076 #error No VTOC layout defined. 2077 #endif /* defined(_SUNOS_VTOC_8) */ 2078 } 2079 } 2080 } 2081 if (b_label_bad) 2082 err_print( 2083 "Warning: Primary and backup labels do not match.\n"); 2084 break; 2085 } 2086 /* 2087 * If we didn't find any backup labels, say so. 2088 */ 2089 if (!b_label_found) 2090 err_print("Warning: Could not read backup labels.\n"); 2091 2092 if ((!b_label_found) || (p_label_bad) || (b_label_bad)) 2093 err_print("\n\ 2094 Warning: Check the current partitioning and 'label' the disk or use the\n\ 2095 \t 'backup' command.\n"); 2096 2097 /* 2098 * Print label information. 2099 */ 2100 if (p_label_found) { 2101 fmt_print("\nPrimary label contents:\n"); 2102 label = &p_label; 2103 } else if (b_label_found) { 2104 fmt_print("\nBackup label contents:\n"); 2105 label = &b_label; 2106 } else { 2107 return (0); 2108 } 2109 2110 /* 2111 * Must put info into partition_info struct for 2112 * for print routine. 2113 */ 2114 bzero(&tmp_pinfo, sizeof (struct partition_info)); 2115 for (i = 0; i < NDKMAP; i++) { 2116 2117 #if defined(_SUNOS_VTOC_8) 2118 tmp_pinfo.pinfo_map[i] = label->dkl_map[i]; 2119 2120 #elif defined(_SUNOS_VTOC_16) 2121 tmp_pinfo.pinfo_map[i].dkl_cylno = 2122 label->dkl_vtoc.v_part[i].p_start / spc(); 2123 tmp_pinfo.pinfo_map[i].dkl_nblk = 2124 label->dkl_vtoc.v_part[i].p_size; 2125 #else 2126 #error No VTOC layout defined. 2127 #endif /* defined(_SUNOS_VTOC_8) */ 2128 } 2129 tmp_pinfo.vtoc = label->dkl_vtoc; 2130 2131 fmt_print("\n"); 2132 fmt_print("Volume name = <%8s>\n", label->dkl_vtoc.v_volume); 2133 fmt_print("ascii name = <%s>\n", id_str); 2134 fmt_print("pcyl = %4d\n", label->dkl_pcyl); 2135 fmt_print("ncyl = %4d\n", label->dkl_ncyl); 2136 fmt_print("acyl = %4d\n", label->dkl_acyl); 2137 2138 #if defined(_SUNOS_VTOC_16) 2139 fmt_print("bcyl = %4d\n", label->dkl_bcyl); 2140 #endif /* defined(_SUNOS_VTOC_16) */ 2141 2142 fmt_print("nhead = %4d\n", label->dkl_nhead); 2143 fmt_print("nsect = %4d\n", label->dkl_nsect); 2144 2145 print_map(&tmp_pinfo); 2146 return (0); 2147 } 2148 2149 2150 /* 2151 * This command implements the inquiry command, for embedded SCSI 2152 * disks only, which issues a SCSI inquiry command, and 2153 * displays the resulting vendor, product id and revision level. 2154 */ 2155 int 2156 c_inquiry() 2157 { 2158 char inqbuf[255]; 2159 struct scsi_inquiry *inq; 2160 2161 assert(SCSI); 2162 2163 inq = (struct scsi_inquiry *)inqbuf; 2164 2165 if (uscsi_inquiry(cur_file, inqbuf, sizeof (inqbuf))) { 2166 err_print("Failed\n"); 2167 return (-1); 2168 } else { 2169 fmt_print("Vendor: "); 2170 print_buf(inq->inq_vid, sizeof (inq->inq_vid)); 2171 fmt_print("\nProduct: "); 2172 print_buf(inq->inq_pid, sizeof (inq->inq_pid)); 2173 fmt_print("\nRevision: "); 2174 print_buf(inq->inq_revision, sizeof (inq->inq_revision)); 2175 fmt_print("\n"); 2176 } 2177 2178 return (0); 2179 } 2180 2181 2182 /* 2183 * This routine allows the user to set the 8-character 2184 * volume name in the vtoc. It then writes both the 2185 * primary and backup labels onto the current disk. 2186 */ 2187 int 2188 c_volname() 2189 { 2190 int status; 2191 char *prompt; 2192 union { 2193 int xfoo; 2194 char defvolname[LEN_DKL_VVOL+1]; 2195 } x; 2196 char s1[MAXPATHLEN], nclean[MAXPATHLEN]; 2197 char *volname; 2198 2199 2200 /* 2201 * There must be a current disk type (and therefore a current disk). 2202 */ 2203 if (cur_dtype == NULL) { 2204 err_print("Current Disk Type is not set.\n"); 2205 return (-1); 2206 } 2207 /* 2208 * The current disk must be formatted to label it. 2209 */ 2210 if (!(cur_flags & DISK_FORMATTED)) { 2211 err_print("Current Disk is unformatted.\n"); 2212 return (-1); 2213 } 2214 /* 2215 * Check for a valid fdisk table entry for Solaris 2216 */ 2217 if (!good_fdisk()) { 2218 return (-1); 2219 } 2220 /* 2221 * The current disk must be formatted to label it. 2222 */ 2223 if (cur_parts == NULL) { 2224 err_print( 2225 "Please select a partition map for the disk first.\n"); 2226 return (-1); 2227 } 2228 2229 /* 2230 * Check to see if there are any mounted file systems anywhere 2231 * on the current disk. If so, refuse to label the disk, but 2232 * only if the partitions would change for the mounted partitions. 2233 * 2234 */ 2235 if (checkmount((diskaddr_t)-1, (diskaddr_t)-1)) { 2236 /* Bleagh, too descriptive */ 2237 if (check_label_with_mount()) { 2238 err_print( 2239 "Cannot label disk while it has mounted partitions.\n\n"); 2240 return (-1); 2241 } 2242 } 2243 2244 /* 2245 * Check to see if there are partitions being used for swapping 2246 * on the current disk. If so, refuse to label the disk, but 2247 * only if the partitions would change for the swap partitions. 2248 * 2249 */ 2250 if (checkswap((diskaddr_t)-1, (diskaddr_t)-1)) { 2251 /* Bleagh, too descriptive */ 2252 if (check_label_with_swap()) { 2253 err_print( 2254 "Cannot label disk while its partitions are currently \ 2255 being used for swapping.\n\n"); 2256 return (-1); 2257 } 2258 } 2259 2260 /* 2261 * Check to see if any partitions used for svm, vxvm, ZFS zpool 2262 * or live upgrade are on the disk. If so, refuse to label the 2263 * disk, but only if we are trying to shrink a partition in 2264 * use. 2265 */ 2266 if (checkdevinuse(cur_disk->disk_name, (diskaddr_t)-1, 2267 (diskaddr_t)-1, 0, 1)) { 2268 err_print("Cannot label disk while its partitions " 2269 "are in use as described.\n"); 2270 return (-1); 2271 } 2272 2273 /* 2274 * Prompt for the disk volume name. 2275 */ 2276 prompt = "Enter 8-character volume name (remember quotes)"; 2277 bzero(x.defvolname, LEN_DKL_VVOL+1); 2278 bcopy(cur_disk->v_volume, x.defvolname, LEN_DKL_VVOL); 2279 /* 2280 * Get the input using "get_inputline" since 2281 * input would never return null string. 2282 */ 2283 fmt_print("%s[\"%s\"]:", prompt, x.defvolname); 2284 2285 /* 2286 * Get input from the user. 2287 */ 2288 get_inputline(nclean, MAXPATHLEN); 2289 clean_token(s1, nclean); 2290 /* 2291 * check for return. 2292 */ 2293 if (s1[0] == 0) { 2294 volname = x.defvolname; 2295 } else { 2296 /* 2297 * remove the " mark from volname. 2298 */ 2299 if (s1[0] == '"') { 2300 int i = 1; 2301 volname = &s1[1]; 2302 while (s1[i] != '"' && s1[i] != '\0') 2303 i++; 2304 s1[i] = '\0'; 2305 clean_token(nclean, volname); 2306 volname = nclean; 2307 } else { 2308 (void) sscanf(&s1[0], "%1024s", nclean); 2309 volname = nclean; 2310 }; 2311 } 2312 /* 2313 * Make sure the user is serious. 2314 */ 2315 if (check("Ready to label disk, continue")) { 2316 fmt_print("\n"); 2317 return (-1); 2318 } 2319 /* 2320 * Use the volume name chosen above 2321 */ 2322 bzero(cur_disk->v_volume, LEN_DKL_VVOL); 2323 bcopy(volname, cur_disk->v_volume, min((int)strlen(volname), 2324 LEN_DKL_VVOL)); 2325 if (cur_label == L_TYPE_EFI) { 2326 bzero(cur_parts->etoc->efi_parts[8].p_name, LEN_DKL_VVOL); 2327 bcopy(volname, cur_parts->etoc->efi_parts[8].p_name, 2328 LEN_DKL_VVOL); 2329 } 2330 /* 2331 * Write the labels out (this will also notify unix) and 2332 * return status. 2333 */ 2334 fmt_print("\n"); 2335 if (status = write_label()) 2336 err_print("Label failed.\n"); 2337 return (status); 2338 } 2339