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