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