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