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