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                     (cur_disk->fdisk_part.systid != EFI_PMBR))
1568                         deflt = L_TYPE_SOLARIS;
1569                 else
1570                         deflt = L_TYPE_EFI;
1571                 defltptr = &deflt;
1572                 choice = input(FIO_INT, "Specify Label type", ':',
1573                     &ioparam, defltptr, DATA_INPUT);
1574                 if ((choice == L_TYPE_SOLARIS) &&
1575                     (cur_label == L_TYPE_SOLARIS) &&
1576                     (cur_disk->fdisk_part.systid != EFI_PMBR)) {
1577                         goto expert_end;
1578                 } else if ((choice == L_TYPE_EFI) &&
1579                     (cur_label == L_TYPE_EFI)) {
1580                         goto expert_end;
1581                 }
1582                 switch (choice) {
1583                 case L_TYPE_SOLARIS:
1584                 /*
1585                  * EFI label to SMI label
1586                  */
1587                 if (cur_dtype->capacity > INFINITY) {
1588                         fmt_print("Warning: SMI labels only support up to "
1589                             "2 TB.\n");
1590                 }
1591 
1592                 if (cur_disk->fdisk_part.systid == EFI_PMBR) {
1593                         fmt_print("Warning: This disk has an EFI label. "
1594                             "Changing to SMI label will erase all\n"
1595                             "current partitions.\n");
1596                         if (check("Continue"))
1597                         return (-1);
1598 #if defined(_FIRMWARE_NEEDS_FDISK)
1599                         fmt_print("You must use fdisk to delete the current "
1600                             "EFI partition and create a new\n"
1601                             "Solaris partition before you can convert the "
1602                             "label.\n");
1603                         return (-1);
1604 #endif
1605                 }
1606 
1607 #if defined(_FIRMWARE_NEEDS_FDISK)
1608                 if (!(((cur_disk->fdisk_part.systid != SUNIXOS) ||
1609                     (cur_disk->fdisk_part.systid != SUNIXOS2)) &&
1610                     (cur_disk->fdisk_part.numsect > 0))) {
1611                         fmt_print("You must use fdisk to create a Solaris "
1612                             "partition before you can convert the label.\n");
1613                         return (-1);
1614                 }
1615 #endif
1616 
1617                 (void) memset((char *)&label, 0, sizeof (struct dk_label));
1618 
1619                 (void) strcpy(x86_devname, cur_disk->disk_name);
1620                 if (cur_ctype->ctype_ctype == DKC_DIRECT)
1621                         dptr = auto_direct_get_geom_label(cur_file,  &label);
1622                 else
1623                         dptr = auto_sense(cur_file, 1, &label);
1624                 if (dptr == NULL) {
1625                         fmt_print("Autoconfiguration failed.\n");
1626                         return (-1);
1627                 }
1628 
1629                 pcyl = label.dkl_pcyl;
1630                 ncyl = label.dkl_ncyl;
1631                 acyl = label.dkl_acyl;
1632                 nhead = label.dkl_nhead;
1633                 nsect = label.dkl_nsect;
1634 
1635                 if (delete_disk_type(cur_disk->disk_type) == 0) {
1636                         cur_label = L_TYPE_SOLARIS;
1637                         cur_disk->label_type = L_TYPE_SOLARIS;
1638                         cur_disk->disk_type = dptr;
1639                         cur_disk->disk_parts = dptr->dtype_plist;
1640                         cur_dtype = dptr;
1641                         cur_parts = dptr->dtype_plist;
1642 
1643                         if (status = write_label())
1644                                 err_print("Label failed.\n");
1645                         else
1646                                 cur_disk->disk_flags &= ~DSK_LABEL_DIRTY;
1647 
1648                         return (status);
1649                 } else {
1650                         err_print("Label failed.\n");
1651                         return (-1);
1652                 }
1653 
1654 
1655                 case L_TYPE_EFI:
1656                 /*
1657                  * SMI label to EFI label
1658                  */
1659 
1660                 if ((cur_disk->fdisk_part.systid == SUNIXOS) ||
1661                     (cur_disk->fdisk_part.systid == SUNIXOS2)) {
1662                         fmt_print("Warning: This disk has an SMI label. "
1663                             "Changing to EFI label will erase all\ncurrent "
1664                             "partitions.\n");
1665                         if (check("Continue")) {
1666                                 return (-1);
1667                         }
1668                 }
1669 
1670                 if (get_disk_info(cur_file, &efinfo) != 0) {
1671                         return (-1);
1672                 }
1673                 (void) memset((char *)&label, 0, sizeof (struct dk_label));
1674                 label.dkl_pcyl = pcyl;
1675                 label.dkl_ncyl = ncyl;
1676                 label.dkl_acyl = acyl;
1677 #if defined(_SUNOS_VTOC_16)
1678                 label.dkl_bcyl = bcyl;
1679 #endif                  /* defined(_SUNOC_VTOC_16) */
1680                 label.dkl_nhead = nhead;
1681                 label.dkl_nsect = nsect;
1682 #if defined(_SUNOS_VTOC_8)
1683                 for (i = 0; i < NDKMAP; i++) {
1684                         label.dkl_map[i] = cur_parts->pinfo_map[i];
1685                 }
1686 #endif                  /* defined(_SUNOS_VTOC_8) */
1687                 label.dkl_magic = DKL_MAGIC;
1688                 label.dkl_vtoc = cur_parts->vtoc;
1689                 if (label_to_vtoc(&vtoc, &label) == -1) {
1690                         return (-1);
1691                 }
1692                 if (SMI_vtoc_to_EFI(cur_file, &vtoc64) == -1) {
1693                         return (-1);
1694                 }
1695                 if (efi_write(cur_file, vtoc64) != 0) {
1696                         err_check(vtoc64);
1697                         err_print("Warning: error writing EFI.\n");
1698                         return (-1);
1699                 } else {
1700                         cur_disk->disk_flags &= ~DSK_LABEL_DIRTY;
1701                 }
1702                 /*
1703                  * copy over the EFI vtoc onto the SMI vtoc and return
1704                  * okay.
1705                  */
1706                 dptr = auto_efi_sense(cur_file, &efinfo);
1707                 if (dptr == NULL) {
1708                         fmt_print("Autoconfiguration failed.\n");
1709                         return (-1);
1710                 }
1711 
1712                 cur_label = L_TYPE_EFI;
1713                 cur_disk->label_type = L_TYPE_EFI;
1714                 cur_disk->disk_type = dptr;
1715                 cur_disk->disk_parts = dptr->dtype_plist;
1716                 cur_dtype = dptr;
1717                 cur_parts = dptr->dtype_plist;
1718                 cur_parts->etoc = vtoc64;
1719 
1720                 ncyl = pcyl = nsect = psect = acyl = phead = 0;
1721 
1722                 /*
1723                  * Get the Solais Fdisk Partition information.
1724                  */
1725                 (void) copy_solaris_part(&cur_disk->fdisk_part);
1726 
1727                 return (0);
1728                 }
1729         }
1730 
1731 expert_end:
1732         /*
1733          * Make sure the user is serious.
1734          */
1735         if (check("Ready to label disk, continue")) {
1736                 return (-1);
1737         }
1738         /*
1739          * Write the labels out (this will also notify unix) and
1740          * return status.
1741          */
1742         fmt_print("\n");
1743         if (status = write_label())
1744                 err_print("Label failed.\n");
1745         return (status);
1746 }
1747 
1748 /*
1749  * This routine implements the 'analyze' command.  It simply runs
1750  * the analyze menu.
1751  */
1752 int
1753 c_analyze()
1754 {
1755 
1756         /*
1757          * There must be a current disk type (and therefor a current disk).
1758          */
1759         if (cur_dtype == NULL) {
1760                 err_print("Current Disk Type is not set.\n");
1761                 return (-1);
1762         }
1763         cur_menu++;
1764         last_menu = cur_menu;
1765 
1766         /*
1767          * Run the menu.
1768          */
1769         run_menu(menu_analyze, "ANALYZE", "analyze", 0);
1770         cur_menu--;
1771         return (0);
1772 }
1773 
1774 /*
1775  * This routine implements the 'defect' command.  It simply runs
1776  * the defect menu.
1777  */
1778 int
1779 c_defect()
1780 {
1781         int     i;
1782 
1783         /*
1784          * There must be a current disk type (and therefor a current disk).
1785          */
1786         if (cur_dtype == NULL) {
1787                 err_print("Current Disk Type is not set.\n");
1788                 return (-1);
1789         }
1790 
1791         /*
1792          * Check for the defect management and list management ops and
1793          * display appropriate message.
1794          */
1795         if ((cur_ops->op_ex_man == NULL) && (cur_ops->op_ex_cur == NULL) &&
1796             (cur_ops->op_create == NULL) && (cur_ops->op_wr_cur == NULL)) {
1797                 err_print("Controller does not support defect management\n");
1798                 err_print("or disk supports automatic defect management.\n");
1799                 return (-1);
1800         }
1801         cur_menu++;
1802         last_menu = cur_menu;
1803 
1804         /*
1805          * Lock out interrupt while we manipulate the defect lists.
1806          */
1807         enter_critical();
1808         /*
1809          * If the working list is null but there is a current list,
1810          * update the working list to be a copy of the current list.
1811          */
1812         if ((work_list.list == NULL) && (cur_list.list != NULL)) {
1813                 work_list.header = cur_list.header;
1814                 work_list.list = (struct defect_entry *)zalloc(
1815                     deflist_size(cur_blksz, work_list.header.count) *
1816                     cur_blksz);
1817                 for (i = 0; i < work_list.header.count; i++)
1818                         *(work_list.list + i) = *(cur_list.list + i);
1819                 work_list.flags = cur_list.flags & LIST_PGLIST;
1820         }
1821         exit_critical();
1822         /*
1823          * Run the menu.
1824          */
1825         run_menu(menu_defect, "DEFECT", "defect", 0);
1826         cur_menu--;
1827 
1828         /*
1829          * If the user has modified the working list but not committed
1830          * it, warn him that he is probably making a mistake.
1831          */
1832         if (work_list.flags & LIST_DIRTY) {
1833                 if (!EMBEDDED_SCSI) {
1834                         err_print(
1835                 "Warning: working defect list modified; but not committed.\n");
1836                         if (!check(
1837                 "Do you wish to commit changes to current defect list"))
1838                         (void) do_commit();
1839                 }
1840         }
1841         return (0);
1842 }
1843 
1844 /*
1845  * This routine implements the 'backup' command.  It allows the user
1846  * to search for backup labels on the current disk.  This is useful
1847  * if the primary label was lost and the user wishes to recover the
1848  * partition information for the disk. The disk is relabeled and
1849  * the current defect list is written out if a backup label is found.
1850  */
1851 int
1852 c_backup()
1853 {
1854         struct  dk_label label;
1855         struct  disk_type *dtype;
1856         struct  partition_info *parts, *plist;
1857         diskaddr_t      bn;
1858         int     sec, head, i;
1859         char    *buf;
1860 
1861         /*
1862          * There must be a current disk type (and therefore a current disk).
1863          */
1864         if (cur_dtype == NULL) {
1865                 err_print("Current Disk Type is not set.\n");
1866                 return (-1);
1867         }
1868         /*
1869          * The disk must be formatted to read backup labels.
1870          */
1871         if (!(cur_flags & DISK_FORMATTED)) {
1872                 err_print("Current Disk is unformatted.\n");
1873                 return (-1);
1874         }
1875         /*
1876          * Check for a valid fdisk table entry for Solaris
1877          */
1878         if (!good_fdisk()) {
1879                 return (-1);
1880         }
1881         /*
1882          * If we found a primary label on this disk, make sure
1883          * the user is serious.
1884          */
1885         if (cur_disk->label_type == L_TYPE_EFI) {
1886                 if (((cur_disk->disk_parts->etoc->efi_flags &
1887                     EFI_GPT_PRIMARY_CORRUPT) == 0) &&
1888                     check("Disk has a primary label, still continue"))
1889                         return (-1);
1890                 fmt_print("Restoring primary label.\n");
1891                 if (write_label()) {
1892                         err_print("Failed\n");
1893                         return (-1);
1894                 }
1895                 return (0);
1896         } else if (((cur_disk->disk_flags & (DSK_LABEL | DSK_LABEL_DIRTY)) ==
1897             DSK_LABEL) &&
1898             (check("Disk has a primary label, still continue"))) {
1899                 return (-1);
1900         }
1901 
1902         buf = zalloc(cur_blksz);
1903         fmt_print("Searching for backup labels...");
1904         (void) fflush(stdout);
1905 
1906         /*
1907          * Some disks have the backup labels in a strange place.
1908          */
1909         if (cur_ctype->ctype_flags & CF_BLABEL)
1910                 head = 2;
1911         else
1912                 head = nhead - 1;
1913         /*
1914          * Loop through each copy of the backup label.
1915          */
1916         for (sec = 1; ((sec < BAD_LISTCNT * 2 + 1) && (sec < nsect));
1917             sec += 2) {
1918                 bn = chs2bn(ncyl + acyl - 1, head, sec) + solaris_offset;
1919                 /*
1920                  * Attempt to read it.
1921                  */
1922                 if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, bn,
1923                     1, buf, F_NORMAL, NULL)) {
1924                         continue;
1925                 }
1926 
1927                 (void *) memcpy((char *)&label, buf, sizeof (struct dk_label));
1928 
1929                 /*
1930                  * Verify that it is a reasonable label.
1931                  */
1932                 if (!checklabel(&label))
1933                         continue;
1934                 if (trim_id(label.dkl_asciilabel))
1935                         continue;
1936                 /*
1937                  * Lock out interrupts while we manipulate lists.
1938                  */
1939                 enter_critical();
1940                 fmt_print("found.\n");
1941                 /*
1942                  * Find out which disk type the backup label claims.
1943                  */
1944                 for (dtype = cur_ctype->ctype_dlist; dtype != NULL;
1945                     dtype = dtype->dtype_next)
1946                         if (dtype_match(&label, dtype))
1947                                 break;
1948                 /*
1949                  * If it disagrees with our current type, something
1950                  * real bad is happening.
1951                  */
1952                 if (dtype != cur_dtype) {
1953                         if (dtype == NULL) {
1954                                 fmt_print("\
1955 Unknown disk type in backup label\n");
1956                                 exit_critical();
1957                                 free(buf);
1958                                 return (-1);
1959                         }
1960                         fmt_print("Backup label claims different type:\n");
1961                         fmt_print("    <%s cyl %d alt %d hd %d sec %d>\n",
1962                             label.dkl_asciilabel, label.dkl_ncyl,
1963                             label.dkl_acyl, label.dkl_nhead,
1964                             label.dkl_nsect);
1965                         if (check("Continue")) {
1966                                 exit_critical();
1967                                 free(buf);
1968                                 return (-1);
1969                         }
1970                         cur_dtype = dtype;
1971                 }
1972                 /*
1973                  * Try to match the partition map with a known map.
1974                  */
1975                 for (parts = dtype->dtype_plist; parts != NULL;
1976                     parts = parts->pinfo_next)
1977                         if (parts_match(&label, parts))
1978                                 break;
1979                 /*
1980                  * If we couldn't match it, allocate space for a new one,
1981                  * fill in the info, and add it to the list.  The name
1982                  * for the new map is derived from the disk name.
1983                  */
1984                 if (parts == NULL) {
1985                         parts = (struct partition_info *)
1986                             zalloc(sizeof (struct partition_info));
1987                         plist = dtype->dtype_plist;
1988                         if (plist == NULL)
1989                                 dtype->dtype_plist = parts;
1990                         else {
1991                                 while (plist->pinfo_next != NULL)
1992                                         plist = plist->pinfo_next;
1993                                 plist->pinfo_next = parts;
1994                         }
1995                         parts->pinfo_name = alloc_string("original");
1996                         for (i = 0; i < NDKMAP; i++)
1997 
1998 #if defined(_SUNOS_VTOC_8)
1999                                 parts->pinfo_map[i] = label.dkl_map[i];
2000 
2001 #elif defined(_SUNOS_VTOC_16)
2002                                 parts->pinfo_map[i].dkl_cylno  =
2003                                     label.dkl_vtoc.v_part[i].p_start / spc();
2004                                 parts->pinfo_map[i].dkl_nblk =
2005                                     label.dkl_vtoc.v_part[i].p_size;
2006 #else
2007 #error No VTOC layout defined.
2008 #endif /* defined(_SUNOS_VTOC_8) */
2009                         parts->vtoc = label.dkl_vtoc;
2010                 }
2011                 /*
2012                  * We now have a partition map.  Make it the current map.
2013                  */
2014                 cur_disk->disk_parts = cur_parts = parts;
2015                 exit_critical();
2016                 /*
2017                  * Rewrite the labels and defect lists, as appropriate.
2018                  */
2019                 if (EMBEDDED_SCSI) {
2020                         fmt_print("Restoring primary label.\n");
2021                         if (write_label()) {
2022                                 free(buf);
2023                                 return (-1);
2024                         }
2025                 } else {
2026                         fmt_print("Restoring primary label and defect list.\n");
2027                         if (write_label()) {
2028                                 free(buf);
2029                                 return (-1);
2030                         }
2031                         if (cur_list.list != NULL)
2032                                 write_deflist(&cur_list);
2033                 }
2034                 fmt_print("\n");
2035                 free(buf);
2036                 return (0);
2037         }
2038         /*
2039          * If we didn't find any backup labels, say so.
2040          */
2041         fmt_print("not found.\n\n");
2042         free(buf);
2043         return (0);
2044 }
2045 
2046 /*
2047  * This routine is called by c_verify() for an EFI labeled disk
2048  */
2049 static int
2050 c_verify_efi()
2051 {
2052         struct efi_info efi_info;
2053         struct  partition_info  tmp_pinfo;
2054         int status;
2055 
2056         status = read_efi_label(cur_file, &efi_info);
2057         if (status != 0) {
2058                 err_print("Warning: Could not read label.\n");
2059                 return (-1);
2060         }
2061         if (cur_parts->etoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) {
2062                 err_print("Reading the primary EFI GPT label ");
2063                 err_print("failed.  Using backup label.\n");
2064                 err_print("Use the 'backup' command to restore ");
2065                 err_print("the primary label.\n");
2066         }
2067         tmp_pinfo.etoc = efi_info.e_parts;
2068         fmt_print("\n");
2069         if (cur_parts->etoc->efi_parts[8].p_name) {
2070                 fmt_print("Volume name = <%8s>\n",
2071                     cur_parts->etoc->efi_parts[8].p_name);
2072         } else {
2073                 fmt_print("Volume name = <        >\n");
2074         }
2075         fmt_print("ascii name  = ");
2076         print_efi_string(efi_info.vendor, efi_info.product,
2077             efi_info.revision, efi_info.capacity);
2078         fmt_print("\n");
2079 
2080         fmt_print("bytes/sector =  %d\n", cur_blksz);
2081         fmt_print("sectors = %llu\n", cur_parts->etoc->efi_last_lba);
2082         fmt_print("accessible sectors = %llu\n",
2083             cur_parts->etoc->efi_last_u_lba);
2084 
2085         print_map(&tmp_pinfo);
2086         return (0);
2087 }
2088 
2089 /*
2090  * This routine implements the 'verify' command.  It allows the user
2091  * to read the labels on the current disk.
2092  */
2093 int
2094 c_verify()
2095 {
2096         struct  dk_label p_label, b_label, *label;
2097         struct  partition_info tmp_pinfo;
2098         diskaddr_t      bn;
2099         int     sec, head, i, status;
2100         int     p_label_bad = 0;
2101         int     b_label_bad = 0;
2102         int     p_label_found = 0;
2103         int     b_label_found = 0;
2104         char    id_str[128];
2105         char    *buf;
2106 
2107         /*
2108          * There must be a current disk type (and therefore a current disk).
2109          */
2110         if (cur_dtype == NULL) {
2111                 err_print("Current Disk Type is not set.\n");
2112                 return (-1);
2113         }
2114         /*
2115          * The disk must be formatted to read labels.
2116          */
2117         if (!(cur_flags & DISK_FORMATTED)) {
2118                 err_print("Current Disk is unformatted.\n");
2119                 return (-1);
2120         }
2121         /*
2122          * Check for a valid fdisk table entry for Solaris
2123          */
2124         if (!good_fdisk()) {
2125                 return (-1);
2126         }
2127         /*
2128          * Branch off here if the disk is EFI labelled.
2129          */
2130         if (cur_label == L_TYPE_EFI) {
2131                 return (c_verify_efi());
2132         }
2133         /*
2134          * Attempt to read the primary label.
2135          */
2136         status = read_label(cur_file, &p_label);
2137         if (status == -1) {
2138                 err_print("Warning: Could not read primary label.\n");
2139                 p_label_bad = 1;
2140         } else {
2141                 /*
2142                  * Verify that it is a reasonable label.
2143                  */
2144                 /*
2145                  * Save complete ascii string for printing later.
2146                  */
2147                 (void) strncpy(id_str, p_label.dkl_asciilabel, 128);
2148 
2149                 if ((!checklabel((struct dk_label *)&p_label)) ||
2150                     (trim_id(p_label.dkl_asciilabel))) {
2151                         err_print("\
2152 Warning: Primary label appears to be corrupt.\n");
2153                         p_label_bad = 1;
2154                 } else {
2155                         p_label_found = 1;
2156                         /*
2157                          * Make sure it matches current label
2158                          */
2159                         if ((!dtype_match(&p_label, cur_dtype)) ||
2160                             (!parts_match(&p_label, cur_parts))) {
2161                                 err_print("\
2162 Warning: Primary label on disk appears to be different from\ncurrent label.\n");
2163                                 p_label_bad = 1;
2164                         }
2165                 }
2166         }
2167 
2168         /*
2169          * Read backup labels.
2170          * Some disks have the backup labels in a strange place.
2171          */
2172         if (cur_ctype->ctype_flags & CF_BLABEL)
2173                 head = 2;
2174         else
2175                 head = nhead - 1;
2176 
2177         buf = zalloc(cur_blksz);
2178         /*
2179          * Loop through each copy of the backup label.
2180          */
2181         for (sec = 1; ((sec < BAD_LISTCNT * 2 + 1) && (sec < nsect));
2182             sec += 2) {
2183                 bn = chs2bn(ncyl + acyl - 1, head, sec) + solaris_offset;
2184                 /*
2185                  * Attempt to read it.
2186                  */
2187                 if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, bn,
2188                     1, buf, F_NORMAL, NULL))
2189                         continue;
2190 
2191                 (void *) memcpy((char *)&b_label, buf,
2192                     sizeof (struct dk_label));
2193 
2194                 /*
2195                  * Verify that it is a reasonable label.
2196                  */
2197                 if (!checklabel(&b_label))
2198                         continue;
2199 
2200                 /*
2201                  * Save complete label only if no primary label exists
2202                  */
2203                 if (!p_label_found)
2204                         (void) strncpy(id_str, b_label.dkl_asciilabel, 128);
2205 
2206                 if (trim_id(b_label.dkl_asciilabel))
2207                         continue;
2208                 b_label_found = 1;
2209                 /*
2210                  * Compare against primary label
2211                  */
2212                 if (p_label_found) {
2213                         if ((strcmp(b_label.dkl_asciilabel,
2214                             p_label.dkl_asciilabel) != 0) ||
2215                             (b_label.dkl_ncyl != p_label.dkl_ncyl) ||
2216                             (b_label.dkl_acyl != p_label.dkl_acyl) ||
2217                             (b_label.dkl_nhead != p_label.dkl_nhead) ||
2218                             (b_label.dkl_nsect != p_label.dkl_nsect)) {
2219                                 b_label_bad = 1;
2220                         } else {
2221                                 for (i = 0; i < NDKMAP; i++) {
2222 #if defined(_SUNOS_VTOC_8)
2223                                         if ((b_label.dkl_map[i].dkl_cylno !=
2224                                             p_label.dkl_map[i].dkl_cylno) ||
2225                                             (b_label.dkl_map[i].dkl_nblk !=
2226                                             p_label.dkl_map[i].dkl_nblk)) {
2227                                                 b_label_bad = 1;
2228                                                 break;
2229                                         }
2230 
2231 #elif defined(_SUNOS_VTOC_16)
2232                                         if ((b_label.dkl_vtoc.v_part[i].p_tag !=
2233                                             p_label.dkl_vtoc.v_part[i].p_tag) ||
2234                                             (b_label.dkl_vtoc.v_part[i].p_flag
2235                                             != p_label.dkl_vtoc.v_part[i].
2236                                             p_flag) ||
2237                                             (b_label.dkl_vtoc.v_part[i].p_start
2238                                             != p_label.dkl_vtoc.v_part[i].
2239                                             p_start) ||
2240                                             (b_label.dkl_vtoc.v_part[i].p_size
2241                                             != p_label.dkl_vtoc.v_part[i].
2242                                             p_size)) {
2243                                                 b_label_bad = 1;
2244                                                 break;
2245                                         }
2246 #else
2247 #error No VTOC layout defined.
2248 #endif /* defined(_SUNOS_VTOC_8) */
2249                                 }
2250                         }
2251                 }
2252                 if (b_label_bad)
2253                         err_print(
2254 "Warning: Primary and backup labels do not match.\n");
2255                 break;
2256         }
2257         /*
2258          * If we didn't find any backup labels, say so.
2259          */
2260         if (!b_label_found)
2261                 err_print("Warning: Could not read backup labels.\n");
2262 
2263         if ((!b_label_found) || (p_label_bad) || (b_label_bad))
2264                 err_print("\n\
2265 Warning: Check the current partitioning and 'label' the disk or use the\n\
2266 \t 'backup' command.\n");
2267 
2268         /*
2269          * Print label information.
2270          */
2271         if (p_label_found) {
2272                 fmt_print("\nPrimary label contents:\n");
2273                 label = &p_label;
2274         } else if (b_label_found) {
2275                 fmt_print("\nBackup label contents:\n");
2276                 label = &b_label;
2277         } else {
2278                 free(buf);
2279                 return (0);
2280         }
2281 
2282         /*
2283          * Must put info into partition_info struct for
2284          * for print routine.
2285          */
2286         bzero(&tmp_pinfo, sizeof (struct partition_info));
2287         for (i = 0; i < NDKMAP; i++) {
2288 
2289 #if defined(_SUNOS_VTOC_8)
2290                 tmp_pinfo.pinfo_map[i] = label->dkl_map[i];
2291 
2292 #elif defined(_SUNOS_VTOC_16)
2293                 tmp_pinfo.pinfo_map[i].dkl_cylno =
2294                     label->dkl_vtoc.v_part[i].p_start / spc();
2295                 tmp_pinfo.pinfo_map[i].dkl_nblk =
2296                     label->dkl_vtoc.v_part[i].p_size;
2297 #else
2298 #error No VTOC layout defined.
2299 #endif /* defined(_SUNOS_VTOC_8) */
2300         }
2301         tmp_pinfo.vtoc = label->dkl_vtoc;
2302 
2303         fmt_print("\n");
2304         fmt_print("Volume name = <%8s>\n", label->dkl_vtoc.v_volume);
2305         fmt_print("ascii name  = <%s>\n", id_str);
2306         fmt_print("pcyl        = %4d\n", label->dkl_pcyl);
2307         fmt_print("ncyl        = %4d\n", label->dkl_ncyl);
2308         fmt_print("acyl        = %4d\n", label->dkl_acyl);
2309 
2310 #if defined(_SUNOS_VTOC_16)
2311         fmt_print("bcyl        = %4d\n", label->dkl_bcyl);
2312 #endif /* defined(_SUNOS_VTOC_16) */
2313 
2314         fmt_print("nhead       = %4d\n", label->dkl_nhead);
2315         fmt_print("nsect       = %4d\n", label->dkl_nsect);
2316 
2317         print_map(&tmp_pinfo);
2318         free(buf);
2319         return (0);
2320 }
2321 
2322 
2323 /*
2324  * This command implements the inquiry command, for embedded SCSI
2325  * disks only, which issues a SCSI inquiry command, and
2326  * displays the resulting vendor, product id and revision level.
2327  */
2328 int
2329 c_inquiry()
2330 {
2331         char                    inqbuf[255];
2332         struct scsi_inquiry     *inq;
2333 
2334         assert(SCSI);
2335 
2336         inq = (struct scsi_inquiry *)inqbuf;
2337 
2338         if (uscsi_inquiry(cur_file, inqbuf, sizeof (inqbuf))) {
2339                 err_print("Failed\n");
2340                 return (-1);
2341         } else {
2342                 fmt_print("Vendor:   ");
2343                 print_buf(inq->inq_vid, sizeof (inq->inq_vid));
2344                 fmt_print("\nProduct:  ");
2345                 print_buf(inq->inq_pid, sizeof (inq->inq_pid));
2346                 fmt_print("\nRevision: ");
2347                 print_buf(inq->inq_revision, sizeof (inq->inq_revision));
2348                 fmt_print("\n");
2349         }
2350 
2351         return (0);
2352 }
2353 
2354 
2355 /*
2356  * This routine allows the user to set the 8-character
2357  * volume name in the vtoc.  It then writes both the
2358  * primary and backup labels onto the current disk.
2359  */
2360 int
2361 c_volname()
2362 {
2363         int      status;
2364         char    *prompt;
2365         union {
2366                 int     xfoo;
2367                 char    defvolname[LEN_DKL_VVOL+1];
2368         } x;
2369         char    s1[MAXPATHLEN], nclean[MAXPATHLEN];
2370         char    *volname;
2371 
2372 
2373         /*
2374          * There must be a current disk type (and therefore a current disk).
2375          */
2376         if (cur_dtype == NULL) {
2377                 err_print("Current Disk Type is not set.\n");
2378                 return (-1);
2379         }
2380         /*
2381          * The current disk must be formatted to label it.
2382          */
2383         if (!(cur_flags & DISK_FORMATTED)) {
2384                 err_print("Current Disk is unformatted.\n");
2385                 return (-1);
2386         }
2387         /*
2388          * Check for a valid fdisk table entry for Solaris
2389          */
2390         if (!good_fdisk()) {
2391                 return (-1);
2392         }
2393         /*
2394          * The current disk must be formatted to label it.
2395          */
2396         if (cur_parts == NULL) {
2397         err_print(
2398 "Please select a partition map for the disk first.\n");
2399         return (-1);
2400         }
2401 
2402         /*
2403          * Check to see if there are any mounted file systems anywhere
2404          * on the current disk.  If so, refuse to label the disk, but
2405          * only if the partitions would change for the mounted partitions.
2406          *
2407          */
2408         if (checkmount((diskaddr_t)-1, (diskaddr_t)-1)) {
2409                 /* Bleagh, too descriptive */
2410                 if (check_label_with_mount()) {
2411                         err_print(
2412 "Cannot label disk while it has mounted partitions.\n\n");
2413                         return (-1);
2414                 }
2415         }
2416 
2417         /*
2418          * Check to see if there are partitions being used for swapping
2419          * on the current disk.  If so, refuse to label the disk, but
2420          * only if the partitions would change for the swap partitions.
2421          *
2422          */
2423         if (checkswap((diskaddr_t)-1, (diskaddr_t)-1)) {
2424                 /* Bleagh, too descriptive */
2425                 if (check_label_with_swap()) {
2426                         err_print(
2427 "Cannot label disk while its partitions are currently \
2428 being used for swapping.\n\n");
2429                         return (-1);
2430                 }
2431         }
2432 
2433         /*
2434          * Check to see if any partitions used for svm, vxvm, ZFS zpool
2435          * or live upgrade are on the disk. If so, refuse to label the
2436          * disk, but only if we are trying to shrink a partition in
2437          * use.
2438          */
2439         if (checkdevinuse(cur_disk->disk_name, (diskaddr_t)-1,
2440             (diskaddr_t)-1, 0, 1)) {
2441                 err_print("Cannot label disk while its partitions "
2442                     "are in use as described.\n");
2443                 return (-1);
2444         }
2445 
2446         /*
2447          * Prompt for the disk volume name.
2448          */
2449         prompt = "Enter 8-character volume name (remember quotes)";
2450         bzero(x.defvolname, LEN_DKL_VVOL+1);
2451         bcopy(cur_disk->v_volume, x.defvolname, LEN_DKL_VVOL);
2452         /*
2453          *  Get the input using "get_inputline" since
2454          *  input would never return null string.
2455          */
2456         fmt_print("%s[\"%s\"]:", prompt, x.defvolname);
2457 
2458         /*
2459          * Get input from the user.
2460          */
2461         get_inputline(nclean, MAXPATHLEN);
2462         clean_token(s1, nclean);
2463         /*
2464          * check for return.
2465          */
2466         if (s1[0] == 0) {
2467                 volname = x.defvolname;
2468         } else {
2469                 /*
2470                  * remove the " mark from volname.
2471                  */
2472                 if (s1[0] == '"') {
2473                         int i = 1;
2474                         volname = &s1[1];
2475                         while (s1[i] != '"' && s1[i] != '\0')
2476                                 i++;
2477                         s1[i] = '\0';
2478                         clean_token(nclean, volname);
2479                         volname = nclean;
2480                 } else {
2481                         (void) sscanf(&s1[0], "%1024s", nclean);
2482                         volname = nclean;
2483                 };
2484         }
2485         /*
2486          * Make sure the user is serious.
2487          */
2488         if (check("Ready to label disk, continue")) {
2489                 fmt_print("\n");
2490                 return (-1);
2491         }
2492         /*
2493          * Use the volume name chosen above
2494          */
2495         bzero(cur_disk->v_volume, LEN_DKL_VVOL);
2496         bcopy(volname, cur_disk->v_volume, min((int)strlen(volname),
2497             LEN_DKL_VVOL));
2498         if (cur_label == L_TYPE_EFI) {
2499                 bzero(cur_parts->etoc->efi_parts[8].p_name, LEN_DKL_VVOL);
2500                 bcopy(volname, cur_parts->etoc->efi_parts[8].p_name,
2501                     LEN_DKL_VVOL);
2502         }
2503         /*
2504          * Write the labels out (this will also notify unix) and
2505          * return status.
2506          */
2507         fmt_print("\n");
2508         if (status = write_label())
2509                 err_print("Label failed.\n");
2510         return (status);
2511 }