10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51524Slh195018 * Common Development and Distribution License (the "License"). 61524Slh195018 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 227491SLi.He@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* 270Sstevel@tonic-gate * This file contains functions that implement the command menu commands. 280Sstevel@tonic-gate */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include "global.h" 310Sstevel@tonic-gate #include <time.h> 320Sstevel@tonic-gate #include <sys/time.h> 330Sstevel@tonic-gate #include <sys/resource.h> 340Sstevel@tonic-gate #include <sys/wait.h> 350Sstevel@tonic-gate #include <strings.h> 360Sstevel@tonic-gate #include <signal.h> 370Sstevel@tonic-gate #include <stdlib.h> 380Sstevel@tonic-gate #include <string.h> 390Sstevel@tonic-gate 400Sstevel@tonic-gate #if defined(sparc) 410Sstevel@tonic-gate #include <sys/hdio.h> 420Sstevel@tonic-gate #endif /* defined(sparc) */ 430Sstevel@tonic-gate 440Sstevel@tonic-gate #include "main.h" 450Sstevel@tonic-gate #include "analyze.h" 460Sstevel@tonic-gate #include "menu.h" 470Sstevel@tonic-gate #include "menu_command.h" 480Sstevel@tonic-gate #include "menu_defect.h" 490Sstevel@tonic-gate #include "menu_partition.h" 500Sstevel@tonic-gate #include "param.h" 510Sstevel@tonic-gate #include "misc.h" 520Sstevel@tonic-gate #include "label.h" 530Sstevel@tonic-gate #include "startup.h" 540Sstevel@tonic-gate #include "partition.h" 550Sstevel@tonic-gate #include "prompts.h" 56767Ssjelinek #include "checkdev.h" 570Sstevel@tonic-gate #include "io.h" 580Sstevel@tonic-gate #include "ctlr_scsi.h" 590Sstevel@tonic-gate #include "auto_sense.h" 600Sstevel@tonic-gate #include "modify_partition.h" 610Sstevel@tonic-gate 620Sstevel@tonic-gate 630Sstevel@tonic-gate extern struct menu_item menu_partition[]; 640Sstevel@tonic-gate extern struct menu_item menu_analyze[]; 650Sstevel@tonic-gate extern struct menu_item menu_defect[]; 660Sstevel@tonic-gate 670Sstevel@tonic-gate /* 680Sstevel@tonic-gate * Choices for the p_tag vtoc field 690Sstevel@tonic-gate */ 700Sstevel@tonic-gate slist_t ptag_choices[] = { 710Sstevel@tonic-gate { "unassigned", "", V_UNASSIGNED }, 720Sstevel@tonic-gate { "boot", "", V_BOOT }, 730Sstevel@tonic-gate { "root", "", V_ROOT }, 740Sstevel@tonic-gate { "swap", "", V_SWAP }, 750Sstevel@tonic-gate { "usr", "", V_USR }, 760Sstevel@tonic-gate { "backup", "", V_BACKUP }, 770Sstevel@tonic-gate { "stand", "", V_STAND }, 780Sstevel@tonic-gate { "var", "", V_VAR }, 790Sstevel@tonic-gate { "home", "", V_HOME }, 800Sstevel@tonic-gate { "alternates", "", V_ALTSCTR }, 810Sstevel@tonic-gate { "reserved", "", V_RESERVED }, 820Sstevel@tonic-gate { NULL } 830Sstevel@tonic-gate }; 840Sstevel@tonic-gate 850Sstevel@tonic-gate 860Sstevel@tonic-gate /* 870Sstevel@tonic-gate * Choices for the p_flag vtoc field 880Sstevel@tonic-gate */ 890Sstevel@tonic-gate slist_t pflag_choices[] = { 900Sstevel@tonic-gate { "wm", "read-write, mountable", 0 }, 910Sstevel@tonic-gate { "wu", "read-write, unmountable", V_UNMNT }, 920Sstevel@tonic-gate { "rm", "read-only, mountable", V_RONLY }, 930Sstevel@tonic-gate { "ru", "read-only, unmountable", V_RONLY|V_UNMNT }, 940Sstevel@tonic-gate { NULL } 950Sstevel@tonic-gate }; 960Sstevel@tonic-gate 970Sstevel@tonic-gate 980Sstevel@tonic-gate /* 990Sstevel@tonic-gate * This routine implements the 'disk' command. It allows the user to 1000Sstevel@tonic-gate * select a disk to be current. The list of choices is the list of 1010Sstevel@tonic-gate * disks that were found at startup time. 1020Sstevel@tonic-gate */ 1030Sstevel@tonic-gate int 1040Sstevel@tonic-gate c_disk() 1050Sstevel@tonic-gate { 1060Sstevel@tonic-gate struct disk_info *disk; 1070Sstevel@tonic-gate u_ioparam_t ioparam; 1080Sstevel@tonic-gate int i; 1090Sstevel@tonic-gate int ndisks = 0; 1100Sstevel@tonic-gate int blind_select = 0; 1110Sstevel@tonic-gate int deflt; 1120Sstevel@tonic-gate int index; 1130Sstevel@tonic-gate int *defltptr = NULL; 1140Sstevel@tonic-gate int more = 0; 1150Sstevel@tonic-gate int more_quit = 0; 1160Sstevel@tonic-gate int one_line = 0; 1170Sstevel@tonic-gate int tty_lines; 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate /* 1200Sstevel@tonic-gate * This buffer holds the check() prompt that verifies we've got the right 1210Sstevel@tonic-gate * disk when performing a blind selection. The size should be sufficient 1220Sstevel@tonic-gate * to hold the prompt string, plus 256 characters for the disk name - 1230Sstevel@tonic-gate * way more than should ever be necessary. See the #define in misc.h. 1240Sstevel@tonic-gate */ 1250Sstevel@tonic-gate char chk_buf[BLIND_SELECT_VER_PROMPT]; 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate if (istokenpresent()) { 1280Sstevel@tonic-gate /* 1290Sstevel@tonic-gate * disk number to be selected is already in the 1300Sstevel@tonic-gate * input stream . 1310Sstevel@tonic-gate */ 1320Sstevel@tonic-gate TOKEN token, cleantoken; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate /* 1350Sstevel@tonic-gate * Get the disk number the user has given. 1360Sstevel@tonic-gate */ 1370Sstevel@tonic-gate i = 0; 1380Sstevel@tonic-gate for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 1390Sstevel@tonic-gate i++; 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate ioparam.io_bounds.lower = 0; 1430Sstevel@tonic-gate ioparam.io_bounds.upper = i - 1; 1440Sstevel@tonic-gate (void) gettoken(token); 1450Sstevel@tonic-gate clean_token(cleantoken, token); 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate /* 1480Sstevel@tonic-gate * Convert the token into an integer. 1490Sstevel@tonic-gate */ 1507563SPrasad.Singamsetty@Sun.COM if (geti(cleantoken, &index, (int *)NULL)) 1510Sstevel@tonic-gate return (0); 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate /* 1540Sstevel@tonic-gate * Check to be sure it is within the legal bounds. 1550Sstevel@tonic-gate */ 1560Sstevel@tonic-gate if ((index < 0) || (index >= i)) { 1570Sstevel@tonic-gate err_print("`%d' is out of range.\n", index); 1580Sstevel@tonic-gate return (0); 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate goto checkdisk; 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate fmt_print("\n\nAVAILABLE DISK SELECTIONS:\n"); 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate i = 0; 1660Sstevel@tonic-gate if ((option_f == (char *)NULL) && isatty(0) == 1 && isatty(1) == 1) { 1670Sstevel@tonic-gate /* 1680Sstevel@tonic-gate * We have a real terminal for std input and output, enable 1690Sstevel@tonic-gate * more style of output for disk selection list. 1700Sstevel@tonic-gate */ 1710Sstevel@tonic-gate more = 1; 1720Sstevel@tonic-gate tty_lines = get_tty_lines(); 1730Sstevel@tonic-gate enter_critical(); 1740Sstevel@tonic-gate echo_off(); 1750Sstevel@tonic-gate charmode_on(); 1760Sstevel@tonic-gate exit_critical(); 1770Sstevel@tonic-gate } 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate /* 1800Sstevel@tonic-gate * Loop through the list of found disks. 1810Sstevel@tonic-gate */ 1820Sstevel@tonic-gate for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 1830Sstevel@tonic-gate /* 1840Sstevel@tonic-gate * If using more output, account 2 lines for each disk. 1850Sstevel@tonic-gate */ 1860Sstevel@tonic-gate if (more && !more_quit && i && (one_line || 1870Sstevel@tonic-gate ((2 * i + 1) % (tty_lines - 2) <= 1))) { 1880Sstevel@tonic-gate int c; 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate /* 1910Sstevel@tonic-gate * Get the next character. 1920Sstevel@tonic-gate */ 1930Sstevel@tonic-gate fmt_print("- hit space for more or s to select - "); 1940Sstevel@tonic-gate c = getchar(); 1950Sstevel@tonic-gate fmt_print("\015"); 1960Sstevel@tonic-gate one_line = 0; 1970Sstevel@tonic-gate /* 1980Sstevel@tonic-gate * Handle display one line command 1990Sstevel@tonic-gate * (return key) 2000Sstevel@tonic-gate */ 2010Sstevel@tonic-gate if (c == '\012') { 2020Sstevel@tonic-gate one_line++; 2030Sstevel@tonic-gate } 2040Sstevel@tonic-gate /* Handle Quit command */ 2050Sstevel@tonic-gate if (c == 'q') { 2060Sstevel@tonic-gate fmt_print( 2070Sstevel@tonic-gate " \015"); 2080Sstevel@tonic-gate more_quit++; 2090Sstevel@tonic-gate } 2100Sstevel@tonic-gate /* Handle ^D command */ 2110Sstevel@tonic-gate if (c == '\004') 2120Sstevel@tonic-gate fullabort(); 2130Sstevel@tonic-gate /* or get on with the show */ 2140Sstevel@tonic-gate if (c == 's' || c == 'S') { 2150Sstevel@tonic-gate fmt_print("%80s\n", " "); 2160Sstevel@tonic-gate break; 2170Sstevel@tonic-gate } 2180Sstevel@tonic-gate } 2190Sstevel@tonic-gate /* 2200Sstevel@tonic-gate * If this is the current disk, mark it as 2210Sstevel@tonic-gate * the default. 2220Sstevel@tonic-gate */ 2230Sstevel@tonic-gate if (cur_disk == disk) { 2240Sstevel@tonic-gate deflt = i; 2250Sstevel@tonic-gate defltptr = &deflt; 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate if (!more || !more_quit) 2280Sstevel@tonic-gate pr_diskline(disk, i); 2290Sstevel@tonic-gate i++; 2300Sstevel@tonic-gate } 2310Sstevel@tonic-gate if (more) { 2320Sstevel@tonic-gate enter_critical(); 2330Sstevel@tonic-gate charmode_off(); 2340Sstevel@tonic-gate echo_on(); 2350Sstevel@tonic-gate exit_critical(); 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate /* 2390Sstevel@tonic-gate * Determine total number of disks, and ask the user which disk he 2400Sstevel@tonic-gate * would like to make current. 2410Sstevel@tonic-gate */ 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 2440Sstevel@tonic-gate ndisks++; 2450Sstevel@tonic-gate } 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate ioparam.io_bounds.lower = 0; 2480Sstevel@tonic-gate ioparam.io_bounds.upper = ndisks - 1; 2490Sstevel@tonic-gate index = input(FIO_INT, "Specify disk (enter its number)", ':', 2500Sstevel@tonic-gate &ioparam, defltptr, DATA_INPUT); 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate if (index >= i) { 2530Sstevel@tonic-gate blind_select = 1; 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate /* 2570Sstevel@tonic-gate * Find the disk chosen. Search through controllers/disks 2580Sstevel@tonic-gate * in the same original order, so we match what the user 2590Sstevel@tonic-gate * chose. 2600Sstevel@tonic-gate */ 2610Sstevel@tonic-gate checkdisk: 2620Sstevel@tonic-gate i = 0; 2630Sstevel@tonic-gate for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 2640Sstevel@tonic-gate if (i == index) 2650Sstevel@tonic-gate goto found; 2660Sstevel@tonic-gate i++; 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate /* 2690Sstevel@tonic-gate * Should never happen. 2700Sstevel@tonic-gate */ 2710Sstevel@tonic-gate impossible("no disk found"); 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate found: 2740Sstevel@tonic-gate if (blind_select) { 2750Sstevel@tonic-gate (void) snprintf(chk_buf, sizeof (chk_buf), 2760Sstevel@tonic-gate "Disk %s selected - is this the desired disk? ", disk->disk_name); 2770Sstevel@tonic-gate if (check(chk_buf)) { 2780Sstevel@tonic-gate return (-1); 2790Sstevel@tonic-gate } 2800Sstevel@tonic-gate } 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate /* 2830Sstevel@tonic-gate * Update the state. We lock out interrupts so the state can't 2840Sstevel@tonic-gate * get half-updated. 2850Sstevel@tonic-gate */ 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate enter_critical(); 2880Sstevel@tonic-gate init_globals(disk); 2890Sstevel@tonic-gate exit_critical(); 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate /* 2920Sstevel@tonic-gate * If type unknown and interactive, ask user to specify type. 2930Sstevel@tonic-gate * Also, set partition table (best guess) too. 2940Sstevel@tonic-gate */ 2950Sstevel@tonic-gate if (!option_f && ncyl == 0 && nhead == 0 && nsect == 0 && 2960Sstevel@tonic-gate (disk->label_type != L_TYPE_EFI)) { 2970Sstevel@tonic-gate (void) c_type(); 2980Sstevel@tonic-gate } 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate /* 3010Sstevel@tonic-gate * Get the Solaris Fdisk Partition information 3020Sstevel@tonic-gate */ 3030Sstevel@tonic-gate if (nhead != 0 && nsect != 0) 3040Sstevel@tonic-gate (void) copy_solaris_part(&cur_disk->fdisk_part); 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate if ((cur_disk->label_type == L_TYPE_EFI) && 3070Sstevel@tonic-gate (cur_disk->disk_parts->etoc->efi_flags & 3080Sstevel@tonic-gate EFI_GPT_PRIMARY_CORRUPT)) { 3090Sstevel@tonic-gate err_print("Reading the primary EFI GPT label "); 3100Sstevel@tonic-gate err_print("failed. Using backup label.\n"); 3110Sstevel@tonic-gate err_print("Use the 'backup' command to restore "); 3120Sstevel@tonic-gate err_print("the primary label.\n"); 3130Sstevel@tonic-gate } 314*7910SBo.Zhou@Sun.COM 315*7910SBo.Zhou@Sun.COM #if defined(_SUNOS_VTOC_16) 316*7910SBo.Zhou@Sun.COM /* 317*7910SBo.Zhou@Sun.COM * If there is no fdisk solaris partition. 318*7910SBo.Zhou@Sun.COM */ 319*7910SBo.Zhou@Sun.COM if (cur_disk->fdisk_part.numsect == 0) { 320*7910SBo.Zhou@Sun.COM err_print("No Solaris fdisk partition found.\n"); 321*7910SBo.Zhou@Sun.COM goto exit; 322*7910SBo.Zhou@Sun.COM } 323*7910SBo.Zhou@Sun.COM #endif /* defined(_SUNOS_VTOC_16) */ 324*7910SBo.Zhou@Sun.COM 3250Sstevel@tonic-gate /* 3260Sstevel@tonic-gate * If the label of the disk is marked dirty, 3270Sstevel@tonic-gate * see if they'd like to label the disk now. 3280Sstevel@tonic-gate */ 3290Sstevel@tonic-gate if (cur_disk->disk_flags & DSK_LABEL_DIRTY) { 3300Sstevel@tonic-gate if (check("Disk not labeled. Label it now") == 0) { 3310Sstevel@tonic-gate if (write_label()) { 3320Sstevel@tonic-gate err_print("Write label failed\n"); 3330Sstevel@tonic-gate } else { 3340Sstevel@tonic-gate cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 3350Sstevel@tonic-gate } 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate } 3387611SBo.Zhou@Sun.COM exit: 3390Sstevel@tonic-gate return (0); 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate /* 3430Sstevel@tonic-gate * This routine implements the 'type' command. It allows the user to 3440Sstevel@tonic-gate * specify the type of the current disk. It should be necessary only 3450Sstevel@tonic-gate * if the disk was not labelled or was somehow labelled incorrectly. 3460Sstevel@tonic-gate * The list of legal types for the disk comes from information that was 3470Sstevel@tonic-gate * in the data file. 3480Sstevel@tonic-gate */ 3490Sstevel@tonic-gate int 3500Sstevel@tonic-gate c_type() 3510Sstevel@tonic-gate { 3520Sstevel@tonic-gate struct disk_type *type, *tptr, *oldtype; 3530Sstevel@tonic-gate u_ioparam_t ioparam; 3540Sstevel@tonic-gate int i, index, deflt, *defltptr = NULL; 3550Sstevel@tonic-gate struct disk_type disk_type; 3560Sstevel@tonic-gate struct disk_type *d = &disk_type; 3570Sstevel@tonic-gate int first_disk; 3580Sstevel@tonic-gate int auto_conf_choice; 3590Sstevel@tonic-gate int other_choice; 3600Sstevel@tonic-gate struct dk_label label; 3610Sstevel@tonic-gate struct efi_info efi_info; 3620Sstevel@tonic-gate uint64_t maxLBA; 3630Sstevel@tonic-gate char volname[LEN_DKL_VVOL]; 3640Sstevel@tonic-gate int volinit = 0; 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate /* 3670Sstevel@tonic-gate * There must be a current disk. 3680Sstevel@tonic-gate */ 3690Sstevel@tonic-gate if (cur_disk == NULL) { 3700Sstevel@tonic-gate err_print("Current Disk is not set.\n"); 3710Sstevel@tonic-gate return (-1); 3720Sstevel@tonic-gate } 3730Sstevel@tonic-gate oldtype = cur_disk->disk_type; 3740Sstevel@tonic-gate type = cur_ctype->ctype_dlist; 3750Sstevel@tonic-gate /* 3760Sstevel@tonic-gate * Print out the list of choices. 3770Sstevel@tonic-gate */ 3780Sstevel@tonic-gate fmt_print("\n\nAVAILABLE DRIVE TYPES:\n"); 3790Sstevel@tonic-gate first_disk = 0; 3800Sstevel@tonic-gate if (cur_ctype->ctype_ctype == DKC_SCSI_CCS) { 3810Sstevel@tonic-gate auto_conf_choice = 0; 3820Sstevel@tonic-gate fmt_print(" %d. Auto configure\n", first_disk++); 3830Sstevel@tonic-gate } else { 3840Sstevel@tonic-gate auto_conf_choice = -1; 3850Sstevel@tonic-gate } 3860Sstevel@tonic-gate i = first_disk; 3870Sstevel@tonic-gate for (tptr = type; tptr != NULL; tptr = tptr->dtype_next) { 3880Sstevel@tonic-gate /* 3890Sstevel@tonic-gate * If we pass the current type, mark it to be the default. 3900Sstevel@tonic-gate */ 3910Sstevel@tonic-gate if (cur_dtype == tptr) { 3920Sstevel@tonic-gate deflt = i; 3930Sstevel@tonic-gate defltptr = &deflt; 3940Sstevel@tonic-gate } 3950Sstevel@tonic-gate if (cur_disk->label_type == L_TYPE_EFI) { 3960Sstevel@tonic-gate continue; 3970Sstevel@tonic-gate } 3980Sstevel@tonic-gate if (tptr->dtype_asciilabel) 3990Sstevel@tonic-gate fmt_print(" %d. %s\n", i++, tptr->dtype_asciilabel); 4000Sstevel@tonic-gate } 4010Sstevel@tonic-gate other_choice = i; 4020Sstevel@tonic-gate fmt_print(" %d. other\n", i); 4030Sstevel@tonic-gate ioparam.io_bounds.lower = 0; 4040Sstevel@tonic-gate ioparam.io_bounds.upper = i; 4050Sstevel@tonic-gate /* 4060Sstevel@tonic-gate * Ask the user which type the disk is. 4070Sstevel@tonic-gate */ 4080Sstevel@tonic-gate index = input(FIO_INT, "Specify disk type (enter its number)", ':', 4090Sstevel@tonic-gate &ioparam, defltptr, DATA_INPUT); 4100Sstevel@tonic-gate /* 4110Sstevel@tonic-gate * Find the type s/he chose. 4120Sstevel@tonic-gate */ 4130Sstevel@tonic-gate if (index == auto_conf_choice) { 4140Sstevel@tonic-gate float scaled; 4157563SPrasad.Singamsetty@Sun.COM diskaddr_t nblks; 4160Sstevel@tonic-gate int nparts; 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate /* 4190Sstevel@tonic-gate * User chose "auto configure". 4200Sstevel@tonic-gate */ 4210Sstevel@tonic-gate (void) strcpy(x86_devname, cur_disk->disk_name); 4220Sstevel@tonic-gate switch (cur_disk->label_type) { 4230Sstevel@tonic-gate case L_TYPE_SOLARIS: 4240Sstevel@tonic-gate if ((tptr = auto_sense(cur_file, 1, &label)) == NULL) { 4250Sstevel@tonic-gate err_print("Auto configure failed\n"); 4260Sstevel@tonic-gate return (-1); 4270Sstevel@tonic-gate } 4280Sstevel@tonic-gate fmt_print("%s: configured with capacity of ", 4290Sstevel@tonic-gate cur_disk->disk_name); 4307563SPrasad.Singamsetty@Sun.COM nblks = (diskaddr_t)tptr->dtype_ncyl * tptr->dtype_nhead * 4310Sstevel@tonic-gate tptr->dtype_nsect; 4320Sstevel@tonic-gate scaled = bn2mb(nblks); 4330Sstevel@tonic-gate if (scaled > 1024.0) { 4340Sstevel@tonic-gate fmt_print("%1.2fGB\n", scaled/1024.0); 4350Sstevel@tonic-gate } else { 4360Sstevel@tonic-gate fmt_print("%1.2fMB\n", scaled); 4370Sstevel@tonic-gate } 4380Sstevel@tonic-gate fmt_print("<%s cyl %d alt %d hd %d sec %d>\n", 4390Sstevel@tonic-gate tptr->dtype_asciilabel, tptr->dtype_ncyl, 4400Sstevel@tonic-gate tptr->dtype_acyl, tptr->dtype_nhead, 4410Sstevel@tonic-gate tptr->dtype_nsect); 4420Sstevel@tonic-gate break; 4430Sstevel@tonic-gate case L_TYPE_EFI: 4440Sstevel@tonic-gate if ((tptr = auto_efi_sense(cur_file, &efi_info)) == NULL) { 4450Sstevel@tonic-gate err_print("Auto configure failed\n"); 4460Sstevel@tonic-gate return (-1); 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate fmt_print("%s: configured with capacity of ", 4490Sstevel@tonic-gate cur_disk->disk_name); 4500Sstevel@tonic-gate scaled = bn2mb(efi_info.capacity); 4510Sstevel@tonic-gate if (scaled > 1024.0) { 4520Sstevel@tonic-gate fmt_print("%1.2fGB\n", scaled/1024.0); 4530Sstevel@tonic-gate } else { 4540Sstevel@tonic-gate fmt_print("%1.2fMB\n", scaled); 4550Sstevel@tonic-gate } 4560Sstevel@tonic-gate print_efi_string(efi_info.vendor, efi_info.product, 4570Sstevel@tonic-gate efi_info.revision, efi_info.capacity); 4580Sstevel@tonic-gate fmt_print("\n"); 4590Sstevel@tonic-gate for (nparts = 0; nparts < cur_parts->etoc->efi_nparts; 4600Sstevel@tonic-gate nparts++) { 4610Sstevel@tonic-gate if (cur_parts->etoc->efi_parts[nparts].p_tag == 4620Sstevel@tonic-gate V_RESERVED) { 4630Sstevel@tonic-gate if (cur_parts->etoc->efi_parts[nparts].p_name) { 4640Sstevel@tonic-gate (void) strcpy(volname, 4650Sstevel@tonic-gate cur_parts->etoc->efi_parts[nparts].p_name); 4660Sstevel@tonic-gate volinit = 1; 4670Sstevel@tonic-gate } 4680Sstevel@tonic-gate break; 4690Sstevel@tonic-gate } 4700Sstevel@tonic-gate } 4710Sstevel@tonic-gate enter_critical(); 4727491SLi.He@Sun.COM if (delete_disk_type(cur_disk->disk_type) != 0) { 4737491SLi.He@Sun.COM fmt_print("Autoconfiguration failed.\n"); 4747491SLi.He@Sun.COM return (-1); 4757491SLi.He@Sun.COM } 4760Sstevel@tonic-gate cur_disk->disk_type = tptr; 4770Sstevel@tonic-gate cur_disk->disk_parts = tptr->dtype_plist; 4780Sstevel@tonic-gate init_globals(cur_disk); 4790Sstevel@tonic-gate exit_critical(); 4800Sstevel@tonic-gate if (volinit) { 4810Sstevel@tonic-gate for (nparts = 0; nparts < cur_parts->etoc->efi_nparts; 4820Sstevel@tonic-gate nparts++) { 4830Sstevel@tonic-gate if (cur_parts->etoc->efi_parts[nparts].p_tag == 4840Sstevel@tonic-gate V_RESERVED) { 4850Sstevel@tonic-gate (void) strcpy( 4860Sstevel@tonic-gate cur_parts->etoc->efi_parts[nparts].p_name, 4870Sstevel@tonic-gate volname); 4880Sstevel@tonic-gate (void) strlcpy(cur_disk->v_volume, volname, 4890Sstevel@tonic-gate LEN_DKL_VVOL); 4900Sstevel@tonic-gate break; 4910Sstevel@tonic-gate } 4920Sstevel@tonic-gate } 4930Sstevel@tonic-gate } 4940Sstevel@tonic-gate return (0); 4950Sstevel@tonic-gate break; 4960Sstevel@tonic-gate default: 4970Sstevel@tonic-gate /* Should never happen */ 4980Sstevel@tonic-gate return (-1); 4990Sstevel@tonic-gate } 5000Sstevel@tonic-gate } else if ((index == other_choice) && (cur_label == L_TYPE_SOLARIS)) { 5010Sstevel@tonic-gate /* 5020Sstevel@tonic-gate * User chose "other". 5030Sstevel@tonic-gate * Get the standard information on the new type. 5040Sstevel@tonic-gate * Put all information in a tmp structure, in 5050Sstevel@tonic-gate * case user aborts. 5060Sstevel@tonic-gate */ 5070Sstevel@tonic-gate bzero((char *)d, sizeof (struct disk_type)); 5080Sstevel@tonic-gate 5090Sstevel@tonic-gate d->dtype_ncyl = get_ncyl(); 5100Sstevel@tonic-gate d->dtype_acyl = get_acyl(d->dtype_ncyl); 5110Sstevel@tonic-gate d->dtype_pcyl = get_pcyl(d->dtype_ncyl, d->dtype_acyl); 5120Sstevel@tonic-gate d->dtype_nhead = get_nhead(); 5130Sstevel@tonic-gate d->dtype_phead = get_phead(d->dtype_nhead, &d->dtype_options); 5140Sstevel@tonic-gate d->dtype_nsect = get_nsect(); 5150Sstevel@tonic-gate d->dtype_psect = get_psect(&d->dtype_options); 5160Sstevel@tonic-gate d->dtype_bpt = get_bpt(d->dtype_nsect, &d->dtype_options); 5170Sstevel@tonic-gate d->dtype_rpm = get_rpm(); 5180Sstevel@tonic-gate d->dtype_fmt_time = get_fmt_time(&d->dtype_options); 5190Sstevel@tonic-gate d->dtype_cyl_skew = get_cyl_skew(&d->dtype_options); 5200Sstevel@tonic-gate d->dtype_trk_skew = get_trk_skew(&d->dtype_options); 5210Sstevel@tonic-gate d->dtype_trks_zone = get_trks_zone(&d->dtype_options); 5220Sstevel@tonic-gate d->dtype_atrks = get_atrks(&d->dtype_options); 5230Sstevel@tonic-gate d->dtype_asect = get_asect(&d->dtype_options); 5240Sstevel@tonic-gate d->dtype_cache = get_cache(&d->dtype_options); 5250Sstevel@tonic-gate d->dtype_threshold = get_threshold(&d->dtype_options); 5260Sstevel@tonic-gate d->dtype_prefetch_min = get_min_prefetch(&d->dtype_options); 5270Sstevel@tonic-gate d->dtype_prefetch_max = get_max_prefetch(d->dtype_prefetch_min, 5280Sstevel@tonic-gate &d->dtype_options); 5290Sstevel@tonic-gate d->dtype_bps = get_bps(); 5300Sstevel@tonic-gate #if defined(sparc) 5310Sstevel@tonic-gate d->dtype_dr_type = 0; 5320Sstevel@tonic-gate #endif /* defined(sparc) */ 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate d->dtype_asciilabel = get_asciilabel(); 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate /* 5370Sstevel@tonic-gate * Add the new type to the list of possible types for 5380Sstevel@tonic-gate * this controller. We lock out interrupts so the lists 5390Sstevel@tonic-gate * can't get munged. We put off actually allocating the 5400Sstevel@tonic-gate * structure till here in case the user wanted to 5410Sstevel@tonic-gate * interrupt while still inputting information. 5420Sstevel@tonic-gate */ 5430Sstevel@tonic-gate enter_critical(); 5440Sstevel@tonic-gate tptr = (struct disk_type *)zalloc(sizeof (struct disk_type)); 5450Sstevel@tonic-gate if (type == NULL) 5460Sstevel@tonic-gate cur_ctype->ctype_dlist = tptr; 5470Sstevel@tonic-gate else { 5480Sstevel@tonic-gate while (type->dtype_next != NULL) 5490Sstevel@tonic-gate type = type->dtype_next; 5500Sstevel@tonic-gate type->dtype_next = tptr; 5510Sstevel@tonic-gate } 5520Sstevel@tonic-gate bcopy((char *)d, (char *)tptr, sizeof (disk_type)); 5530Sstevel@tonic-gate tptr->dtype_next = NULL; 5540Sstevel@tonic-gate /* 5550Sstevel@tonic-gate * the new disk type does not have any defined 5560Sstevel@tonic-gate * partition table . Hence copy the current partition 5570Sstevel@tonic-gate * table if possible else create a default 5580Sstevel@tonic-gate * paritition table. 5590Sstevel@tonic-gate */ 5600Sstevel@tonic-gate new_partitiontable(tptr, oldtype); 5610Sstevel@tonic-gate } else if ((index == other_choice) && (cur_label == L_TYPE_EFI)) { 5620Sstevel@tonic-gate maxLBA = get_mlba(); 5630Sstevel@tonic-gate cur_parts->etoc->efi_last_lba = maxLBA; 5640Sstevel@tonic-gate cur_parts->etoc->efi_last_u_lba = maxLBA - 34; 5650Sstevel@tonic-gate for (i = 0; i < cur_parts->etoc->efi_nparts; i++) { 5660Sstevel@tonic-gate cur_parts->etoc->efi_parts[i].p_start = 0; 5670Sstevel@tonic-gate cur_parts->etoc->efi_parts[i].p_size = 0; 5680Sstevel@tonic-gate cur_parts->etoc->efi_parts[i].p_tag = V_UNASSIGNED; 5690Sstevel@tonic-gate } 5700Sstevel@tonic-gate cur_parts->etoc->efi_parts[8].p_start = 5710Sstevel@tonic-gate maxLBA - 34 - (1024 * 16); 5720Sstevel@tonic-gate cur_parts->etoc->efi_parts[8].p_size = (1024 * 16); 5730Sstevel@tonic-gate cur_parts->etoc->efi_parts[8].p_tag = V_RESERVED; 5740Sstevel@tonic-gate if (write_label()) { 5750Sstevel@tonic-gate err_print("Write label failed\n"); 5760Sstevel@tonic-gate } else { 5770Sstevel@tonic-gate cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate return (0); 5800Sstevel@tonic-gate } else { 5810Sstevel@tonic-gate /* 5820Sstevel@tonic-gate * User picked an existing disk type. 5830Sstevel@tonic-gate */ 5840Sstevel@tonic-gate i = first_disk; 5850Sstevel@tonic-gate tptr = type; 5860Sstevel@tonic-gate while (i < index) { 5870Sstevel@tonic-gate if (tptr->dtype_asciilabel) { 5880Sstevel@tonic-gate i++; 5890Sstevel@tonic-gate } 5900Sstevel@tonic-gate tptr = tptr->dtype_next; 5910Sstevel@tonic-gate } 5920Sstevel@tonic-gate if ((tptr->dtype_asciilabel == NULL) && 5930Sstevel@tonic-gate (tptr->dtype_next != NULL)) { 5940Sstevel@tonic-gate while (tptr->dtype_asciilabel == NULL) { 5950Sstevel@tonic-gate tptr = tptr->dtype_next; 5960Sstevel@tonic-gate } 5970Sstevel@tonic-gate } 5980Sstevel@tonic-gate } 5990Sstevel@tonic-gate /* 6000Sstevel@tonic-gate * Check for mounted file systems in the format zone. 6010Sstevel@tonic-gate * One potential problem with this would be that check() 6020Sstevel@tonic-gate * always returns 'yes' when running out of a file. However, 6030Sstevel@tonic-gate * it is actually ok because we don't let the program get 6040Sstevel@tonic-gate * started if there are mounted file systems and we are 6050Sstevel@tonic-gate * running from a file. 6060Sstevel@tonic-gate */ 6070Sstevel@tonic-gate if ((tptr != oldtype) && 6087563SPrasad.Singamsetty@Sun.COM checkmount((diskaddr_t)-1, (diskaddr_t)-1)) { 6090Sstevel@tonic-gate err_print( 6100Sstevel@tonic-gate "Cannot set disk type while it has mounted partitions.\n\n"); 6110Sstevel@tonic-gate return (-1); 6120Sstevel@tonic-gate } 6130Sstevel@tonic-gate /* 6140Sstevel@tonic-gate * check for partitions being used for swapping in format zone 6150Sstevel@tonic-gate */ 6160Sstevel@tonic-gate if ((tptr != oldtype) && 6177563SPrasad.Singamsetty@Sun.COM checkswap((diskaddr_t)-1, (diskaddr_t)-1)) { 6180Sstevel@tonic-gate err_print("Cannot set disk type while its partition are \ 6190Sstevel@tonic-gate currently being used for swapping.\n"); 6200Sstevel@tonic-gate return (-1); 6210Sstevel@tonic-gate } 622767Ssjelinek 623767Ssjelinek /* 624767Ssjelinek * Check for partitions being used in SVM, VxVM or LU devices 625767Ssjelinek */ 626767Ssjelinek 627767Ssjelinek if ((tptr != oldtype) && 628767Ssjelinek checkdevinuse(cur_disk->disk_name, (diskaddr_t)-1, 629767Ssjelinek (diskaddr_t)-1, 0, 0)) { 630767Ssjelinek err_print("Cannot set disk type while its " 631767Ssjelinek "partitions are currently in use.\n"); 632767Ssjelinek return (-1); 633767Ssjelinek } 6340Sstevel@tonic-gate /* 6350Sstevel@tonic-gate * If the type selected is different from the previous type, 6360Sstevel@tonic-gate * mark the disk as not labelled and reload the current 6370Sstevel@tonic-gate * partition info. This is not essential but probably the 6380Sstevel@tonic-gate * right thing to do, since the size of the disk has probably 6390Sstevel@tonic-gate * changed. 6400Sstevel@tonic-gate */ 6410Sstevel@tonic-gate enter_critical(); 6420Sstevel@tonic-gate if (tptr != oldtype) { 6430Sstevel@tonic-gate cur_disk->disk_type = tptr; 6440Sstevel@tonic-gate cur_disk->disk_parts = NULL; 6450Sstevel@tonic-gate cur_disk->disk_flags &= ~DSK_LABEL; 6460Sstevel@tonic-gate } 6470Sstevel@tonic-gate /* 6480Sstevel@tonic-gate * Initialize the state of the current disk. 6490Sstevel@tonic-gate */ 6500Sstevel@tonic-gate init_globals(cur_disk); 6510Sstevel@tonic-gate (void) get_partition(); 6520Sstevel@tonic-gate exit_critical(); 6530Sstevel@tonic-gate 6540Sstevel@tonic-gate /* 6550Sstevel@tonic-gate * If the label of the disk is marked dirty, 6560Sstevel@tonic-gate * see if they'd like to label the disk now. 6570Sstevel@tonic-gate */ 6580Sstevel@tonic-gate if (cur_disk->disk_flags & DSK_LABEL_DIRTY) { 6590Sstevel@tonic-gate if (check("Disk not labeled. Label it now") == 0) { 6600Sstevel@tonic-gate if (write_label()) { 6610Sstevel@tonic-gate err_print("Write label failed\n"); 6620Sstevel@tonic-gate } else { 6630Sstevel@tonic-gate cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 6640Sstevel@tonic-gate } 6650Sstevel@tonic-gate } 6660Sstevel@tonic-gate } 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate return (0); 6690Sstevel@tonic-gate } 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate /* 6720Sstevel@tonic-gate * This routine implements the 'partition' command. It simply runs 6730Sstevel@tonic-gate * the partition menu. 6740Sstevel@tonic-gate */ 6750Sstevel@tonic-gate int 6760Sstevel@tonic-gate c_partition() 6770Sstevel@tonic-gate { 6780Sstevel@tonic-gate 6790Sstevel@tonic-gate /* 6800Sstevel@tonic-gate * There must be a current disk type and a current disk 6810Sstevel@tonic-gate */ 6820Sstevel@tonic-gate if (cur_dtype == NULL) { 6830Sstevel@tonic-gate err_print("Current Disk Type is not set.\n"); 6840Sstevel@tonic-gate return (-1); 6850Sstevel@tonic-gate } 6860Sstevel@tonic-gate /* 6870Sstevel@tonic-gate * Check for a valid fdisk table entry for Solaris 6880Sstevel@tonic-gate */ 6890Sstevel@tonic-gate if (!good_fdisk()) { 6900Sstevel@tonic-gate return (-1); 6910Sstevel@tonic-gate } 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate cur_menu++; 6940Sstevel@tonic-gate last_menu = cur_menu; 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate #ifdef not 6970Sstevel@tonic-gate /* 6980Sstevel@tonic-gate * If there is no current partition table, make one. This is 6990Sstevel@tonic-gate * so the commands within the menu never have to check for 7000Sstevel@tonic-gate * a non-existent table. 7010Sstevel@tonic-gate */ 7020Sstevel@tonic-gate if (cur_parts == NULL) 7030Sstevel@tonic-gate err_print("making partition.\n"); 7040Sstevel@tonic-gate make_partition(); 7050Sstevel@tonic-gate #endif /* not */ 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate /* 7080Sstevel@tonic-gate * Run the menu. 7090Sstevel@tonic-gate */ 7100Sstevel@tonic-gate run_menu(menu_partition, "PARTITION", "partition", 0); 7110Sstevel@tonic-gate cur_menu--; 7120Sstevel@tonic-gate return (0); 7130Sstevel@tonic-gate } 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate /* 7160Sstevel@tonic-gate * This routine implements the 'current' command. It describes the 7170Sstevel@tonic-gate * current disk. 7180Sstevel@tonic-gate */ 7190Sstevel@tonic-gate int 7200Sstevel@tonic-gate c_current() 7210Sstevel@tonic-gate { 7220Sstevel@tonic-gate 7230Sstevel@tonic-gate /* 7240Sstevel@tonic-gate * If there is no current disk, say so. Note that this is 7250Sstevel@tonic-gate * not an error since it is a legitimate response to the inquiry. 7260Sstevel@tonic-gate */ 7270Sstevel@tonic-gate if (cur_disk == NULL) { 7280Sstevel@tonic-gate fmt_print("No Current Disk.\n"); 7290Sstevel@tonic-gate return (0); 7300Sstevel@tonic-gate } 7310Sstevel@tonic-gate /* 7320Sstevel@tonic-gate * Print out the info we have on the current disk. 7330Sstevel@tonic-gate */ 7340Sstevel@tonic-gate fmt_print("Current Disk = %s", cur_disk->disk_name); 7350Sstevel@tonic-gate if (chk_volname(cur_disk)) { 7360Sstevel@tonic-gate fmt_print(": "); 7370Sstevel@tonic-gate print_volname(cur_disk); 7380Sstevel@tonic-gate } 7390Sstevel@tonic-gate fmt_print("\n"); 7400Sstevel@tonic-gate if (cur_disk->devfs_name != NULL) { 7410Sstevel@tonic-gate if (cur_dtype == NULL) { 7420Sstevel@tonic-gate fmt_print("<type unknown>\n"); 7430Sstevel@tonic-gate } else if (cur_label == L_TYPE_SOLARIS) { 7440Sstevel@tonic-gate fmt_print("<%s cyl %d alt %d hd %d sec %d>\n", 7450Sstevel@tonic-gate cur_dtype->dtype_asciilabel, ncyl, 7460Sstevel@tonic-gate acyl, nhead, nsect); 7470Sstevel@tonic-gate } else if (cur_label == L_TYPE_EFI) { 7480Sstevel@tonic-gate print_efi_string(cur_dtype->vendor, 7490Sstevel@tonic-gate cur_dtype->product, cur_dtype->revision, 7500Sstevel@tonic-gate cur_dtype->capacity); 7510Sstevel@tonic-gate fmt_print("\n"); 7520Sstevel@tonic-gate } 7530Sstevel@tonic-gate fmt_print("%s\n", cur_disk->devfs_name); 7540Sstevel@tonic-gate } else { 7550Sstevel@tonic-gate fmt_print("%s%d: <", cur_ctlr->ctlr_dname, 7560Sstevel@tonic-gate cur_disk->disk_dkinfo.dki_unit); 7570Sstevel@tonic-gate if (cur_dtype == NULL) { 7580Sstevel@tonic-gate fmt_print("type unknown"); 7590Sstevel@tonic-gate } else if (cur_label == L_TYPE_SOLARIS) { 7600Sstevel@tonic-gate fmt_print("%s cyl %d alt %d hd %d sec %d", 7610Sstevel@tonic-gate cur_dtype->dtype_asciilabel, ncyl, 7620Sstevel@tonic-gate acyl, nhead, nsect); 7630Sstevel@tonic-gate } else if (cur_label == L_TYPE_EFI) { 7640Sstevel@tonic-gate print_efi_string(cur_dtype->vendor, 7650Sstevel@tonic-gate cur_dtype->product, cur_dtype->revision, 7660Sstevel@tonic-gate cur_dtype->capacity); 7670Sstevel@tonic-gate fmt_print("\n"); 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate fmt_print(">\n"); 7700Sstevel@tonic-gate } 7710Sstevel@tonic-gate fmt_print("\n"); 7720Sstevel@tonic-gate return (0); 7730Sstevel@tonic-gate } 7740Sstevel@tonic-gate /* 7750Sstevel@tonic-gate * This routine implements the 'format' command. It allows the user 7760Sstevel@tonic-gate * to format and verify any portion of the disk. 7770Sstevel@tonic-gate */ 7780Sstevel@tonic-gate int 7790Sstevel@tonic-gate c_format() 7800Sstevel@tonic-gate { 7810Sstevel@tonic-gate diskaddr_t start, end; 782767Ssjelinek time_t clock; 783767Ssjelinek int format_time, format_tracks, format_cyls; 784767Ssjelinek int format_interval; 7857563SPrasad.Singamsetty@Sun.COM diskaddr_t deflt; 7867563SPrasad.Singamsetty@Sun.COM int status; 787767Ssjelinek u_ioparam_t ioparam; 7880Sstevel@tonic-gate 7890Sstevel@tonic-gate /* 7900Sstevel@tonic-gate * There must be a current disk type and a current disk 7910Sstevel@tonic-gate */ 7920Sstevel@tonic-gate if (cur_dtype == NULL) { 7930Sstevel@tonic-gate err_print("Current Disk Type is not set.\n"); 7940Sstevel@tonic-gate return (-1); 7950Sstevel@tonic-gate } 7960Sstevel@tonic-gate 7970Sstevel@tonic-gate /* 7980Sstevel@tonic-gate * There must be a format routine in cur_ops structure to have 7990Sstevel@tonic-gate * this routine work. 8000Sstevel@tonic-gate */ 8010Sstevel@tonic-gate if (cur_ops->op_format == NULL) { 8020Sstevel@tonic-gate err_print( 8030Sstevel@tonic-gate "Cannot format this drive. Please use your Manufacturer supplied formatting " 8040Sstevel@tonic-gate "utility.\n"); 8050Sstevel@tonic-gate return (-1); 8060Sstevel@tonic-gate } 8070Sstevel@tonic-gate 8080Sstevel@tonic-gate /* 8090Sstevel@tonic-gate * There must be a current defect list. Except for 8100Sstevel@tonic-gate * unformatted SCSI disks. For them the defect list 8110Sstevel@tonic-gate * can only be retrieved after formatting the disk. 8120Sstevel@tonic-gate */ 8130Sstevel@tonic-gate if ((cur_ctype->ctype_flags & CF_SCSI) && !EMBEDDED_SCSI && 8140Sstevel@tonic-gate (cur_ctype->ctype_flags & CF_DEFECTS) && 8150Sstevel@tonic-gate ! (cur_flags & DISK_FORMATTED)) { 8160Sstevel@tonic-gate cur_list.flags |= LIST_RELOAD; 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate } else if (cur_list.list == NULL && !EMBEDDED_SCSI) { 8190Sstevel@tonic-gate err_print("Current Defect List must be initialized.\n"); 8200Sstevel@tonic-gate return (-1); 8210Sstevel@tonic-gate } 8220Sstevel@tonic-gate /* 8230Sstevel@tonic-gate * Ask for the bounds of the format. We always use the whole 8240Sstevel@tonic-gate * disk as the default, since that is the most likely case. 8250Sstevel@tonic-gate * Note, for disks which must be formatted accross the whole disk, 8260Sstevel@tonic-gate * don't bother the user. 8270Sstevel@tonic-gate */ 8280Sstevel@tonic-gate ioparam.io_bounds.lower = start = 0; 8290Sstevel@tonic-gate if (cur_label == L_TYPE_SOLARIS) { 8300Sstevel@tonic-gate if (cur_ctype->ctype_flags & CF_SCSI) { 8310Sstevel@tonic-gate ioparam.io_bounds.upper = end = datasects() - 1; 8320Sstevel@tonic-gate } else { 8330Sstevel@tonic-gate ioparam.io_bounds.upper = end = physsects() - 1; 8340Sstevel@tonic-gate } 8350Sstevel@tonic-gate } else { 8360Sstevel@tonic-gate ioparam.io_bounds.upper = end = cur_parts->etoc->efi_last_lba; 8370Sstevel@tonic-gate } 8380Sstevel@tonic-gate 8390Sstevel@tonic-gate if (! (cur_ctlr->ctlr_flags & DKI_FMTVOL)) { 8400Sstevel@tonic-gate deflt = ioparam.io_bounds.lower; 8410Sstevel@tonic-gate start = input(FIO_BN, 8420Sstevel@tonic-gate "Enter starting block number", ':', 8437563SPrasad.Singamsetty@Sun.COM &ioparam, (int *)&deflt, DATA_INPUT); 8440Sstevel@tonic-gate ioparam.io_bounds.lower = start; 8450Sstevel@tonic-gate deflt = ioparam.io_bounds.upper; 8460Sstevel@tonic-gate end = input(FIO_BN, 8470Sstevel@tonic-gate "Enter ending block number", ':', 8487563SPrasad.Singamsetty@Sun.COM &ioparam, (int *)&deflt, DATA_INPUT); 8490Sstevel@tonic-gate } 8500Sstevel@tonic-gate /* 8510Sstevel@tonic-gate * Some disks can format tracks. Make sure the whole track is 8520Sstevel@tonic-gate * specified for them. 8530Sstevel@tonic-gate */ 8540Sstevel@tonic-gate if (cur_ctlr->ctlr_flags & DKI_FMTTRK) { 8550Sstevel@tonic-gate if (bn2s(start) != 0 || 8560Sstevel@tonic-gate bn2s(end) != sectors(bn2h(end)) - 1) { 8570Sstevel@tonic-gate err_print("Controller requires formatting of "); 8580Sstevel@tonic-gate err_print("entire tracks.\n"); 8590Sstevel@tonic-gate return (-1); 8600Sstevel@tonic-gate } 8610Sstevel@tonic-gate } 8620Sstevel@tonic-gate /* 8630Sstevel@tonic-gate * Check for mounted file systems in the format zone, and if we 8640Sstevel@tonic-gate * find any, make sure they are really serious. One potential 8650Sstevel@tonic-gate * problem with this would be that check() always returns 'yes' 8660Sstevel@tonic-gate * when running out of a file. However, it is actually ok 8670Sstevel@tonic-gate * because we don't let the program get started if there are 8680Sstevel@tonic-gate * mounted file systems and we are running from a file. 8690Sstevel@tonic-gate */ 8700Sstevel@tonic-gate if (checkmount(start, end)) { 8710Sstevel@tonic-gate err_print( 8720Sstevel@tonic-gate "Cannot format disk while it has mounted partitions.\n\n"); 8730Sstevel@tonic-gate return (-1); 8740Sstevel@tonic-gate } 8750Sstevel@tonic-gate /* 8760Sstevel@tonic-gate * check for partitions being used for swapping in format zone 8770Sstevel@tonic-gate */ 8780Sstevel@tonic-gate if (checkswap(start, end)) { 8790Sstevel@tonic-gate err_print("Cannot format disk while its partition are \ 8800Sstevel@tonic-gate currently being used for swapping.\n"); 8810Sstevel@tonic-gate return (-1); 8820Sstevel@tonic-gate } 883767Ssjelinek /* 884767Ssjelinek * Check for partitions being used in SVM, VxVM or LU devices 885767Ssjelinek * in this format zone 886767Ssjelinek */ 887767Ssjelinek if (checkdevinuse(cur_disk->disk_name, start, end, 0, 0)) { 888767Ssjelinek err_print("Cannot format disk while its partitions " 889767Ssjelinek "are currently in use.\n"); 890767Ssjelinek return (-1); 891767Ssjelinek } 892767Ssjelinek 8930Sstevel@tonic-gate if (SCSI && (format_time = scsi_format_time()) > 0) { 8940Sstevel@tonic-gate fmt_print( 8950Sstevel@tonic-gate "Ready to format. Formatting cannot be interrupted\n" 8960Sstevel@tonic-gate "and takes %d minutes (estimated). ", format_time); 8970Sstevel@tonic-gate 8980Sstevel@tonic-gate } else if (cur_dtype->dtype_options & SUP_FMTTIME) { 8990Sstevel@tonic-gate /* 9000Sstevel@tonic-gate * Formatting time is (2 * time of 1 spin * number of 9010Sstevel@tonic-gate * tracks) + (step rate * number of cylinders) rounded 9020Sstevel@tonic-gate * up to the nearest minute. Note, a 10% fudge factor 9030Sstevel@tonic-gate * is thrown in for insurance. 9040Sstevel@tonic-gate */ 9050Sstevel@tonic-gate if (cur_dtype->dtype_fmt_time == 0) 9060Sstevel@tonic-gate cur_dtype->dtype_fmt_time = 2; 9070Sstevel@tonic-gate 9080Sstevel@tonic-gate format_tracks = ((end-start) / cur_dtype->dtype_nsect) + 1; 9090Sstevel@tonic-gate format_cyls = format_tracks / cur_dtype->dtype_nhead; 9100Sstevel@tonic-gate format_tracks = format_tracks * cur_dtype->dtype_fmt_time; 9110Sstevel@tonic-gate 9120Sstevel@tonic-gate /* 9130Sstevel@tonic-gate * ms. 9140Sstevel@tonic-gate */ 9150Sstevel@tonic-gate format_time = ((60000 / cur_dtype->dtype_rpm) +1) * 9160Sstevel@tonic-gate format_tracks + format_cyls * 7; 9170Sstevel@tonic-gate /* 9180Sstevel@tonic-gate * 20% done tick (sec) 9190Sstevel@tonic-gate */ 9200Sstevel@tonic-gate format_interval = format_time / 5000; 9210Sstevel@tonic-gate /* 9220Sstevel@tonic-gate * min. 9230Sstevel@tonic-gate */ 9240Sstevel@tonic-gate format_time = (format_time + 59999) / 60000; 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate /* 9270Sstevel@tonic-gate * Check format time values and make adjustments 9280Sstevel@tonic-gate * to prevent sleeping too long (forever?) or 9290Sstevel@tonic-gate * too short. 9300Sstevel@tonic-gate */ 9310Sstevel@tonic-gate if (format_time <= 1) { 9320Sstevel@tonic-gate /* 9330Sstevel@tonic-gate * Format time is less than 1 min.. 9340Sstevel@tonic-gate */ 9350Sstevel@tonic-gate format_time = 1; 9360Sstevel@tonic-gate } 9370Sstevel@tonic-gate 9380Sstevel@tonic-gate if (format_interval < 11) { 9390Sstevel@tonic-gate /* Format time is less than 1 minute. */ 9400Sstevel@tonic-gate if (format_interval < 2) 9410Sstevel@tonic-gate format_interval = 2; /* failsafe */ 9420Sstevel@tonic-gate format_interval = 10; 9430Sstevel@tonic-gate } else { 9440Sstevel@tonic-gate /* Format time is greater than 1 minute. */ 9450Sstevel@tonic-gate format_interval -= 10; 9460Sstevel@tonic-gate } 9470Sstevel@tonic-gate 9480Sstevel@tonic-gate fmt_print( 9490Sstevel@tonic-gate "Ready to format. Formatting cannot be interrupted\n" 9500Sstevel@tonic-gate "and takes %d minutes (estimated). ", format_time); 9510Sstevel@tonic-gate } else { 9520Sstevel@tonic-gate fmt_print( 9530Sstevel@tonic-gate "Ready to format. Formatting cannot be interrupted.\n"); 9540Sstevel@tonic-gate } 9550Sstevel@tonic-gate if (check("Continue")) { 9560Sstevel@tonic-gate return (-1); 9570Sstevel@tonic-gate } 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate /* 9600Sstevel@tonic-gate * Print the time so that the user will know when format started. 9610Sstevel@tonic-gate * Lock out interrupts. This could be a problem, since it could 9620Sstevel@tonic-gate * cause the user to sit for quite awhile with no control, but we 9630Sstevel@tonic-gate * don't have any other good way of keeping his gun from going off. 9640Sstevel@tonic-gate */ 9650Sstevel@tonic-gate clock = time((time_t *)0); 9660Sstevel@tonic-gate fmt_print("Beginning format. The current time is %s\n", 9670Sstevel@tonic-gate ctime(&clock)); 9680Sstevel@tonic-gate enter_critical(); 9690Sstevel@tonic-gate /* 9700Sstevel@tonic-gate * Mark the defect list dirty so it will be rewritten when we are 9710Sstevel@tonic-gate * done. It is possible to qualify this so it doesn't always 9720Sstevel@tonic-gate * get rewritten, but it's not worth the trouble. 9730Sstevel@tonic-gate * Note: no defect lists for embedded scsi drives. 9740Sstevel@tonic-gate */ 9750Sstevel@tonic-gate if (!EMBEDDED_SCSI) { 9760Sstevel@tonic-gate cur_list.flags |= LIST_DIRTY; 9770Sstevel@tonic-gate } 9780Sstevel@tonic-gate /* 9790Sstevel@tonic-gate * If we are formatting over any of the labels, mark the label 9800Sstevel@tonic-gate * dirty so it will be rewritten. 9810Sstevel@tonic-gate */ 9820Sstevel@tonic-gate if (cur_disk->label_type == L_TYPE_SOLARIS) { 9830Sstevel@tonic-gate if (start < totalsects() && end >= datasects()) { 9840Sstevel@tonic-gate if (cur_disk->disk_flags & DSK_LABEL) 9850Sstevel@tonic-gate cur_flags |= LABEL_DIRTY; 9860Sstevel@tonic-gate } 9870Sstevel@tonic-gate } else if (cur_disk->label_type == L_TYPE_EFI) { 9880Sstevel@tonic-gate if (start < 34) { 9890Sstevel@tonic-gate if (cur_disk->disk_flags & DSK_LABEL) 9900Sstevel@tonic-gate cur_flags |= LABEL_DIRTY; 9910Sstevel@tonic-gate } 9920Sstevel@tonic-gate } 9930Sstevel@tonic-gate if (start == 0) { 9940Sstevel@tonic-gate cur_flags |= LABEL_DIRTY; 9950Sstevel@tonic-gate } 9960Sstevel@tonic-gate /* 9970Sstevel@tonic-gate * Do the format. bugid 1009138 removed the use of fork to 9980Sstevel@tonic-gate * background the format and print a tick. 9990Sstevel@tonic-gate */ 10000Sstevel@tonic-gate 10010Sstevel@tonic-gate status = (*cur_ops->op_format)(start, end, &cur_list); 10020Sstevel@tonic-gate if (status) { 10030Sstevel@tonic-gate exit_critical(); 10040Sstevel@tonic-gate err_print("failed\n"); 10050Sstevel@tonic-gate return (-1); 10060Sstevel@tonic-gate } 10070Sstevel@tonic-gate fmt_print("done\n"); 10080Sstevel@tonic-gate if (option_msg && diag_msg) { 10090Sstevel@tonic-gate clock = time((time_t *)0); 10100Sstevel@tonic-gate fmt_print("The current time is %s\n", ctime(&clock)); 10110Sstevel@tonic-gate } 10120Sstevel@tonic-gate cur_flags |= DISK_FORMATTED; 10130Sstevel@tonic-gate /* 10140Sstevel@tonic-gate * If the defect list or label is dirty, write them out again. 10150Sstevel@tonic-gate * Note, for SCSI we have to wait til now to load defect list 10160Sstevel@tonic-gate * since we can't access it until after formatting a virgin disk. 10170Sstevel@tonic-gate */ 10180Sstevel@tonic-gate /* enter_critical(); */ 10190Sstevel@tonic-gate if (cur_list.flags & LIST_RELOAD) { 10200Sstevel@tonic-gate assert(!EMBEDDED_SCSI); 10210Sstevel@tonic-gate if (*cur_ops->op_ex_man == NULL || 10220Sstevel@tonic-gate (*cur_ops->op_ex_man)(&cur_list)) { 10230Sstevel@tonic-gate err_print("Warning: unable to reload defect list\n"); 10240Sstevel@tonic-gate cur_list.flags &= ~LIST_DIRTY; 10250Sstevel@tonic-gate return (-1); 10260Sstevel@tonic-gate } 10270Sstevel@tonic-gate cur_list.flags |= LIST_DIRTY; 10280Sstevel@tonic-gate } 10290Sstevel@tonic-gate 10300Sstevel@tonic-gate if (cur_list.flags & LIST_DIRTY) { 10310Sstevel@tonic-gate assert(!EMBEDDED_SCSI); 10320Sstevel@tonic-gate write_deflist(&cur_list); 10330Sstevel@tonic-gate cur_list.flags = 0; 10340Sstevel@tonic-gate } 10350Sstevel@tonic-gate if (cur_flags & LABEL_DIRTY) { 10360Sstevel@tonic-gate (void) write_label(); 10370Sstevel@tonic-gate cur_flags &= ~LABEL_DIRTY; 10380Sstevel@tonic-gate } 10390Sstevel@tonic-gate /* 10400Sstevel@tonic-gate * Come up for air, since the verify step does not need to 10410Sstevel@tonic-gate * be atomic (it does it's own lockouts when necessary). 10420Sstevel@tonic-gate */ 10430Sstevel@tonic-gate exit_critical(); 10440Sstevel@tonic-gate /* 10450Sstevel@tonic-gate * If we are supposed to verify, we do the 'write' test over 10460Sstevel@tonic-gate * the format zone. The rest of the analysis parameters are 10470Sstevel@tonic-gate * left the way they were. 10480Sstevel@tonic-gate */ 10490Sstevel@tonic-gate if (scan_auto) { 10500Sstevel@tonic-gate scan_entire = 0; 10510Sstevel@tonic-gate scan_lower = start; 10520Sstevel@tonic-gate scan_upper = end; 10530Sstevel@tonic-gate fmt_print("\nVerifying media..."); 10540Sstevel@tonic-gate status = do_scan(SCAN_PATTERN, F_SILENT); 10550Sstevel@tonic-gate } 10560Sstevel@tonic-gate /* 10570Sstevel@tonic-gate * If the defect list or label is dirty, write them out again. 10580Sstevel@tonic-gate */ 10590Sstevel@tonic-gate if (cur_list.flags & LIST_DIRTY) { 10600Sstevel@tonic-gate assert(!EMBEDDED_SCSI); 10610Sstevel@tonic-gate cur_list.flags = 0; 10620Sstevel@tonic-gate write_deflist(&cur_list); 10630Sstevel@tonic-gate } 10640Sstevel@tonic-gate if (cur_flags & LABEL_DIRTY) { 10650Sstevel@tonic-gate cur_flags &= ~LABEL_DIRTY; 10660Sstevel@tonic-gate (void) write_label(); 10670Sstevel@tonic-gate } 10680Sstevel@tonic-gate return (status); 10690Sstevel@tonic-gate } 10700Sstevel@tonic-gate 10710Sstevel@tonic-gate /* 10720Sstevel@tonic-gate * This routine implements the 'repair' command. It allows the user 10730Sstevel@tonic-gate * to reallocate sectors on the disk that have gone bad. 10740Sstevel@tonic-gate */ 10750Sstevel@tonic-gate int 10760Sstevel@tonic-gate c_repair() 10770Sstevel@tonic-gate { 10780Sstevel@tonic-gate diskaddr_t bn; 10790Sstevel@tonic-gate int status; 10800Sstevel@tonic-gate u_ioparam_t ioparam; 10810Sstevel@tonic-gate char buf[SECSIZE]; 10820Sstevel@tonic-gate int buf_is_good; 10830Sstevel@tonic-gate int block_has_error; 10840Sstevel@tonic-gate int i; 10850Sstevel@tonic-gate 10860Sstevel@tonic-gate /* 10870Sstevel@tonic-gate * There must be a current disk type (and therefore a current disk). 10880Sstevel@tonic-gate */ 10890Sstevel@tonic-gate if (cur_dtype == NULL) { 10900Sstevel@tonic-gate err_print("Current Disk Type is not set.\n"); 10910Sstevel@tonic-gate return (-1); 10920Sstevel@tonic-gate } 10930Sstevel@tonic-gate /* 10940Sstevel@tonic-gate * The current disk must be formatted for repair to work. 10950Sstevel@tonic-gate */ 10960Sstevel@tonic-gate if (!(cur_flags & DISK_FORMATTED)) { 10970Sstevel@tonic-gate err_print("Current Disk is unformatted.\n"); 10980Sstevel@tonic-gate return (-1); 10990Sstevel@tonic-gate } 11000Sstevel@tonic-gate /* 11010Sstevel@tonic-gate * Check for a valid fdisk table entry for Solaris 11020Sstevel@tonic-gate */ 11030Sstevel@tonic-gate if (!good_fdisk()) { 11040Sstevel@tonic-gate return (-1); 11050Sstevel@tonic-gate } 11060Sstevel@tonic-gate /* 11070Sstevel@tonic-gate * Repair is an optional command for controllers, so it may 11080Sstevel@tonic-gate * not be supported. 11090Sstevel@tonic-gate */ 11100Sstevel@tonic-gate if (cur_ops->op_repair == NULL) { 11110Sstevel@tonic-gate err_print("Controller does not support repairing.\n"); 11120Sstevel@tonic-gate err_print("or disk supports automatic defect management.\n"); 11130Sstevel@tonic-gate return (-1); 11140Sstevel@tonic-gate } 11150Sstevel@tonic-gate /* 11160Sstevel@tonic-gate * There must be a defect list for non-embedded scsi devices, 11170Sstevel@tonic-gate * since we will add to it. 11180Sstevel@tonic-gate */ 11190Sstevel@tonic-gate if (!EMBEDDED_SCSI && cur_list.list == NULL) { 11200Sstevel@tonic-gate err_print("Current Defect List must be initialized.\n"); 11210Sstevel@tonic-gate return (-1); 11220Sstevel@tonic-gate } 11230Sstevel@tonic-gate /* 11240Sstevel@tonic-gate * Ask the user which sector has gone bad. 11250Sstevel@tonic-gate */ 11260Sstevel@tonic-gate ioparam.io_bounds.lower = 0; 11270Sstevel@tonic-gate if (cur_disk->label_type == L_TYPE_SOLARIS) { 11280Sstevel@tonic-gate ioparam.io_bounds.upper = physsects() - 1; 11290Sstevel@tonic-gate } else { 11300Sstevel@tonic-gate ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; 11310Sstevel@tonic-gate } 11320Sstevel@tonic-gate bn = input(FIO_BN, 11330Sstevel@tonic-gate "Enter absolute block number of defect", ':', 11340Sstevel@tonic-gate &ioparam, (int *)NULL, DATA_INPUT); 11350Sstevel@tonic-gate /* 11360Sstevel@tonic-gate * Check to see if there is a mounted file system over the 11370Sstevel@tonic-gate * specified sector. If there is, make sure the user is 11380Sstevel@tonic-gate * really serious. 11390Sstevel@tonic-gate */ 11400Sstevel@tonic-gate if (checkmount(bn, bn)) { 11410Sstevel@tonic-gate if (check("Repair is in a mounted partition, continue")) 11420Sstevel@tonic-gate return (-1); 11430Sstevel@tonic-gate } 11440Sstevel@tonic-gate /* 11450Sstevel@tonic-gate * check for partitions being used for swapping in format zone 11460Sstevel@tonic-gate */ 11470Sstevel@tonic-gate if (checkswap(bn, bn)) { 11480Sstevel@tonic-gate if (check("Repair is in a partition which is currently \ 11490Sstevel@tonic-gate being used for swapping.\ncontinue")) 11500Sstevel@tonic-gate return (-1); 11510Sstevel@tonic-gate } 11520Sstevel@tonic-gate 1153767Ssjelinek if (checkdevinuse(cur_disk->disk_name, bn, bn, 0, 0)) { 1154767Ssjelinek if (check("Repair is in a partition which is currently " 1155767Ssjelinek "in use.\ncontinue")) 1156767Ssjelinek return (-1); 1157767Ssjelinek } 1158767Ssjelinek 11590Sstevel@tonic-gate /* 11600Sstevel@tonic-gate * Try to read the sector before repairing it. If we can 11610Sstevel@tonic-gate * get good data out of it, we can write that data back 11620Sstevel@tonic-gate * after the repair. If the sector looks ok, ask the 11630Sstevel@tonic-gate * user to confirm the repair, since it doesn't appear 11640Sstevel@tonic-gate * necessary. Try reading the block several times to 11650Sstevel@tonic-gate * see if we can read it consistently. 11660Sstevel@tonic-gate * 11670Sstevel@tonic-gate * First, let's see if the block appears to have problems... 11680Sstevel@tonic-gate */ 11690Sstevel@tonic-gate block_has_error = 1; 11700Sstevel@tonic-gate for (i = 0; i < 5; i++) { 11710Sstevel@tonic-gate status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, 11720Sstevel@tonic-gate 1, buf, (F_SILENT | F_ALLERRS), NULL); 11730Sstevel@tonic-gate if (status) 11740Sstevel@tonic-gate break; /* one of the tries failed */ 11750Sstevel@tonic-gate } 11760Sstevel@tonic-gate if (status == 0) { 11770Sstevel@tonic-gate block_has_error = 0; 11780Sstevel@tonic-gate if (check("\ 11790Sstevel@tonic-gate This block doesn't appear to be bad. Repair it anyway")) { 11800Sstevel@tonic-gate return (0); 11810Sstevel@tonic-gate } 11820Sstevel@tonic-gate } 11830Sstevel@tonic-gate /* 11840Sstevel@tonic-gate * Last chance... 11850Sstevel@tonic-gate */ 11860Sstevel@tonic-gate if (check("Ready to repair defect, continue")) { 11870Sstevel@tonic-gate return (-1); 11880Sstevel@tonic-gate } 11890Sstevel@tonic-gate /* 11900Sstevel@tonic-gate * We're committed to repairing it. Try to get any good 11910Sstevel@tonic-gate * data out of the block if possible. Note that we do 11920Sstevel@tonic-gate * not set the F_ALLERRS flag. 11930Sstevel@tonic-gate */ 11940Sstevel@tonic-gate buf_is_good = 0; 11950Sstevel@tonic-gate for (i = 0; i < 5; i++) { 11960Sstevel@tonic-gate status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, 11970Sstevel@tonic-gate 1, buf, F_SILENT, NULL); 11980Sstevel@tonic-gate if (status == 0) { 11990Sstevel@tonic-gate buf_is_good = 1; 12000Sstevel@tonic-gate break; 12010Sstevel@tonic-gate } 12020Sstevel@tonic-gate } 12030Sstevel@tonic-gate /* 12040Sstevel@tonic-gate * Lock out interrupts so the disk can't get out of sync with 12050Sstevel@tonic-gate * the defect list. 12060Sstevel@tonic-gate */ 12070Sstevel@tonic-gate enter_critical(); 12080Sstevel@tonic-gate 12090Sstevel@tonic-gate fmt_print("Repairing "); 12100Sstevel@tonic-gate if (block_has_error) { 12110Sstevel@tonic-gate fmt_print("%s error on ", buf_is_good ? "soft" : "hard"); 12120Sstevel@tonic-gate } 12130Sstevel@tonic-gate fmt_print("block %llu (", bn); 12140Sstevel@tonic-gate pr_dblock(fmt_print, bn); 12150Sstevel@tonic-gate fmt_print(")..."); 12160Sstevel@tonic-gate /* 12170Sstevel@tonic-gate * Do the repair. 12180Sstevel@tonic-gate */ 12190Sstevel@tonic-gate status = (*cur_ops->op_repair)(bn, F_NORMAL); 12200Sstevel@tonic-gate if (status) { 12210Sstevel@tonic-gate fmt_print("failed.\n\n"); 12220Sstevel@tonic-gate } else { 12230Sstevel@tonic-gate /* 12240Sstevel@tonic-gate * The repair worked. Write the old data to the new 12250Sstevel@tonic-gate * block if we were able to read it, otherwise 12260Sstevel@tonic-gate * zero out the new block. If it looks like the 12270Sstevel@tonic-gate * new block is bad, let the user know that, too. 12280Sstevel@tonic-gate * Should we attempt auto-repair in this case? 12290Sstevel@tonic-gate */ 12300Sstevel@tonic-gate fmt_print("ok.\n"); 12310Sstevel@tonic-gate if (!buf_is_good) { 12320Sstevel@tonic-gate bzero(buf, SECSIZE); 12330Sstevel@tonic-gate } 12340Sstevel@tonic-gate status = (*cur_ops->op_rdwr)(DIR_WRITE, cur_file, bn, 12350Sstevel@tonic-gate 1, buf, (F_SILENT | F_ALLERRS), NULL); 12360Sstevel@tonic-gate if (status == 0) { 12370Sstevel@tonic-gate status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, 12380Sstevel@tonic-gate bn, 1, buf, (F_SILENT | F_ALLERRS), NULL); 12390Sstevel@tonic-gate } 12400Sstevel@tonic-gate if (status) { 12410Sstevel@tonic-gate fmt_print("The new block %llu (", bn); 12420Sstevel@tonic-gate pr_dblock(fmt_print, bn); 12430Sstevel@tonic-gate fmt_print(") also appears defective.\n"); 12440Sstevel@tonic-gate } 12450Sstevel@tonic-gate fmt_print("\n"); 12460Sstevel@tonic-gate /* 12470Sstevel@tonic-gate * Add the bad sector to the defect list, write out 12480Sstevel@tonic-gate * the defect list, and kill off the working list so 12490Sstevel@tonic-gate * it will get synced up with the current defect list 12500Sstevel@tonic-gate * next time we need it. 12510Sstevel@tonic-gate * 12520Sstevel@tonic-gate * For embedded scsi, we don't require a defect list. 12530Sstevel@tonic-gate * However, if we have one, add the defect if the 12540Sstevel@tonic-gate * list includes the grown list. If not, kill it 12550Sstevel@tonic-gate * to force a resync if we need the list later. 12560Sstevel@tonic-gate */ 12570Sstevel@tonic-gate if (EMBEDDED_SCSI) { 12580Sstevel@tonic-gate if (cur_list.list != NULL) { 12590Sstevel@tonic-gate if (cur_list.flags & LIST_PGLIST) { 12600Sstevel@tonic-gate add_ldef(bn, &cur_list); 12610Sstevel@tonic-gate } else { 12620Sstevel@tonic-gate kill_deflist(&cur_list); 12630Sstevel@tonic-gate } 12640Sstevel@tonic-gate } 12650Sstevel@tonic-gate } else if (cur_ctype->ctype_flags & CF_WLIST) { 12660Sstevel@tonic-gate kill_deflist(&cur_list); 12670Sstevel@tonic-gate if (*cur_ops->op_ex_cur != NULL) { 12680Sstevel@tonic-gate (*cur_ops->op_ex_cur)(&cur_list); 12690Sstevel@tonic-gate fmt_print("Current list updated\n"); 12700Sstevel@tonic-gate } 12710Sstevel@tonic-gate } else { 12720Sstevel@tonic-gate add_ldef(bn, &cur_list); 12730Sstevel@tonic-gate write_deflist(&cur_list); 12740Sstevel@tonic-gate } 12750Sstevel@tonic-gate kill_deflist(&work_list); 12760Sstevel@tonic-gate } 12770Sstevel@tonic-gate exit_critical(); 12780Sstevel@tonic-gate /* 12790Sstevel@tonic-gate * Return status. 12800Sstevel@tonic-gate */ 12810Sstevel@tonic-gate return (status); 12820Sstevel@tonic-gate } 12830Sstevel@tonic-gate 12840Sstevel@tonic-gate /* 12850Sstevel@tonic-gate * This routine implements the 'show' command. It translates a disk 12860Sstevel@tonic-gate * block given in any format into decimal, hexadecimal, and 12870Sstevel@tonic-gate * cylinder/head/sector format. 12880Sstevel@tonic-gate */ 12890Sstevel@tonic-gate int 12900Sstevel@tonic-gate c_show() 12910Sstevel@tonic-gate { 12920Sstevel@tonic-gate u_ioparam_t ioparam; 12937563SPrasad.Singamsetty@Sun.COM diskaddr_t bn; 12940Sstevel@tonic-gate 12950Sstevel@tonic-gate /* 12960Sstevel@tonic-gate * There must be a current disk type, so we will know the geometry. 12970Sstevel@tonic-gate */ 12980Sstevel@tonic-gate if (cur_dtype == NULL) { 12990Sstevel@tonic-gate err_print("Current Disk Type is not set.\n"); 13000Sstevel@tonic-gate return (-1); 13010Sstevel@tonic-gate } 13020Sstevel@tonic-gate /* 13030Sstevel@tonic-gate * Ask the user for a disk block. 13040Sstevel@tonic-gate */ 13050Sstevel@tonic-gate ioparam.io_bounds.lower = 0; 13060Sstevel@tonic-gate if (cur_disk->label_type == L_TYPE_SOLARIS) { 13070Sstevel@tonic-gate ioparam.io_bounds.upper = physsects() - 1; 13080Sstevel@tonic-gate } else { 13090Sstevel@tonic-gate ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; 13100Sstevel@tonic-gate } 13117563SPrasad.Singamsetty@Sun.COM bn = input(FIO_BN, "Enter a disk block", ':', 13120Sstevel@tonic-gate &ioparam, (int *)NULL, DATA_INPUT); 13130Sstevel@tonic-gate /* 13140Sstevel@tonic-gate * Echo it back. 13150Sstevel@tonic-gate */ 13167563SPrasad.Singamsetty@Sun.COM fmt_print("Disk block = %lld = 0x%llx = (", bn, bn); 13170Sstevel@tonic-gate pr_dblock(fmt_print, bn); 13180Sstevel@tonic-gate fmt_print(")\n\n"); 13190Sstevel@tonic-gate return (0); 13200Sstevel@tonic-gate } 13210Sstevel@tonic-gate 13220Sstevel@tonic-gate /* 13230Sstevel@tonic-gate * This routine implements the 'label' command. It writes the 13240Sstevel@tonic-gate * primary and backup labels onto the current disk. 13250Sstevel@tonic-gate */ 13260Sstevel@tonic-gate int 13270Sstevel@tonic-gate c_label() 13280Sstevel@tonic-gate { 1329767Ssjelinek int status; 1330767Ssjelinek int deflt, *defltptr = NULL; 13310Sstevel@tonic-gate 13320Sstevel@tonic-gate /* 13330Sstevel@tonic-gate * There must be a current disk type (and therefore a current disk). 13340Sstevel@tonic-gate */ 13350Sstevel@tonic-gate if (cur_dtype == NULL) { 13360Sstevel@tonic-gate err_print("Current Disk Type is not set.\n"); 13370Sstevel@tonic-gate return (-1); 13380Sstevel@tonic-gate } 13390Sstevel@tonic-gate /* 13400Sstevel@tonic-gate * The current disk must be formatted to label it. 13410Sstevel@tonic-gate */ 13420Sstevel@tonic-gate if (!(cur_flags & DISK_FORMATTED)) { 13430Sstevel@tonic-gate err_print("Current Disk is unformatted.\n"); 13440Sstevel@tonic-gate return (-1); 13450Sstevel@tonic-gate } 13460Sstevel@tonic-gate /* 13470Sstevel@tonic-gate * Check for a valid fdisk table entry for Solaris 13480Sstevel@tonic-gate */ 13490Sstevel@tonic-gate if (!good_fdisk()) { 13500Sstevel@tonic-gate return (-1); 13510Sstevel@tonic-gate } 13520Sstevel@tonic-gate /* 13530Sstevel@tonic-gate * Check to see if there are any mounted file systems anywhere 13540Sstevel@tonic-gate * on the current disk. If so, refuse to label the disk, but 13550Sstevel@tonic-gate * only if the partitions would change for the mounted partitions. 13560Sstevel@tonic-gate * 13570Sstevel@tonic-gate */ 13587563SPrasad.Singamsetty@Sun.COM if (checkmount((diskaddr_t)-1, (diskaddr_t)-1)) { 13590Sstevel@tonic-gate /* Bleagh, too descriptive */ 13600Sstevel@tonic-gate if (check_label_with_mount()) { 13610Sstevel@tonic-gate err_print("Cannot label disk while it has " 13620Sstevel@tonic-gate "mounted partitions.\n\n"); 13630Sstevel@tonic-gate return (-1); 13640Sstevel@tonic-gate } 13650Sstevel@tonic-gate } 13660Sstevel@tonic-gate 13670Sstevel@tonic-gate /* 13680Sstevel@tonic-gate * check to see if there any partitions being used for swapping 13690Sstevel@tonic-gate * on the current disk. If so, refuse to label the disk, but 13700Sstevel@tonic-gate * only if the partitions would change for the mounted partitions. 13710Sstevel@tonic-gate */ 13727563SPrasad.Singamsetty@Sun.COM if (checkswap((diskaddr_t)-1, (diskaddr_t)-1)) { 13730Sstevel@tonic-gate if (check_label_with_swap()) { 13740Sstevel@tonic-gate err_print("Cannot label disk while its " 13750Sstevel@tonic-gate "partitions are currently being used for " 13760Sstevel@tonic-gate "swapping.\n"); 13770Sstevel@tonic-gate return (-1); 13780Sstevel@tonic-gate } 13790Sstevel@tonic-gate } 13800Sstevel@tonic-gate 1381767Ssjelinek /* 1382767Ssjelinek * Check to see if any partitions used for svm, vxvm or live upgrade 1383767Ssjelinek * are on the disk. If so, refuse to label the disk, but only 1384767Ssjelinek * if we are trying to shrink a partition in use. 1385767Ssjelinek */ 1386767Ssjelinek if (checkdevinuse(cur_disk->disk_name, (diskaddr_t)-1, 1387767Ssjelinek (diskaddr_t)-1, 0, 1)) { 1388767Ssjelinek err_print("Cannot label disk when " 1389767Ssjelinek "partitions are in use as described.\n"); 1390767Ssjelinek return (-1); 1391767Ssjelinek } 13920Sstevel@tonic-gate 13930Sstevel@tonic-gate /* 13940Sstevel@tonic-gate * If there is not a current partition map, warn the user we 13950Sstevel@tonic-gate * are going to use the default. The default is the first 13960Sstevel@tonic-gate * partition map we encountered in the data file. If there is 13970Sstevel@tonic-gate * no default we give up. 13980Sstevel@tonic-gate */ 13990Sstevel@tonic-gate if (cur_parts == NULL) { 14000Sstevel@tonic-gate fmt_print("Current Partition Table is not set, " 14010Sstevel@tonic-gate "using default.\n"); 14020Sstevel@tonic-gate cur_disk->disk_parts = cur_parts = cur_dtype->dtype_plist; 14030Sstevel@tonic-gate if (cur_parts == NULL) { 14040Sstevel@tonic-gate err_print("No default available, cannot label.\n"); 14050Sstevel@tonic-gate return (-1); 14060Sstevel@tonic-gate } 14070Sstevel@tonic-gate } 14080Sstevel@tonic-gate /* 14090Sstevel@tonic-gate * If expert (-e) mode, then ask user if they wish 14100Sstevel@tonic-gate * to change the current solaris label into an EFI one 14110Sstevel@tonic-gate */ 14120Sstevel@tonic-gate if (expert_mode) { 14130Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 14140Sstevel@tonic-gate int i; 14150Sstevel@tonic-gate #endif 14160Sstevel@tonic-gate int choice; 14170Sstevel@tonic-gate u_ioparam_t ioparam; 14187563SPrasad.Singamsetty@Sun.COM struct extvtoc vtoc; 14190Sstevel@tonic-gate struct dk_label label; 14200Sstevel@tonic-gate struct dk_gpt *vtoc64; 14210Sstevel@tonic-gate struct efi_info efinfo; 14220Sstevel@tonic-gate struct disk_type *dptr; 14230Sstevel@tonic-gate 14247563SPrasad.Singamsetty@Sun.COM /* Ask user what label to use */ 14250Sstevel@tonic-gate fmt_print("[0] SMI Label\n"); 14260Sstevel@tonic-gate fmt_print("[1] EFI Label\n"); 14270Sstevel@tonic-gate ioparam.io_bounds.lower = 0; 14280Sstevel@tonic-gate ioparam.io_bounds.upper = 1; 14290Sstevel@tonic-gate if (cur_label == L_TYPE_SOLARIS) 14300Sstevel@tonic-gate deflt = 0; 14310Sstevel@tonic-gate else 14320Sstevel@tonic-gate deflt = 1; 14330Sstevel@tonic-gate defltptr = &deflt; 14340Sstevel@tonic-gate choice = input(FIO_INT, "Specify Label type", ':', 14350Sstevel@tonic-gate &ioparam, defltptr, DATA_INPUT); 14360Sstevel@tonic-gate if ((choice == 0) && (cur_label == L_TYPE_SOLARIS)) { 14370Sstevel@tonic-gate goto expert_end; 14380Sstevel@tonic-gate } else if ((choice == 1) && (cur_label == L_TYPE_EFI)) { 14390Sstevel@tonic-gate goto expert_end; 14400Sstevel@tonic-gate } 14410Sstevel@tonic-gate switch (choice) { 14420Sstevel@tonic-gate case 0: 14430Sstevel@tonic-gate /* 14440Sstevel@tonic-gate * EFI label to SMI label 14450Sstevel@tonic-gate */ 14460Sstevel@tonic-gate if (cur_dtype->capacity > INFINITY) { 14477563SPrasad.Singamsetty@Sun.COM fmt_print("Warning: SMI labels only support up to 2 TB.\n"); 14480Sstevel@tonic-gate } 14490Sstevel@tonic-gate 14507563SPrasad.Singamsetty@Sun.COM if (cur_disk->fdisk_part.systid == EFI_PMBR) { 14517563SPrasad.Singamsetty@Sun.COM fmt_print("Warning: This disk has an EFI label. Changing to" 14527563SPrasad.Singamsetty@Sun.COM " SMI label will erase all\ncurrent partitions.\n"); 14537563SPrasad.Singamsetty@Sun.COM if (check("Continue")) 1454786Slclee return (-1); 14557563SPrasad.Singamsetty@Sun.COM #if defined(_FIRMWARE_NEEDS_FDISK) 14567563SPrasad.Singamsetty@Sun.COM fmt_print("You must use fdisk to delete the current " 14571344Syl194034 "EFI partition and create a new\n" 14581344Syl194034 "Solaris partition before you can convert the " 14591344Syl194034 "label.\n"); 14607563SPrasad.Singamsetty@Sun.COM return (-1); 14617563SPrasad.Singamsetty@Sun.COM #endif 14627563SPrasad.Singamsetty@Sun.COM } 14637563SPrasad.Singamsetty@Sun.COM 14647563SPrasad.Singamsetty@Sun.COM #if defined(_FIRMWARE_NEEDS_FDISK) 14657563SPrasad.Singamsetty@Sun.COM if (!(((cur_disk->fdisk_part.systid != SUNIXOS) || 14667563SPrasad.Singamsetty@Sun.COM (cur_disk->fdisk_part.systid != SUNIXOS2)) && 14677563SPrasad.Singamsetty@Sun.COM (cur_disk->fdisk_part.numsect > 0))) { 14687563SPrasad.Singamsetty@Sun.COM fmt_print("You must use fdisk to create a Solaris " 14697563SPrasad.Singamsetty@Sun.COM "partition before you can convert the label.\n"); 14701344Syl194034 return (-1); 14711344Syl194034 } 14727563SPrasad.Singamsetty@Sun.COM #endif 14737563SPrasad.Singamsetty@Sun.COM 14747563SPrasad.Singamsetty@Sun.COM (void) memset((char *)&label, 0, sizeof (struct dk_label)); 14751344Syl194034 1476791Sshidokht (void) strcpy(x86_devname, cur_disk->disk_name); 1477786Slclee if (cur_ctype->ctype_ctype == DKC_DIRECT) 1478786Slclee dptr = auto_direct_get_geom_label(cur_file, &label); 1479786Slclee else 1480786Slclee dptr = auto_sense(cur_file, 1, &label); 14810Sstevel@tonic-gate if (dptr == NULL) { 1482786Slclee fmt_print("Autoconfiguration failed.\n"); 1483786Slclee return (-1); 14840Sstevel@tonic-gate } 14850Sstevel@tonic-gate 1486786Slclee pcyl = label.dkl_pcyl; 1487786Slclee ncyl = label.dkl_ncyl; 1488786Slclee acyl = label.dkl_acyl; 1489786Slclee nhead = label.dkl_nhead; 1490786Slclee nsect = label.dkl_nsect; 1491786Slclee 14921524Slh195018 if (delete_disk_type(cur_disk->disk_type) == 0) { 14931524Slh195018 cur_label = L_TYPE_SOLARIS; 14941524Slh195018 cur_disk->label_type = L_TYPE_SOLARIS; 14951524Slh195018 cur_disk->disk_type = dptr; 14961524Slh195018 cur_disk->disk_parts = dptr->dtype_plist; 14971524Slh195018 cur_dtype = dptr; 14981524Slh195018 cur_parts = dptr->dtype_plist; 1499786Slclee 15001524Slh195018 if (status = write_label()) 15011524Slh195018 err_print("Label failed.\n"); 15021524Slh195018 else 15031524Slh195018 cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 15041524Slh195018 15051524Slh195018 return (status); 15061524Slh195018 } else { 1507786Slclee err_print("Label failed.\n"); 15081524Slh195018 return (-1); 15091524Slh195018 } 1510786Slclee 1511786Slclee 15120Sstevel@tonic-gate case 1: 15130Sstevel@tonic-gate /* 15140Sstevel@tonic-gate * SMI label to EFI label 15150Sstevel@tonic-gate */ 1516786Slclee 1517786Slclee 1518786Slclee fmt_print("Warning: This disk has an SMI label. Changing to " 1519786Slclee "EFI label will erase all\ncurrent partitions.\n"); 1520786Slclee 1521786Slclee if (check("Continue")) { 15220Sstevel@tonic-gate return (-1); 15230Sstevel@tonic-gate } 15240Sstevel@tonic-gate 15250Sstevel@tonic-gate if (get_disk_info(cur_file, &efinfo) != 0) { 15260Sstevel@tonic-gate return (-1); 15270Sstevel@tonic-gate } 15280Sstevel@tonic-gate (void) memset((char *)&label, 0, sizeof (struct dk_label)); 15290Sstevel@tonic-gate label.dkl_pcyl = pcyl; 15300Sstevel@tonic-gate label.dkl_ncyl = ncyl; 15310Sstevel@tonic-gate label.dkl_acyl = acyl; 15320Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16) 15330Sstevel@tonic-gate label.dkl_bcyl = bcyl; 15340Sstevel@tonic-gate #endif /* defined(_SUNOC_VTOC_16) */ 15350Sstevel@tonic-gate label.dkl_nhead = nhead; 15360Sstevel@tonic-gate label.dkl_nsect = nsect; 15370Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 15380Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 15390Sstevel@tonic-gate label.dkl_map[i] = cur_parts->pinfo_map[i]; 15400Sstevel@tonic-gate } 15410Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 15420Sstevel@tonic-gate label.dkl_magic = DKL_MAGIC; 15430Sstevel@tonic-gate label.dkl_vtoc = cur_parts->vtoc; 15440Sstevel@tonic-gate if (label_to_vtoc(&vtoc, &label) == -1) { 15450Sstevel@tonic-gate return (-1); 15460Sstevel@tonic-gate } 15471067Sgz161490 if (SMI_vtoc_to_EFI(cur_file, &vtoc64) == -1) { 15480Sstevel@tonic-gate return (-1); 15490Sstevel@tonic-gate } 15500Sstevel@tonic-gate if (efi_write(cur_file, vtoc64) != 0) { 15510Sstevel@tonic-gate err_check(vtoc64); 15520Sstevel@tonic-gate err_print("Warning: error writing EFI.\n"); 15530Sstevel@tonic-gate return (-1); 15541524Slh195018 } else { 15551524Slh195018 cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 15560Sstevel@tonic-gate } 15570Sstevel@tonic-gate /* 15580Sstevel@tonic-gate * copy over the EFI vtoc onto the SMI vtoc and return 15590Sstevel@tonic-gate * okay. 15600Sstevel@tonic-gate */ 15611524Slh195018 dptr = auto_efi_sense(cur_file, &efinfo); 15621524Slh195018 if (dptr == NULL) { 15631524Slh195018 fmt_print("Autoconfiguration failed.\n"); 15641524Slh195018 return (-1); 15651524Slh195018 } 15661524Slh195018 15670Sstevel@tonic-gate cur_label = L_TYPE_EFI; 15680Sstevel@tonic-gate cur_disk->label_type = L_TYPE_EFI; 15691524Slh195018 cur_disk->disk_type = dptr; 15701524Slh195018 cur_disk->disk_parts = dptr->dtype_plist; 15711524Slh195018 cur_dtype = dptr; 15721524Slh195018 cur_parts = dptr->dtype_plist; 15731524Slh195018 cur_parts->etoc = vtoc64; 15741524Slh195018 1575362Sbg159949 ncyl = pcyl = nsect = psect = acyl = phead = 0; 15760Sstevel@tonic-gate 15771524Slh195018 /* 15781524Slh195018 * Get the Solais Fdisk Partition information. 15791524Slh195018 */ 15801524Slh195018 (void) copy_solaris_part(&cur_disk->fdisk_part); 15811524Slh195018 15820Sstevel@tonic-gate return (0); 15830Sstevel@tonic-gate } 15840Sstevel@tonic-gate } 15850Sstevel@tonic-gate 15860Sstevel@tonic-gate expert_end: 15870Sstevel@tonic-gate /* 15880Sstevel@tonic-gate * Make sure the user is serious. 15890Sstevel@tonic-gate */ 15900Sstevel@tonic-gate if (check("Ready to label disk, continue")) { 15910Sstevel@tonic-gate return (-1); 15920Sstevel@tonic-gate } 15930Sstevel@tonic-gate /* 15940Sstevel@tonic-gate * Write the labels out (this will also notify unix) and 15950Sstevel@tonic-gate * return status. 15960Sstevel@tonic-gate */ 15970Sstevel@tonic-gate fmt_print("\n"); 15980Sstevel@tonic-gate if (status = write_label()) 15990Sstevel@tonic-gate err_print("Label failed.\n"); 16000Sstevel@tonic-gate return (status); 16010Sstevel@tonic-gate } 16020Sstevel@tonic-gate 16030Sstevel@tonic-gate /* 16040Sstevel@tonic-gate * This routine implements the 'analyze' command. It simply runs 16050Sstevel@tonic-gate * the analyze menu. 16060Sstevel@tonic-gate */ 16070Sstevel@tonic-gate int 16080Sstevel@tonic-gate c_analyze() 16090Sstevel@tonic-gate { 16100Sstevel@tonic-gate 16110Sstevel@tonic-gate /* 16120Sstevel@tonic-gate * There must be a current disk type (and therefor a current disk). 16130Sstevel@tonic-gate */ 16140Sstevel@tonic-gate if (cur_dtype == NULL) { 16150Sstevel@tonic-gate err_print("Current Disk Type is not set.\n"); 16160Sstevel@tonic-gate return (-1); 16170Sstevel@tonic-gate } 16180Sstevel@tonic-gate cur_menu++; 16190Sstevel@tonic-gate last_menu = cur_menu; 16200Sstevel@tonic-gate 16210Sstevel@tonic-gate /* 16220Sstevel@tonic-gate * Run the menu. 16230Sstevel@tonic-gate */ 16240Sstevel@tonic-gate run_menu(menu_analyze, "ANALYZE", "analyze", 0); 16250Sstevel@tonic-gate cur_menu--; 16260Sstevel@tonic-gate return (0); 16270Sstevel@tonic-gate } 16280Sstevel@tonic-gate 16290Sstevel@tonic-gate /* 16300Sstevel@tonic-gate * This routine implements the 'defect' command. It simply runs 16310Sstevel@tonic-gate * the defect menu. 16320Sstevel@tonic-gate */ 16330Sstevel@tonic-gate int 16340Sstevel@tonic-gate c_defect() 16350Sstevel@tonic-gate { 16360Sstevel@tonic-gate int i; 16370Sstevel@tonic-gate 16380Sstevel@tonic-gate /* 16390Sstevel@tonic-gate * There must be a current disk type (and therefor a current disk). 16400Sstevel@tonic-gate */ 16410Sstevel@tonic-gate if (cur_dtype == NULL) { 16420Sstevel@tonic-gate err_print("Current Disk Type is not set.\n"); 16430Sstevel@tonic-gate return (-1); 16440Sstevel@tonic-gate } 16450Sstevel@tonic-gate 16460Sstevel@tonic-gate /* 16470Sstevel@tonic-gate * Check for the defect management and list management ops and 16480Sstevel@tonic-gate * display appropriate message. 16490Sstevel@tonic-gate */ 16500Sstevel@tonic-gate if ((cur_ops->op_ex_man == NULL) && (cur_ops->op_ex_cur == NULL) && 16510Sstevel@tonic-gate (cur_ops->op_create == NULL) && (cur_ops->op_wr_cur == NULL)) { 16520Sstevel@tonic-gate err_print("Controller does not support defect management\n"); 16530Sstevel@tonic-gate err_print("or disk supports automatic defect management.\n"); 16540Sstevel@tonic-gate return (-1); 16550Sstevel@tonic-gate } 16560Sstevel@tonic-gate cur_menu++; 16570Sstevel@tonic-gate last_menu = cur_menu; 16580Sstevel@tonic-gate 16590Sstevel@tonic-gate /* 16600Sstevel@tonic-gate * Lock out interrupt while we manipulate the defect lists. 16610Sstevel@tonic-gate */ 16620Sstevel@tonic-gate enter_critical(); 16630Sstevel@tonic-gate /* 16640Sstevel@tonic-gate * If the working list is null but there is a current list, 16650Sstevel@tonic-gate * update the working list to be a copy of the current list. 16660Sstevel@tonic-gate */ 16670Sstevel@tonic-gate if ((work_list.list == NULL) && (cur_list.list != NULL)) { 16680Sstevel@tonic-gate work_list.header = cur_list.header; 16690Sstevel@tonic-gate work_list.list = (struct defect_entry *)zalloc( 16700Sstevel@tonic-gate LISTSIZE(work_list.header.count) * SECSIZE); 16710Sstevel@tonic-gate for (i = 0; i < work_list.header.count; i++) 16720Sstevel@tonic-gate *(work_list.list + i) = *(cur_list.list + i); 16730Sstevel@tonic-gate work_list.flags = cur_list.flags & LIST_PGLIST; 16740Sstevel@tonic-gate } 16750Sstevel@tonic-gate exit_critical(); 16760Sstevel@tonic-gate /* 16770Sstevel@tonic-gate * Run the menu. 16780Sstevel@tonic-gate */ 16790Sstevel@tonic-gate run_menu(menu_defect, "DEFECT", "defect", 0); 16800Sstevel@tonic-gate cur_menu--; 16810Sstevel@tonic-gate 16820Sstevel@tonic-gate /* 16830Sstevel@tonic-gate * If the user has modified the working list but not committed 16840Sstevel@tonic-gate * it, warn him that he is probably making a mistake. 16850Sstevel@tonic-gate */ 16860Sstevel@tonic-gate if (work_list.flags & LIST_DIRTY) { 16870Sstevel@tonic-gate if (!EMBEDDED_SCSI) { 16880Sstevel@tonic-gate err_print( 16890Sstevel@tonic-gate "Warning: working defect list modified; but not committed.\n"); 16900Sstevel@tonic-gate if (!check( 16910Sstevel@tonic-gate "Do you wish to commit changes to current defect list")) 16920Sstevel@tonic-gate (void) do_commit(); 16930Sstevel@tonic-gate } 16940Sstevel@tonic-gate } 16950Sstevel@tonic-gate return (0); 16960Sstevel@tonic-gate } 16970Sstevel@tonic-gate 16980Sstevel@tonic-gate /* 16990Sstevel@tonic-gate * This routine implements the 'backup' command. It allows the user 17000Sstevel@tonic-gate * to search for backup labels on the current disk. This is useful 17010Sstevel@tonic-gate * if the primary label was lost and the user wishes to recover the 17020Sstevel@tonic-gate * partition information for the disk. The disk is relabeled and 17030Sstevel@tonic-gate * the current defect list is written out if a backup label is found. 17040Sstevel@tonic-gate */ 17050Sstevel@tonic-gate int 17060Sstevel@tonic-gate c_backup() 17070Sstevel@tonic-gate { 17080Sstevel@tonic-gate struct dk_label label; 17090Sstevel@tonic-gate struct disk_type *dtype; 17100Sstevel@tonic-gate struct partition_info *parts, *plist; 17117563SPrasad.Singamsetty@Sun.COM diskaddr_t bn; 17120Sstevel@tonic-gate int sec, head, i; 17130Sstevel@tonic-gate 17140Sstevel@tonic-gate /* 17150Sstevel@tonic-gate * There must be a current disk type (and therefore a current disk). 17160Sstevel@tonic-gate */ 17170Sstevel@tonic-gate if (cur_dtype == NULL) { 17180Sstevel@tonic-gate err_print("Current Disk Type is not set.\n"); 17190Sstevel@tonic-gate return (-1); 17200Sstevel@tonic-gate } 17210Sstevel@tonic-gate /* 17220Sstevel@tonic-gate * The disk must be formatted to read backup labels. 17230Sstevel@tonic-gate */ 17240Sstevel@tonic-gate if (!(cur_flags & DISK_FORMATTED)) { 17250Sstevel@tonic-gate err_print("Current Disk is unformatted.\n"); 17260Sstevel@tonic-gate return (-1); 17270Sstevel@tonic-gate } 17280Sstevel@tonic-gate /* 17290Sstevel@tonic-gate * Check for a valid fdisk table entry for Solaris 17300Sstevel@tonic-gate */ 17310Sstevel@tonic-gate if (!good_fdisk()) { 17320Sstevel@tonic-gate return (-1); 17330Sstevel@tonic-gate } 17340Sstevel@tonic-gate /* 17350Sstevel@tonic-gate * If we found a primary label on this disk, make sure 17360Sstevel@tonic-gate * the user is serious. 17370Sstevel@tonic-gate */ 17380Sstevel@tonic-gate if (cur_disk->label_type == L_TYPE_EFI) { 17390Sstevel@tonic-gate if (((cur_disk->disk_parts->etoc->efi_flags & 17400Sstevel@tonic-gate EFI_GPT_PRIMARY_CORRUPT) == 0) && 17410Sstevel@tonic-gate check("Disk has a primary label, still continue")) 17420Sstevel@tonic-gate return (-1); 17430Sstevel@tonic-gate fmt_print("Restoring primary label.\n"); 17440Sstevel@tonic-gate if (write_label()) { 17450Sstevel@tonic-gate err_print("Failed\n"); 17460Sstevel@tonic-gate return (-1); 17470Sstevel@tonic-gate } 17480Sstevel@tonic-gate return (0); 17490Sstevel@tonic-gate } else if (((cur_disk->disk_flags & (DSK_LABEL | DSK_LABEL_DIRTY)) == 17500Sstevel@tonic-gate DSK_LABEL) && 17510Sstevel@tonic-gate (check("Disk has a primary label, still continue"))) { 17520Sstevel@tonic-gate return (-1); 17530Sstevel@tonic-gate } 17540Sstevel@tonic-gate fmt_print("Searching for backup labels..."); 17550Sstevel@tonic-gate (void) fflush(stdout); 17560Sstevel@tonic-gate /* 17570Sstevel@tonic-gate * Some disks have the backup labels in a strange place. 17580Sstevel@tonic-gate */ 17590Sstevel@tonic-gate if (cur_ctype->ctype_flags & CF_BLABEL) 17600Sstevel@tonic-gate head = 2; 17610Sstevel@tonic-gate else 17620Sstevel@tonic-gate head = nhead - 1; 17630Sstevel@tonic-gate /* 17640Sstevel@tonic-gate * Loop through each copy of the backup label. 17650Sstevel@tonic-gate */ 17660Sstevel@tonic-gate for (sec = 1; ((sec < BAD_LISTCNT * 2 + 1) && (sec < nsect)); 17670Sstevel@tonic-gate sec += 2) { 17680Sstevel@tonic-gate bn = chs2bn(ncyl + acyl - 1, head, sec) + solaris_offset; 17690Sstevel@tonic-gate /* 17700Sstevel@tonic-gate * Attempt to read it. 17710Sstevel@tonic-gate */ 17727563SPrasad.Singamsetty@Sun.COM if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, 17730Sstevel@tonic-gate 1, (char *)&label, F_NORMAL, NULL)) { 17740Sstevel@tonic-gate continue; 17750Sstevel@tonic-gate } 17760Sstevel@tonic-gate /* 17770Sstevel@tonic-gate * Verify that it is a reasonable label. 17780Sstevel@tonic-gate */ 17790Sstevel@tonic-gate if (!checklabel(&label)) 17800Sstevel@tonic-gate continue; 17810Sstevel@tonic-gate if (trim_id(label.dkl_asciilabel)) 17820Sstevel@tonic-gate continue; 17830Sstevel@tonic-gate /* 17840Sstevel@tonic-gate * Lock out interrupts while we manipulate lists. 17850Sstevel@tonic-gate */ 17860Sstevel@tonic-gate enter_critical(); 17870Sstevel@tonic-gate fmt_print("found.\n"); 17880Sstevel@tonic-gate /* 17890Sstevel@tonic-gate * Find out which disk type the backup label claims. 17900Sstevel@tonic-gate */ 17910Sstevel@tonic-gate for (dtype = cur_ctype->ctype_dlist; dtype != NULL; 17920Sstevel@tonic-gate dtype = dtype->dtype_next) 17930Sstevel@tonic-gate if (dtype_match(&label, dtype)) 17940Sstevel@tonic-gate break; 17950Sstevel@tonic-gate /* 17960Sstevel@tonic-gate * If it disagrees with our current type, something 17970Sstevel@tonic-gate * real bad is happening. 17980Sstevel@tonic-gate */ 17990Sstevel@tonic-gate if (dtype != cur_dtype) { 18000Sstevel@tonic-gate if (dtype == NULL) { 18010Sstevel@tonic-gate fmt_print("\ 18020Sstevel@tonic-gate Unknown disk type in backup label\n"); 18030Sstevel@tonic-gate exit_critical(); 18040Sstevel@tonic-gate return (-1); 18050Sstevel@tonic-gate } 18060Sstevel@tonic-gate fmt_print("Backup label claims different type:\n"); 18070Sstevel@tonic-gate fmt_print(" <%s cyl %d alt %d hd %d sec %d>\n", 18080Sstevel@tonic-gate label.dkl_asciilabel, label.dkl_ncyl, 18090Sstevel@tonic-gate label.dkl_acyl, label.dkl_nhead, 18100Sstevel@tonic-gate label.dkl_nsect); 18110Sstevel@tonic-gate if (check("Continue")) { 18120Sstevel@tonic-gate exit_critical(); 18130Sstevel@tonic-gate return (-1); 18140Sstevel@tonic-gate } 18150Sstevel@tonic-gate cur_dtype = dtype; 18160Sstevel@tonic-gate } 18170Sstevel@tonic-gate /* 18180Sstevel@tonic-gate * Try to match the partition map with a known map. 18190Sstevel@tonic-gate */ 18200Sstevel@tonic-gate for (parts = dtype->dtype_plist; parts != NULL; 18210Sstevel@tonic-gate parts = parts->pinfo_next) 18220Sstevel@tonic-gate if (parts_match(&label, parts)) 18230Sstevel@tonic-gate break; 18240Sstevel@tonic-gate /* 18250Sstevel@tonic-gate * If we couldn't match it, allocate space for a new one, 18260Sstevel@tonic-gate * fill in the info, and add it to the list. The name 18270Sstevel@tonic-gate * for the new map is derived from the disk name. 18280Sstevel@tonic-gate */ 18290Sstevel@tonic-gate if (parts == NULL) { 18300Sstevel@tonic-gate parts = (struct partition_info *) 18310Sstevel@tonic-gate zalloc(sizeof (struct partition_info)); 18320Sstevel@tonic-gate plist = dtype->dtype_plist; 18330Sstevel@tonic-gate if (plist == NULL) 18340Sstevel@tonic-gate dtype->dtype_plist = parts; 18350Sstevel@tonic-gate else { 18360Sstevel@tonic-gate while (plist->pinfo_next != NULL) 18370Sstevel@tonic-gate plist = plist->pinfo_next; 18380Sstevel@tonic-gate plist->pinfo_next = parts; 18390Sstevel@tonic-gate } 18400Sstevel@tonic-gate parts->pinfo_name = alloc_string("original"); 18410Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) 18420Sstevel@tonic-gate 18430Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 18440Sstevel@tonic-gate parts->pinfo_map[i] = label.dkl_map[i]; 18450Sstevel@tonic-gate 18460Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16) 18470Sstevel@tonic-gate parts->pinfo_map[i].dkl_cylno = 18480Sstevel@tonic-gate label.dkl_vtoc.v_part[i].p_start / spc(); 18490Sstevel@tonic-gate parts->pinfo_map[i].dkl_nblk = 18500Sstevel@tonic-gate label.dkl_vtoc.v_part[i].p_size; 18510Sstevel@tonic-gate #else 18520Sstevel@tonic-gate #error No VTOC layout defined. 18530Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 18540Sstevel@tonic-gate parts->vtoc = label.dkl_vtoc; 18550Sstevel@tonic-gate } 18560Sstevel@tonic-gate /* 18570Sstevel@tonic-gate * We now have a partition map. Make it the current map. 18580Sstevel@tonic-gate */ 18590Sstevel@tonic-gate cur_disk->disk_parts = cur_parts = parts; 18600Sstevel@tonic-gate exit_critical(); 18610Sstevel@tonic-gate /* 18620Sstevel@tonic-gate * Rewrite the labels and defect lists, as appropriate. 18630Sstevel@tonic-gate */ 18640Sstevel@tonic-gate if (EMBEDDED_SCSI) { 18650Sstevel@tonic-gate fmt_print("Restoring primary label.\n"); 18660Sstevel@tonic-gate if (write_label()) 18670Sstevel@tonic-gate return (-1); 18680Sstevel@tonic-gate } else { 18690Sstevel@tonic-gate fmt_print("Restoring primary label and defect list.\n"); 18700Sstevel@tonic-gate if (write_label()) 18710Sstevel@tonic-gate return (-1); 18720Sstevel@tonic-gate if (cur_list.list != NULL) 18730Sstevel@tonic-gate write_deflist(&cur_list); 18740Sstevel@tonic-gate } 18750Sstevel@tonic-gate fmt_print("\n"); 18760Sstevel@tonic-gate return (0); 18770Sstevel@tonic-gate } 18780Sstevel@tonic-gate /* 18790Sstevel@tonic-gate * If we didn't find any backup labels, say so. 18800Sstevel@tonic-gate */ 18810Sstevel@tonic-gate fmt_print("not found.\n\n"); 18820Sstevel@tonic-gate return (0); 18830Sstevel@tonic-gate } 18840Sstevel@tonic-gate 18850Sstevel@tonic-gate /* 18860Sstevel@tonic-gate * This routine is called by c_verify() for an EFI labeled disk 18870Sstevel@tonic-gate */ 18880Sstevel@tonic-gate static int 18890Sstevel@tonic-gate c_verify_efi() 18900Sstevel@tonic-gate { 18910Sstevel@tonic-gate struct efi_info efi_info; 18920Sstevel@tonic-gate struct partition_info tmp_pinfo; 18930Sstevel@tonic-gate int status; 18940Sstevel@tonic-gate 18950Sstevel@tonic-gate status = read_efi_label(cur_file, &efi_info); 18960Sstevel@tonic-gate if (status != 0) { 18970Sstevel@tonic-gate err_print("Warning: Could not read label.\n"); 18980Sstevel@tonic-gate return (-1); 18990Sstevel@tonic-gate } 19000Sstevel@tonic-gate if (cur_parts->etoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) { 19010Sstevel@tonic-gate err_print("Reading the primary EFI GPT label "); 19020Sstevel@tonic-gate err_print("failed. Using backup label.\n"); 19030Sstevel@tonic-gate err_print("Use the 'backup' command to restore "); 19040Sstevel@tonic-gate err_print("the primary label.\n"); 19050Sstevel@tonic-gate } 19060Sstevel@tonic-gate tmp_pinfo.etoc = efi_info.e_parts; 19070Sstevel@tonic-gate fmt_print("\n"); 19080Sstevel@tonic-gate if (cur_parts->etoc->efi_parts[8].p_name) { 19090Sstevel@tonic-gate fmt_print("Volume name = <%8s>\n", 19100Sstevel@tonic-gate cur_parts->etoc->efi_parts[8].p_name); 19110Sstevel@tonic-gate } else { 19120Sstevel@tonic-gate fmt_print("Volume name = < >\n"); 19130Sstevel@tonic-gate } 19140Sstevel@tonic-gate fmt_print("ascii name = "); 19150Sstevel@tonic-gate print_efi_string(efi_info.vendor, efi_info.product, 19160Sstevel@tonic-gate efi_info.revision, efi_info.capacity); 19170Sstevel@tonic-gate fmt_print("\n"); 19180Sstevel@tonic-gate 19190Sstevel@tonic-gate fmt_print("bytes/sector = %d\n", DEV_BSIZE); 19200Sstevel@tonic-gate fmt_print("sectors = %llu\n", cur_parts->etoc->efi_last_lba); 19210Sstevel@tonic-gate fmt_print("accessible sectors = %llu\n", 19220Sstevel@tonic-gate cur_parts->etoc->efi_last_u_lba); 19230Sstevel@tonic-gate 19240Sstevel@tonic-gate print_map(&tmp_pinfo); 19250Sstevel@tonic-gate return (0); 19260Sstevel@tonic-gate } 19270Sstevel@tonic-gate 19280Sstevel@tonic-gate /* 19290Sstevel@tonic-gate * This routine implements the 'verify' command. It allows the user 19300Sstevel@tonic-gate * to read the labels on the current disk. 19310Sstevel@tonic-gate */ 19320Sstevel@tonic-gate int 19330Sstevel@tonic-gate c_verify() 19340Sstevel@tonic-gate { 19350Sstevel@tonic-gate struct dk_label p_label, b_label, *label; 19360Sstevel@tonic-gate struct partition_info tmp_pinfo; 19377563SPrasad.Singamsetty@Sun.COM diskaddr_t bn; 19380Sstevel@tonic-gate int sec, head, i, status; 19390Sstevel@tonic-gate int p_label_bad = 0; 19400Sstevel@tonic-gate int b_label_bad = 0; 19410Sstevel@tonic-gate int p_label_found = 0; 19420Sstevel@tonic-gate int b_label_found = 0; 19430Sstevel@tonic-gate char id_str[128]; 19440Sstevel@tonic-gate 19450Sstevel@tonic-gate /* 19460Sstevel@tonic-gate * There must be a current disk type (and therefore a current disk). 19470Sstevel@tonic-gate */ 19480Sstevel@tonic-gate if (cur_dtype == NULL) { 19490Sstevel@tonic-gate err_print("Current Disk Type is not set.\n"); 19500Sstevel@tonic-gate return (-1); 19510Sstevel@tonic-gate } 19520Sstevel@tonic-gate /* 19530Sstevel@tonic-gate * The disk must be formatted to read labels. 19540Sstevel@tonic-gate */ 19550Sstevel@tonic-gate if (!(cur_flags & DISK_FORMATTED)) { 19560Sstevel@tonic-gate err_print("Current Disk is unformatted.\n"); 19570Sstevel@tonic-gate return (-1); 19580Sstevel@tonic-gate } 19590Sstevel@tonic-gate /* 19600Sstevel@tonic-gate * Check for a valid fdisk table entry for Solaris 19610Sstevel@tonic-gate */ 19620Sstevel@tonic-gate if (!good_fdisk()) { 19630Sstevel@tonic-gate return (-1); 19640Sstevel@tonic-gate } 19650Sstevel@tonic-gate /* 19660Sstevel@tonic-gate * Branch off here if the disk is EFI labelled. 19670Sstevel@tonic-gate */ 19680Sstevel@tonic-gate if (cur_label == L_TYPE_EFI) { 19690Sstevel@tonic-gate return (c_verify_efi()); 19700Sstevel@tonic-gate } 19710Sstevel@tonic-gate /* 19720Sstevel@tonic-gate * Attempt to read the primary label. 19730Sstevel@tonic-gate */ 19740Sstevel@tonic-gate status = read_label(cur_file, &p_label); 19750Sstevel@tonic-gate if (status == -1) { 19760Sstevel@tonic-gate err_print("Warning: Could not read primary label.\n"); 19770Sstevel@tonic-gate p_label_bad = 1; 19780Sstevel@tonic-gate } else { 19790Sstevel@tonic-gate /* 19800Sstevel@tonic-gate * Verify that it is a reasonable label. 19810Sstevel@tonic-gate */ 19820Sstevel@tonic-gate /* 19830Sstevel@tonic-gate * Save complete ascii string for printing later. 19840Sstevel@tonic-gate */ 19850Sstevel@tonic-gate (void) strncpy(id_str, p_label.dkl_asciilabel, 128); 19860Sstevel@tonic-gate 19870Sstevel@tonic-gate if ((!checklabel((struct dk_label *)&p_label)) || 19880Sstevel@tonic-gate (trim_id(p_label.dkl_asciilabel))) { 19890Sstevel@tonic-gate err_print("\ 19900Sstevel@tonic-gate Warning: Primary label appears to be corrupt.\n"); 19910Sstevel@tonic-gate p_label_bad = 1; 19920Sstevel@tonic-gate } else { 19930Sstevel@tonic-gate p_label_found = 1; 19940Sstevel@tonic-gate /* 19950Sstevel@tonic-gate * Make sure it matches current label 19960Sstevel@tonic-gate */ 19970Sstevel@tonic-gate if ((!dtype_match(&p_label, cur_dtype)) || 19980Sstevel@tonic-gate (!parts_match(&p_label, cur_parts))) { 19990Sstevel@tonic-gate err_print("\ 20000Sstevel@tonic-gate Warning: Primary label on disk appears to be different from\ncurrent label.\n"); 20010Sstevel@tonic-gate p_label_bad = 1; 20020Sstevel@tonic-gate } 20030Sstevel@tonic-gate } 20040Sstevel@tonic-gate } 20050Sstevel@tonic-gate 20060Sstevel@tonic-gate /* 20070Sstevel@tonic-gate * Read backup labels. 20080Sstevel@tonic-gate * Some disks have the backup labels in a strange place. 20090Sstevel@tonic-gate */ 20100Sstevel@tonic-gate if (cur_ctype->ctype_flags & CF_BLABEL) 20110Sstevel@tonic-gate head = 2; 20120Sstevel@tonic-gate else 20130Sstevel@tonic-gate head = nhead - 1; 20140Sstevel@tonic-gate /* 20150Sstevel@tonic-gate * Loop through each copy of the backup label. 20160Sstevel@tonic-gate */ 20170Sstevel@tonic-gate for (sec = 1; ((sec < BAD_LISTCNT * 2 + 1) && (sec < nsect)); 20180Sstevel@tonic-gate sec += 2) { 20190Sstevel@tonic-gate bn = chs2bn(ncyl + acyl - 1, head, sec) + solaris_offset; 20200Sstevel@tonic-gate /* 20210Sstevel@tonic-gate * Attempt to read it. 20220Sstevel@tonic-gate */ 20237563SPrasad.Singamsetty@Sun.COM if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, 20240Sstevel@tonic-gate 1, (char *)&b_label, F_NORMAL, NULL)) 20250Sstevel@tonic-gate continue; 20260Sstevel@tonic-gate /* 20270Sstevel@tonic-gate * Verify that it is a reasonable label. 20280Sstevel@tonic-gate */ 20290Sstevel@tonic-gate if (!checklabel(&b_label)) 20300Sstevel@tonic-gate continue; 20310Sstevel@tonic-gate 20320Sstevel@tonic-gate /* 20330Sstevel@tonic-gate * Save complete label only if no primary label exists 20340Sstevel@tonic-gate */ 20350Sstevel@tonic-gate if (!p_label_found) 20360Sstevel@tonic-gate (void) strncpy(id_str, b_label.dkl_asciilabel, 128); 20370Sstevel@tonic-gate 20380Sstevel@tonic-gate if (trim_id(b_label.dkl_asciilabel)) 20390Sstevel@tonic-gate continue; 20400Sstevel@tonic-gate b_label_found = 1; 20410Sstevel@tonic-gate /* 20420Sstevel@tonic-gate * Compare against primary label 20430Sstevel@tonic-gate */ 20440Sstevel@tonic-gate if (p_label_found) { 20450Sstevel@tonic-gate if ((strcmp(b_label.dkl_asciilabel, 20460Sstevel@tonic-gate p_label.dkl_asciilabel) != 0) || 20470Sstevel@tonic-gate (b_label.dkl_ncyl != p_label.dkl_ncyl) || 20480Sstevel@tonic-gate (b_label.dkl_acyl != p_label.dkl_acyl) || 20490Sstevel@tonic-gate (b_label.dkl_nhead != p_label.dkl_nhead) || 20500Sstevel@tonic-gate (b_label.dkl_nsect != p_label.dkl_nsect)) { 20510Sstevel@tonic-gate b_label_bad = 1; 20520Sstevel@tonic-gate } else { 20530Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 20540Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 20550Sstevel@tonic-gate if ((b_label.dkl_map[i].dkl_cylno != 20560Sstevel@tonic-gate p_label.dkl_map[i].dkl_cylno) || 20570Sstevel@tonic-gate (b_label.dkl_map[i].dkl_nblk != 20580Sstevel@tonic-gate p_label.dkl_map[i].dkl_nblk)) { 20590Sstevel@tonic-gate b_label_bad = 1; 20600Sstevel@tonic-gate break; 20610Sstevel@tonic-gate } 20620Sstevel@tonic-gate 20630Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16) 20640Sstevel@tonic-gate if ((b_label.dkl_vtoc.v_part[i].p_tag != 20650Sstevel@tonic-gate p_label.dkl_vtoc.v_part[i].p_tag) || 20660Sstevel@tonic-gate (b_label.dkl_vtoc.v_part[i].p_flag != 20670Sstevel@tonic-gate p_label.dkl_vtoc.v_part[i].p_flag) || 20680Sstevel@tonic-gate (b_label.dkl_vtoc.v_part[i].p_start != 20690Sstevel@tonic-gate p_label.dkl_vtoc.v_part[i].p_start) || 20700Sstevel@tonic-gate (b_label.dkl_vtoc.v_part[i].p_size != 20710Sstevel@tonic-gate p_label.dkl_vtoc.v_part[i].p_size)) { 20720Sstevel@tonic-gate b_label_bad = 1; 20730Sstevel@tonic-gate break; 20740Sstevel@tonic-gate } 20750Sstevel@tonic-gate #else 20760Sstevel@tonic-gate #error No VTOC layout defined. 20770Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 20780Sstevel@tonic-gate } 20790Sstevel@tonic-gate } 20800Sstevel@tonic-gate } 20810Sstevel@tonic-gate if (b_label_bad) 20820Sstevel@tonic-gate err_print( 20830Sstevel@tonic-gate "Warning: Primary and backup labels do not match.\n"); 20840Sstevel@tonic-gate break; 20850Sstevel@tonic-gate } 20860Sstevel@tonic-gate /* 20870Sstevel@tonic-gate * If we didn't find any backup labels, say so. 20880Sstevel@tonic-gate */ 20890Sstevel@tonic-gate if (!b_label_found) 20900Sstevel@tonic-gate err_print("Warning: Could not read backup labels.\n"); 20910Sstevel@tonic-gate 20920Sstevel@tonic-gate if ((!b_label_found) || (p_label_bad) || (b_label_bad)) 20930Sstevel@tonic-gate err_print("\n\ 20940Sstevel@tonic-gate Warning: Check the current partitioning and 'label' the disk or use the\n\ 20950Sstevel@tonic-gate \t 'backup' command.\n"); 20960Sstevel@tonic-gate 20970Sstevel@tonic-gate /* 20980Sstevel@tonic-gate * Print label information. 20990Sstevel@tonic-gate */ 21000Sstevel@tonic-gate if (p_label_found) { 21010Sstevel@tonic-gate fmt_print("\nPrimary label contents:\n"); 21020Sstevel@tonic-gate label = &p_label; 21030Sstevel@tonic-gate } else if (b_label_found) { 21040Sstevel@tonic-gate fmt_print("\nBackup label contents:\n"); 21050Sstevel@tonic-gate label = &b_label; 21060Sstevel@tonic-gate } else { 21070Sstevel@tonic-gate return (0); 21080Sstevel@tonic-gate } 21090Sstevel@tonic-gate 21100Sstevel@tonic-gate /* 21110Sstevel@tonic-gate * Must put info into partition_info struct for 21120Sstevel@tonic-gate * for print routine. 21130Sstevel@tonic-gate */ 21140Sstevel@tonic-gate bzero(&tmp_pinfo, sizeof (struct partition_info)); 21150Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 21160Sstevel@tonic-gate 21170Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 21180Sstevel@tonic-gate tmp_pinfo.pinfo_map[i] = label->dkl_map[i]; 21190Sstevel@tonic-gate 21200Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16) 21210Sstevel@tonic-gate tmp_pinfo.pinfo_map[i].dkl_cylno = 21220Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_start / spc(); 21230Sstevel@tonic-gate tmp_pinfo.pinfo_map[i].dkl_nblk = 21240Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_size; 21250Sstevel@tonic-gate #else 21260Sstevel@tonic-gate #error No VTOC layout defined. 21270Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 21280Sstevel@tonic-gate } 21290Sstevel@tonic-gate tmp_pinfo.vtoc = label->dkl_vtoc; 21300Sstevel@tonic-gate 21310Sstevel@tonic-gate fmt_print("\n"); 21320Sstevel@tonic-gate fmt_print("Volume name = <%8s>\n", label->dkl_vtoc.v_volume); 21330Sstevel@tonic-gate fmt_print("ascii name = <%s>\n", id_str); 21340Sstevel@tonic-gate fmt_print("pcyl = %4d\n", label->dkl_pcyl); 21350Sstevel@tonic-gate fmt_print("ncyl = %4d\n", label->dkl_ncyl); 21360Sstevel@tonic-gate fmt_print("acyl = %4d\n", label->dkl_acyl); 21370Sstevel@tonic-gate 21380Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16) 21390Sstevel@tonic-gate fmt_print("bcyl = %4d\n", label->dkl_bcyl); 21400Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_16) */ 21410Sstevel@tonic-gate 21420Sstevel@tonic-gate fmt_print("nhead = %4d\n", label->dkl_nhead); 21430Sstevel@tonic-gate fmt_print("nsect = %4d\n", label->dkl_nsect); 21440Sstevel@tonic-gate 21450Sstevel@tonic-gate print_map(&tmp_pinfo); 21460Sstevel@tonic-gate return (0); 21470Sstevel@tonic-gate } 21480Sstevel@tonic-gate 21490Sstevel@tonic-gate 21500Sstevel@tonic-gate /* 21510Sstevel@tonic-gate * This command implements the inquiry command, for embedded SCSI 21520Sstevel@tonic-gate * disks only, which issues a SCSI inquiry command, and 21530Sstevel@tonic-gate * displays the resulting vendor, product id and revision level. 21540Sstevel@tonic-gate */ 21550Sstevel@tonic-gate int 21560Sstevel@tonic-gate c_inquiry() 21570Sstevel@tonic-gate { 21580Sstevel@tonic-gate char inqbuf[255]; 21590Sstevel@tonic-gate struct scsi_inquiry *inq; 21600Sstevel@tonic-gate 21610Sstevel@tonic-gate assert(SCSI); 21620Sstevel@tonic-gate 21630Sstevel@tonic-gate inq = (struct scsi_inquiry *)inqbuf; 21640Sstevel@tonic-gate 21650Sstevel@tonic-gate if (uscsi_inquiry(cur_file, inqbuf, sizeof (inqbuf))) { 21660Sstevel@tonic-gate err_print("Failed\n"); 21670Sstevel@tonic-gate return (-1); 21680Sstevel@tonic-gate } else { 21690Sstevel@tonic-gate fmt_print("Vendor: "); 21700Sstevel@tonic-gate print_buf(inq->inq_vid, sizeof (inq->inq_vid)); 21710Sstevel@tonic-gate fmt_print("\nProduct: "); 21720Sstevel@tonic-gate print_buf(inq->inq_pid, sizeof (inq->inq_pid)); 21730Sstevel@tonic-gate fmt_print("\nRevision: "); 21740Sstevel@tonic-gate print_buf(inq->inq_revision, sizeof (inq->inq_revision)); 21750Sstevel@tonic-gate fmt_print("\n"); 21760Sstevel@tonic-gate } 21770Sstevel@tonic-gate 21780Sstevel@tonic-gate return (0); 21790Sstevel@tonic-gate } 21800Sstevel@tonic-gate 21810Sstevel@tonic-gate 21820Sstevel@tonic-gate /* 21830Sstevel@tonic-gate * This routine allows the user to set the 8-character 21840Sstevel@tonic-gate * volume name in the vtoc. It then writes both the 21850Sstevel@tonic-gate * primary and backup labels onto the current disk. 21860Sstevel@tonic-gate */ 21870Sstevel@tonic-gate int 21880Sstevel@tonic-gate c_volname() 21890Sstevel@tonic-gate { 21900Sstevel@tonic-gate int status; 21910Sstevel@tonic-gate char *prompt; 21920Sstevel@tonic-gate union { 21930Sstevel@tonic-gate int xfoo; 21940Sstevel@tonic-gate char defvolname[LEN_DKL_VVOL+1]; 21950Sstevel@tonic-gate } x; 21960Sstevel@tonic-gate char s1[MAXPATHLEN], nclean[MAXPATHLEN]; 21970Sstevel@tonic-gate char *volname; 21980Sstevel@tonic-gate 21990Sstevel@tonic-gate 22000Sstevel@tonic-gate /* 22010Sstevel@tonic-gate * There must be a current disk type (and therefore a current disk). 22020Sstevel@tonic-gate */ 22030Sstevel@tonic-gate if (cur_dtype == NULL) { 22040Sstevel@tonic-gate err_print("Current Disk Type is not set.\n"); 22050Sstevel@tonic-gate return (-1); 22060Sstevel@tonic-gate } 22070Sstevel@tonic-gate /* 22080Sstevel@tonic-gate * The current disk must be formatted to label it. 22090Sstevel@tonic-gate */ 22100Sstevel@tonic-gate if (!(cur_flags & DISK_FORMATTED)) { 22110Sstevel@tonic-gate err_print("Current Disk is unformatted.\n"); 22120Sstevel@tonic-gate return (-1); 22130Sstevel@tonic-gate } 22140Sstevel@tonic-gate /* 22150Sstevel@tonic-gate * Check for a valid fdisk table entry for Solaris 22160Sstevel@tonic-gate */ 22170Sstevel@tonic-gate if (!good_fdisk()) { 22180Sstevel@tonic-gate return (-1); 22190Sstevel@tonic-gate } 22200Sstevel@tonic-gate /* 22210Sstevel@tonic-gate * The current disk must be formatted to label it. 22220Sstevel@tonic-gate */ 22230Sstevel@tonic-gate if (cur_parts == NULL) { 22240Sstevel@tonic-gate err_print( 22250Sstevel@tonic-gate "Please select a partition map for the disk first.\n"); 22260Sstevel@tonic-gate return (-1); 22270Sstevel@tonic-gate } 22285421Smishra 22290Sstevel@tonic-gate /* 22300Sstevel@tonic-gate * Check to see if there are any mounted file systems anywhere 22310Sstevel@tonic-gate * on the current disk. If so, refuse to label the disk, but 22320Sstevel@tonic-gate * only if the partitions would change for the mounted partitions. 22330Sstevel@tonic-gate * 22340Sstevel@tonic-gate */ 22357563SPrasad.Singamsetty@Sun.COM if (checkmount((diskaddr_t)-1, (diskaddr_t)-1)) { 22360Sstevel@tonic-gate /* Bleagh, too descriptive */ 22370Sstevel@tonic-gate if (check_label_with_mount()) { 22380Sstevel@tonic-gate err_print( 22390Sstevel@tonic-gate "Cannot label disk while it has mounted partitions.\n\n"); 22400Sstevel@tonic-gate return (-1); 22410Sstevel@tonic-gate } 22420Sstevel@tonic-gate } 22435421Smishra 22440Sstevel@tonic-gate /* 22450Sstevel@tonic-gate * Check to see if there are partitions being used for swapping 22460Sstevel@tonic-gate * on the current disk. If so, refuse to label the disk, but 22470Sstevel@tonic-gate * only if the partitions would change for the swap partitions. 22480Sstevel@tonic-gate * 22490Sstevel@tonic-gate */ 22507563SPrasad.Singamsetty@Sun.COM if (checkswap((diskaddr_t)-1, (diskaddr_t)-1)) { 22510Sstevel@tonic-gate /* Bleagh, too descriptive */ 22520Sstevel@tonic-gate if (check_label_with_swap()) { 22530Sstevel@tonic-gate err_print( 22540Sstevel@tonic-gate "Cannot label disk while its partitions are currently \ 22550Sstevel@tonic-gate being used for swapping.\n\n"); 22560Sstevel@tonic-gate return (-1); 22570Sstevel@tonic-gate } 22580Sstevel@tonic-gate } 22595421Smishra 22605421Smishra /* 22615421Smishra * Check to see if any partitions used for svm, vxvm, ZFS zpool 22625421Smishra * or live upgrade are on the disk. If so, refuse to label the 22635421Smishra * disk, but only if we are trying to shrink a partition in 22645421Smishra * use. 22655421Smishra */ 22665421Smishra if (checkdevinuse(cur_disk->disk_name, (diskaddr_t)-1, 22675421Smishra (diskaddr_t)-1, 0, 1)) { 22685421Smishra err_print("Cannot label disk while its partitions " 22695421Smishra "are in use as described.\n"); 22705421Smishra return (-1); 22715421Smishra } 22725421Smishra 22730Sstevel@tonic-gate /* 22740Sstevel@tonic-gate * Prompt for the disk volume name. 22750Sstevel@tonic-gate */ 22760Sstevel@tonic-gate prompt = "Enter 8-character volume name (remember quotes)"; 22770Sstevel@tonic-gate bzero(x.defvolname, LEN_DKL_VVOL+1); 22780Sstevel@tonic-gate bcopy(cur_disk->v_volume, x.defvolname, LEN_DKL_VVOL); 22790Sstevel@tonic-gate /* 22800Sstevel@tonic-gate * Get the input using "get_inputline" since 22810Sstevel@tonic-gate * input would never return null string. 22820Sstevel@tonic-gate */ 22830Sstevel@tonic-gate fmt_print("%s[\"%s\"]:", prompt, x.defvolname); 22840Sstevel@tonic-gate 22850Sstevel@tonic-gate /* 22860Sstevel@tonic-gate * Get input from the user. 22870Sstevel@tonic-gate */ 22880Sstevel@tonic-gate get_inputline(nclean, MAXPATHLEN); 22890Sstevel@tonic-gate clean_token(s1, nclean); 22900Sstevel@tonic-gate /* 22910Sstevel@tonic-gate * check for return. 22920Sstevel@tonic-gate */ 22930Sstevel@tonic-gate if (s1[0] == 0) { 22940Sstevel@tonic-gate volname = x.defvolname; 22950Sstevel@tonic-gate } else { 22960Sstevel@tonic-gate /* 22970Sstevel@tonic-gate * remove the " mark from volname. 22980Sstevel@tonic-gate */ 22990Sstevel@tonic-gate if (s1[0] == '"') { 23000Sstevel@tonic-gate int i = 1; 23010Sstevel@tonic-gate volname = &s1[1]; 23020Sstevel@tonic-gate while (s1[i] != '"' && s1[i] != '\0') 23030Sstevel@tonic-gate i++; 23040Sstevel@tonic-gate s1[i] = '\0'; 23050Sstevel@tonic-gate clean_token(nclean, volname); 23060Sstevel@tonic-gate volname = nclean; 23070Sstevel@tonic-gate } else { 23080Sstevel@tonic-gate (void) sscanf(&s1[0], "%1024s", nclean); 23090Sstevel@tonic-gate volname = nclean; 23100Sstevel@tonic-gate }; 23110Sstevel@tonic-gate } 23120Sstevel@tonic-gate /* 23130Sstevel@tonic-gate * Make sure the user is serious. 23140Sstevel@tonic-gate */ 23150Sstevel@tonic-gate if (check("Ready to label disk, continue")) { 23160Sstevel@tonic-gate fmt_print("\n"); 23170Sstevel@tonic-gate return (-1); 23180Sstevel@tonic-gate } 23190Sstevel@tonic-gate /* 23200Sstevel@tonic-gate * Use the volume name chosen above 23210Sstevel@tonic-gate */ 23220Sstevel@tonic-gate bzero(cur_disk->v_volume, LEN_DKL_VVOL); 23230Sstevel@tonic-gate bcopy(volname, cur_disk->v_volume, min((int)strlen(volname), 23240Sstevel@tonic-gate LEN_DKL_VVOL)); 23250Sstevel@tonic-gate if (cur_label == L_TYPE_EFI) { 23260Sstevel@tonic-gate bzero(cur_parts->etoc->efi_parts[8].p_name, LEN_DKL_VVOL); 23270Sstevel@tonic-gate bcopy(volname, cur_parts->etoc->efi_parts[8].p_name, 23280Sstevel@tonic-gate LEN_DKL_VVOL); 23290Sstevel@tonic-gate } 23300Sstevel@tonic-gate /* 23310Sstevel@tonic-gate * Write the labels out (this will also notify unix) and 23320Sstevel@tonic-gate * return status. 23330Sstevel@tonic-gate */ 23340Sstevel@tonic-gate fmt_print("\n"); 23350Sstevel@tonic-gate if (status = write_label()) 23360Sstevel@tonic-gate err_print("Label failed.\n"); 23370Sstevel@tonic-gate return (status); 23380Sstevel@tonic-gate } 2339