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