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) 2011 Gary Mills 23 * 24 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 27 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> 28 */ 29 30 /* 31 * This file contains functions to implement automatic configuration 32 * of scsi disks. 33 */ 34 #include "global.h" 35 36 #include <fcntl.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <strings.h> 40 #include <stdlib.h> 41 #include <ctype.h> 42 43 #include "misc.h" 44 #include "param.h" 45 #include "ctlr_scsi.h" 46 #include "auto_sense.h" 47 #include "partition.h" 48 #include "label.h" 49 #include "startup.h" 50 #include "analyze.h" 51 #include "io.h" 52 #include "hardware_structs.h" 53 #include "menu_fdisk.h" 54 55 56 #define DISK_NAME_MAX 256 57 58 extern int nctypes; 59 extern struct ctlr_type ctlr_types[]; 60 61 62 /* 63 * Marker for free hog partition 64 */ 65 #define HOG (-1) 66 67 68 69 /* 70 * Default partition tables 71 * 72 * Disk capacity root swap usr 73 * ------------- ---- ---- --- 74 * 0mb to 64mb 0 0 remainder 75 * 64mb to 180mb 16mb 16mb remainder 76 * 180mb to 280mb 16mb 32mb remainder 77 * 280mb to 380mb 24mb 32mb remainder 78 * 380mb to 600mb 32mb 32mb remainder 79 * 600mb to 1gb 32mb 64mb remainder 80 * 1gb to 2gb 64mb 128mb remainder 81 * 2gb on up 128mb 128mb remainder 82 */ 83 struct part_table { 84 int partitions[NDKMAP]; 85 }; 86 87 static struct part_table part_table_64mb = { 88 { 0, 0, 0, 0, 0, 0, HOG, 0} 89 }; 90 91 static struct part_table part_table_180mb = { 92 { 16, 16, 0, 0, 0, 0, HOG, 0} 93 }; 94 95 static struct part_table part_table_280mb = { 96 { 16, 32, 0, 0, 0, 0, HOG, 0} 97 }; 98 99 static struct part_table part_table_380mb = { 100 { 24, 32, 0, 0, 0, 0, HOG, 0} 101 }; 102 103 static struct part_table part_table_600mb = { 104 { 32, 32, 0, 0, 0, 0, HOG, 0} 105 }; 106 107 static struct part_table part_table_1gb = { 108 { 32, 64, 0, 0, 0, 0, HOG, 0} 109 }; 110 111 static struct part_table part_table_2gb = { 112 { 64, 128, 0, 0, 0, 0, HOG, 0} 113 }; 114 115 static struct part_table part_table_infinity = { 116 { 128, 128, 0, 0, 0, 0, HOG, 0} 117 }; 118 119 120 static struct default_partitions { 121 diskaddr_t min_capacity; 122 diskaddr_t max_capacity; 123 struct part_table *part_table; 124 } default_partitions[] = { 125 { 0, 64, &part_table_64mb }, /* 0 to 64 mb */ 126 { 64, 180, &part_table_180mb }, /* 64 to 180 mb */ 127 { 180, 280, &part_table_280mb }, /* 180 to 280 mb */ 128 { 280, 380, &part_table_380mb }, /* 280 to 380 mb */ 129 { 380, 600, &part_table_600mb }, /* 380 to 600 mb */ 130 { 600, 1024, &part_table_1gb }, /* 600 to 1 gb */ 131 { 1024, 2048, &part_table_2gb }, /* 1 to 2 gb */ 132 { 2048, INFINITY, &part_table_infinity }, /* 2 gb on up */ 133 }; 134 135 #define DEFAULT_PARTITION_TABLE_SIZE \ 136 (sizeof (default_partitions) / sizeof (struct default_partitions)) 137 138 /* 139 * msgs for check() 140 */ 141 #define FORMAT_MSG "Auto configuration via format.dat" 142 #define GENERIC_MSG "Auto configuration via generic SCSI-2" 143 144 /* 145 * Disks on symbios(Hardwire raid controller) return a fixed number 146 * of heads(64)/cylinders(64) and adjust the cylinders depending 147 * capacity of the configured lun. 148 * In such a case we get number of physical cylinders < 3 which 149 * is the minimum required by solaris(2 reserved + 1 data cylinders). 150 * Hence try to adjust the cylinders by reducing the "nsect/nhead". 151 * 152 */ 153 /* 154 * assuming a minimum of 32 block cylinders. 155 */ 156 #define MINIMUM_NO_HEADS 2 157 #define MINIMUM_NO_SECTORS 16 158 159 #define MINIMUM_NO_CYLINDERS 128 160 161 #if defined(_SUNOS_VTOC_8) 162 163 /* These are 16-bit fields */ 164 #define MAXIMUM_NO_HEADS 65535 165 #define MAXIMUM_NO_SECTORS 65535 166 #define MAXIMUM_NO_CYLINDERS 65535 167 168 #endif /* defined(_SUNOS_VTOC_8) */ 169 170 /* 171 * minimum number of cylinders required by Solaris. 172 */ 173 #define SUN_MIN_CYL 3 174 175 176 177 /* 178 * ANSI prototypes for local static functions 179 */ 180 static struct disk_type *generic_disk_sense( 181 int fd, 182 int can_prompt, 183 struct dk_label *label, 184 struct scsi_inquiry *inquiry, 185 struct scsi_capacity_16 *capacity, 186 char *disk_name); 187 static int use_existing_disk_type( 188 int fd, 189 int can_prompt, 190 struct dk_label *label, 191 struct scsi_inquiry *inquiry, 192 struct disk_type *disk_type, 193 struct scsi_capacity_16 *capacity); 194 int build_default_partition(struct dk_label *label, 195 int ctrl_type); 196 static struct disk_type *find_scsi_disk_type( 197 char *disk_name, 198 struct dk_label *label); 199 static struct disk_type *find_scsi_disk_by_name( 200 char *disk_name); 201 static struct ctlr_type *find_scsi_ctlr_type(void); 202 static struct ctlr_info *find_scsi_ctlr_info( 203 struct dk_cinfo *dkinfo); 204 static struct disk_type *new_scsi_disk_type( 205 int fd, 206 char *disk_name, 207 struct dk_label *label); 208 static struct disk_info *find_scsi_disk_info( 209 struct dk_cinfo *dkinfo); 210 211 static struct disk_type *new_direct_disk_type(int fd, char *disk_name, 212 struct dk_label *label); 213 214 static int efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc); 215 static int auto_label_init(struct dk_label *label); 216 static struct ctlr_type *find_ctlr_type(ushort_t); 217 static struct ctlr_info *find_ctlr_info(struct dk_cinfo *, ushort_t); 218 static struct disk_info *find_disk_info(struct dk_cinfo *, ushort_t); 219 220 static char *get_sun_disk_name( 221 char *disk_name, 222 struct scsi_inquiry *inquiry); 223 static char *strcopy( 224 char *dst, 225 char *src, 226 int n); 227 static int adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl, 228 uint_t *nsect, uint_t *nhead); 229 static void compute_chs_values(diskaddr_t total_capacity, 230 diskaddr_t usable_capacity, uint_t *pcylp, 231 uint_t *nheadp, uint_t *nsectp); 232 #if defined(_SUNOS_VTOC_8) 233 static diskaddr_t square_box( 234 diskaddr_t capacity, 235 uint_t *dim1, uint_t lim1, 236 uint_t *dim2, uint_t lim2, 237 uint_t *dim3, uint_t lim3); 238 #endif /* defined(_SUNOS_VTOC_8) */ 239 240 241 /* 242 * We need to get information necessary to construct a *new* efi 243 * label type 244 */ 245 struct disk_type * 246 auto_efi_sense(int fd, struct efi_info *label) 247 { 248 249 struct dk_gpt *vtoc; 250 int i; 251 252 struct disk_type *disk, *dp; 253 struct disk_info *disk_info; 254 struct ctlr_info *ctlr; 255 struct dk_cinfo dkinfo; 256 struct partition_info *part; 257 uint64_t reserved; 258 259 if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) { 260 if (option_msg && diag_msg) { 261 err_print("DKIOCINFO failed\n"); 262 } 263 return (NULL); 264 } 265 if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_DIRECT || 266 cur_ctype->ctype_ctype == DKC_VBD || 267 cur_ctype->ctype_ctype == DKC_BLKDEV)) { 268 ctlr = find_ctlr_info(&dkinfo, cur_ctype->ctype_ctype); 269 disk_info = find_disk_info(&dkinfo, cur_ctype->ctype_ctype); 270 } else { 271 ctlr = find_scsi_ctlr_info(&dkinfo); 272 disk_info = find_scsi_disk_info(&dkinfo); 273 } 274 275 /* 276 * get vendor, product, revision and capacity info. 277 */ 278 if (get_disk_info(fd, label, disk_info) == -1) { 279 return ((struct disk_type *)NULL); 280 } 281 /* 282 * Now build the default partition table 283 */ 284 if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) { 285 err_print("efi_alloc_and_init failed. \n"); 286 return ((struct disk_type *)NULL); 287 } 288 289 label->e_parts = vtoc; 290 reserved = efi_reserved_sectors(vtoc); 291 292 /* 293 * Create a whole hog EFI partition table: 294 * S0 takes the whole disk except the primary EFI label, 295 * backup EFI label, and the reserved partition. 296 */ 297 vtoc->efi_parts[0].p_tag = V_USR; 298 vtoc->efi_parts[0].p_start = vtoc->efi_first_u_lba; 299 vtoc->efi_parts[0].p_size = vtoc->efi_last_u_lba - vtoc->efi_first_u_lba 300 - reserved + 1; 301 302 /* 303 * S1-S6 are unassigned slices. 304 */ 305 for (i = 1; i < vtoc->efi_nparts - 2; i ++) { 306 vtoc->efi_parts[i].p_tag = V_UNASSIGNED; 307 vtoc->efi_parts[i].p_start = 0; 308 vtoc->efi_parts[i].p_size = 0; 309 } 310 311 /* 312 * The reserved slice 313 */ 314 vtoc->efi_parts[vtoc->efi_nparts - 1].p_tag = V_RESERVED; 315 vtoc->efi_parts[vtoc->efi_nparts - 1].p_start = 316 vtoc->efi_last_u_lba - reserved + 1; 317 vtoc->efi_parts[vtoc->efi_nparts - 1].p_size = reserved; 318 319 /* 320 * Now stick all of it into the disk_type struct 321 */ 322 323 disk = (struct disk_type *)zalloc(sizeof (struct disk_type)); 324 assert(disk_info->disk_ctlr == ctlr); 325 dp = ctlr->ctlr_ctype->ctype_dlist; 326 if (dp == NULL) { 327 ctlr->ctlr_ctype->ctype_dlist = dp; 328 } else { 329 while (dp->dtype_next != NULL) { 330 dp = dp->dtype_next; 331 } 332 dp->dtype_next = disk; 333 } 334 disk->dtype_next = NULL; 335 336 disk->vendor = strdup(label->vendor); 337 disk->product = strdup(label->product); 338 disk->revision = strdup(label->revision); 339 340 if (disk->vendor == NULL || 341 disk->product == NULL || 342 disk->revision == NULL) { 343 free(disk->vendor); 344 free(disk->product); 345 free(disk->revision); 346 free(disk); 347 return (NULL); 348 } 349 350 disk->capacity = label->capacity; 351 352 part = (struct partition_info *) 353 zalloc(sizeof (struct partition_info)); 354 disk->dtype_plist = part; 355 356 part->pinfo_name = alloc_string("default"); 357 part->pinfo_next = NULL; 358 part->etoc = vtoc; 359 360 bzero(disk_info->v_volume, LEN_DKL_VVOL); 361 disk_info->disk_parts = part; 362 return (disk); 363 } 364 365 static int 366 efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc) 367 { 368 void *data = dk_ioc->dki_data; 369 int error; 370 371 dk_ioc->dki_data_64 = (uint64_t)(uintptr_t)data; 372 error = ioctl(fd, cmd, (void *)dk_ioc); 373 dk_ioc->dki_data = data; 374 375 return (error); 376 } 377 378 static struct ctlr_type * 379 find_ctlr_type(ushort_t type) 380 { 381 struct mctlr_list *mlp; 382 383 assert(type == DKC_DIRECT || 384 type == DKC_VBD || 385 type == DKC_BLKDEV); 386 387 mlp = controlp; 388 389 while (mlp != NULL) { 390 if (mlp->ctlr_type->ctype_ctype == type) { 391 return (mlp->ctlr_type); 392 } 393 mlp = mlp->next; 394 } 395 396 impossible("no DIRECT/VBD/BLKDEV controller type"); 397 398 return ((struct ctlr_type *)NULL); 399 } 400 401 static struct ctlr_info * 402 find_ctlr_info(struct dk_cinfo *dkinfo, ushort_t type) 403 { 404 struct ctlr_info *ctlr; 405 406 assert(type == DKC_DIRECT || 407 type == DKC_VBD || 408 type == DKC_BLKDEV); 409 410 for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) { 411 if (ctlr->ctlr_addr == dkinfo->dki_addr && 412 ctlr->ctlr_space == dkinfo->dki_space && 413 ctlr->ctlr_ctype->ctype_ctype == dkinfo->dki_ctype) { 414 return (ctlr); 415 } 416 } 417 418 impossible("no DIRECT/VBD/BLKDEV controller info"); 419 /*NOTREACHED*/ 420 return ((struct ctlr_info *)NULL); 421 } 422 423 static struct disk_info * 424 find_disk_info(struct dk_cinfo *dkinfo, ushort_t type) 425 { 426 struct disk_info *disk; 427 struct dk_cinfo *dp; 428 429 assert(type == DKC_DIRECT || 430 type == DKC_VBD || 431 type == DKC_BLKDEV); 432 433 for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 434 dp = &disk->disk_dkinfo; 435 if (dp->dki_ctype == dkinfo->dki_ctype && 436 dp->dki_cnum == dkinfo->dki_cnum && 437 dp->dki_unit == dkinfo->dki_unit && 438 strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) { 439 return (disk); 440 } 441 } 442 443 impossible("No DIRECT/VBD/BLKDEV disk info instance\n"); 444 /*NOTREACHED*/ 445 return ((struct disk_info *)NULL); 446 } 447 448 /* 449 * To convert EFI to SMI labels, we need to get label geometry. 450 * Unfortunately at this time there is no good way to do so. 451 * DKIOCGGEOM will fail if disk is EFI labeled. So we hack around 452 * it and clear EFI label, do a DKIOCGGEOM and put the EFI label 453 * back on disk. 454 * This routine gets the label geometry and initializes the label 455 * It uses cur_file as opened device. 456 * returns 0 if succeeds or -1 if failed. 457 */ 458 static int 459 auto_label_init(struct dk_label *label) 460 { 461 dk_efi_t dk_ioc; 462 dk_efi_t dk_ioc_back; 463 efi_gpt_t *data = NULL; 464 efi_gpt_t *databack = NULL; 465 struct dk_geom disk_geom; 466 struct dk_minfo disk_info; 467 efi_gpt_t *backsigp; 468 int fd = cur_file; 469 int rval = -1; 470 int efisize = EFI_LABEL_SIZE * 2; 471 int success = 0; 472 uint64_t sig; 473 uint64_t backsig; 474 475 if ((data = calloc(efisize, 1)) == NULL) { 476 err_print("auto_label_init: calloc failed\n"); 477 goto auto_label_init_out; 478 } 479 480 dk_ioc.dki_data = data; 481 dk_ioc.dki_lba = 1; 482 dk_ioc.dki_length = efisize; 483 484 if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) != 0) { 485 err_print("auto_label_init: GETEFI failed\n"); 486 goto auto_label_init_out; 487 } 488 489 if ((databack = calloc(efisize, 1)) == NULL) { 490 err_print("auto_label_init calloc2 failed"); 491 goto auto_label_init_out; 492 } 493 494 /* get the LBA size and capacity */ 495 if (ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) == -1) { 496 err_print("auto_label_init: dkiocgmediainfo failed\n"); 497 goto auto_label_init_out; 498 } 499 500 if (disk_info.dki_lbsize == 0) { 501 if (option_msg && diag_msg) { 502 err_print("auto_lbal_init: assuming 512 byte" 503 "block size"); 504 } 505 disk_info.dki_lbsize = DEV_BSIZE; 506 } 507 508 dk_ioc_back.dki_data = databack; 509 510 /* 511 * back up efi label goes to capacity - 1, we are reading an extra block 512 * before the back up label. 513 */ 514 dk_ioc_back.dki_lba = disk_info.dki_capacity - 1 - 1; 515 dk_ioc_back.dki_length = efisize; 516 517 if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc_back) != 0) { 518 err_print("auto_label_init: GETEFI backup failed\n"); 519 goto auto_label_init_out; 520 } 521 522 sig = dk_ioc.dki_data->efi_gpt_Signature; 523 dk_ioc.dki_data->efi_gpt_Signature = 0x0; 524 525 enter_critical(); 526 527 if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) { 528 err_print("auto_label_init: SETEFI failed\n"); 529 exit_critical(); 530 goto auto_label_init_out; 531 } 532 533 backsigp = (efi_gpt_t *)((uintptr_t)dk_ioc_back.dki_data + cur_blksz); 534 535 backsig = backsigp->efi_gpt_Signature; 536 537 backsigp->efi_gpt_Signature = 0; 538 539 if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc_back) == -1) { 540 err_print("auto_label_init: SETEFI backup failed\n"); 541 } 542 543 if (ioctl(cur_file, DKIOCGGEOM, &disk_geom) != 0) 544 err_print("auto_label_init: GGEOM failed\n"); 545 else 546 success = 1; 547 548 dk_ioc.dki_data->efi_gpt_Signature = sig; 549 backsigp->efi_gpt_Signature = backsig; 550 551 if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc_back) == -1) { 552 err_print("auto_label_init: SETEFI revert backup failed\n"); 553 success = 0; 554 } 555 556 if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc) == -1) { 557 err_print("auto_label_init: SETEFI revert failed\n"); 558 success = 0; 559 } 560 561 exit_critical(); 562 563 if (success == 0) 564 goto auto_label_init_out; 565 566 ncyl = disk_geom.dkg_ncyl; 567 acyl = disk_geom.dkg_acyl; 568 nhead = disk_geom.dkg_nhead; 569 nsect = disk_geom.dkg_nsect; 570 pcyl = ncyl + acyl; 571 572 label->dkl_pcyl = pcyl; 573 label->dkl_ncyl = ncyl; 574 label->dkl_acyl = acyl; 575 label->dkl_nhead = nhead; 576 label->dkl_nsect = nsect; 577 label->dkl_apc = 0; 578 label->dkl_intrlv = 1; 579 label->dkl_rpm = disk_geom.dkg_rpm; 580 581 label->dkl_magic = DKL_MAGIC; 582 583 (void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel), 584 "%s cyl %u alt %u hd %u sec %u", 585 "DEFAULT", ncyl, acyl, nhead, nsect); 586 587 rval = 0; 588 #if defined(_FIRMWARE_NEEDS_FDISK) 589 (void) auto_solaris_part(label); 590 ncyl = label->dkl_ncyl; 591 592 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 593 594 if (!build_default_partition(label, DKC_DIRECT)) { 595 rval = -1; 596 } 597 598 (void) checksum(label, CK_MAKESUM); 599 600 601 auto_label_init_out: 602 if (data) 603 free(data); 604 if (databack) 605 free(databack); 606 607 return (rval); 608 } 609 610 static struct disk_type * 611 new_direct_disk_type( 612 int fd, 613 char *disk_name, 614 struct dk_label *label) 615 { 616 struct disk_type *dp; 617 struct disk_type *disk; 618 struct ctlr_info *ctlr; 619 struct dk_cinfo dkinfo; 620 struct partition_info *part = NULL; 621 struct partition_info *pt; 622 struct disk_info *disk_info; 623 int i; 624 625 /* 626 * Get the disk controller info for this disk 627 */ 628 if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) { 629 if (option_msg && diag_msg) { 630 err_print("DKIOCINFO failed\n"); 631 } 632 return (NULL); 633 } 634 635 /* 636 * Find the ctlr_info for this disk. 637 */ 638 ctlr = find_ctlr_info(&dkinfo, dkinfo.dki_ctype); 639 640 /* 641 * Allocate a new disk type for the direct controller. 642 */ 643 disk = (struct disk_type *)zalloc(sizeof (struct disk_type)); 644 645 /* 646 * Find the disk_info instance for this disk. 647 */ 648 disk_info = find_disk_info(&dkinfo, dkinfo.dki_ctype); 649 650 /* 651 * The controller and the disk should match. 652 */ 653 assert(disk_info->disk_ctlr == ctlr); 654 655 /* 656 * Link the disk into the list of disks 657 */ 658 dp = ctlr->ctlr_ctype->ctype_dlist; 659 if (dp == NULL) { 660 ctlr->ctlr_ctype->ctype_dlist = dp; 661 } else { 662 while (dp->dtype_next != NULL) { 663 dp = dp->dtype_next; 664 } 665 dp->dtype_next = disk; 666 } 667 disk->dtype_next = NULL; 668 669 /* 670 * Allocate and initialize the disk name. 671 */ 672 disk->dtype_asciilabel = alloc_string(disk_name); 673 674 /* 675 * Initialize disk geometry info 676 */ 677 disk->dtype_pcyl = label->dkl_pcyl; 678 disk->dtype_ncyl = label->dkl_ncyl; 679 disk->dtype_acyl = label->dkl_acyl; 680 disk->dtype_nhead = label->dkl_nhead; 681 disk->dtype_nsect = label->dkl_nsect; 682 disk->dtype_rpm = label->dkl_rpm; 683 684 part = (struct partition_info *) 685 zalloc(sizeof (struct partition_info)); 686 pt = disk->dtype_plist; 687 if (pt == NULL) { 688 disk->dtype_plist = part; 689 } else { 690 while (pt->pinfo_next != NULL) { 691 pt = pt->pinfo_next; 692 } 693 pt->pinfo_next = part; 694 } 695 696 part->pinfo_next = NULL; 697 698 /* 699 * Set up the partition name 700 */ 701 part->pinfo_name = alloc_string("default"); 702 703 /* 704 * Fill in the partition info from the label 705 */ 706 for (i = 0; i < NDKMAP; i++) { 707 708 #if defined(_SUNOS_VTOC_8) 709 part->pinfo_map[i] = label->dkl_map[i]; 710 711 #elif defined(_SUNOS_VTOC_16) 712 part->pinfo_map[i].dkl_cylno = 713 label->dkl_vtoc.v_part[i].p_start / 714 ((blkaddr_t)(disk->dtype_nhead * 715 disk->dtype_nsect - apc)); 716 part->pinfo_map[i].dkl_nblk = 717 label->dkl_vtoc.v_part[i].p_size; 718 #else 719 #error No VTOC format defined. 720 #endif /* defined(_SUNOS_VTOC_8) */ 721 } 722 723 /* 724 * Use the VTOC if valid, or install a default 725 */ 726 if (label->dkl_vtoc.v_version == V_VERSION) { 727 (void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume, 728 LEN_DKL_VVOL); 729 part->vtoc = label->dkl_vtoc; 730 } else { 731 (void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL); 732 set_vtoc_defaults(part); 733 } 734 735 /* 736 * Link the disk to the partition map 737 */ 738 disk_info->disk_parts = part; 739 740 return (disk); 741 } 742 743 /* 744 * Get a disk type that has label info. This is used to convert 745 * EFI label to SMI label 746 */ 747 struct disk_type * 748 auto_direct_get_geom_label(int fd, struct dk_label *label) 749 { 750 struct disk_type *disk_type; 751 752 if (auto_label_init(label) != 0) { 753 err_print("auto_direct_get_geom_label: failed to get label" 754 "geometry"); 755 return (NULL); 756 } else { 757 disk_type = new_direct_disk_type(fd, "DEFAULT", label); 758 return (disk_type); 759 } 760 } 761 762 /* 763 * Auto-sense a scsi disk configuration, ie get the information 764 * necessary to construct a label. We have two different 765 * ways to auto-sense a scsi disk: 766 * - format.dat override, via inquiry name 767 * - generic scsi, via standard mode sense and inquiry 768 * Depending on how and when we are called, and/or 769 * change geometry and reformat. 770 */ 771 struct disk_type * 772 auto_sense( 773 int fd, 774 int can_prompt, 775 struct dk_label *label) 776 { 777 struct scsi_inquiry inquiry; 778 struct scsi_capacity_16 capacity; 779 struct disk_type *disk_type; 780 char disk_name[DISK_NAME_MAX]; 781 int force_format_dat = 0; 782 int force_generic = 0; 783 u_ioparam_t ioparam; 784 int deflt; 785 char *buf; 786 787 /* 788 * First, if expert mode, find out if the user 789 * wants to override any of the standard methods. 790 */ 791 if (can_prompt && expert_mode) { 792 deflt = 1; 793 ioparam.io_charlist = confirm_list; 794 if (input(FIO_MSTR, FORMAT_MSG, '?', &ioparam, 795 &deflt, DATA_INPUT) == 0) { 796 force_format_dat = 1; 797 } else if (input(FIO_MSTR, GENERIC_MSG, '?', &ioparam, 798 &deflt, DATA_INPUT) == 0) { 799 force_generic = 1; 800 } 801 } 802 803 /* 804 * Get the Inquiry data. If this fails, there's 805 * no hope for this disk, so give up. 806 */ 807 if (uscsi_inquiry(fd, (char *)&inquiry, sizeof (inquiry))) { 808 return ((struct disk_type *)NULL); 809 } 810 if (option_msg && diag_msg) { 811 err_print("Product id: "); 812 print_buf(inquiry.inq_pid, sizeof (inquiry.inq_pid)); 813 err_print("\n"); 814 } 815 816 /* 817 * Get the Read Capacity 818 */ 819 if (uscsi_read_capacity(fd, &capacity)) { 820 return ((struct disk_type *)NULL); 821 } 822 823 /* 824 * If the reported capacity is set to zero, then the disk 825 * is not usable. If the reported capacity is set to all 826 * 0xf's, then this disk is too large. These could only 827 * happen with a device that supports LBAs larger than 64 828 * bits which are not defined by any current T10 standards 829 * or by error responding from target. 830 */ 831 if ((capacity.sc_capacity == 0) || 832 (capacity.sc_capacity == UINT_MAX64)) { 833 if (option_msg && diag_msg) { 834 err_print("Invalid capacity\n"); 835 } 836 return ((struct disk_type *)NULL); 837 } 838 if (option_msg && diag_msg) { 839 err_print("blocks: %llu (0x%llx)\n", 840 capacity.sc_capacity, capacity.sc_capacity); 841 err_print("blksize: %u\n", capacity.sc_lbasize); 842 } 843 844 /* 845 * Extract the disk name for the format.dat override 846 */ 847 (void) get_sun_disk_name(disk_name, &inquiry); 848 if (option_msg && diag_msg) { 849 err_print("disk name: `%s`\n", disk_name); 850 } 851 852 buf = zalloc(cur_blksz); 853 if (scsi_rdwr(DIR_READ, fd, (diskaddr_t)0, 1, (caddr_t)buf, 854 F_SILENT, NULL)) { 855 free(buf); 856 return ((struct disk_type *)NULL); 857 } 858 free(buf); 859 860 /* 861 * Figure out which method we use for auto sense. 862 * If a particular method fails, we fall back to 863 * the next possibility. 864 */ 865 866 if (force_generic) { 867 return (generic_disk_sense(fd, can_prompt, label, 868 &inquiry, &capacity, disk_name)); 869 } 870 871 /* 872 * Try for an existing format.dat first 873 */ 874 if ((disk_type = find_scsi_disk_by_name(disk_name)) != NULL) { 875 if (use_existing_disk_type(fd, can_prompt, label, 876 &inquiry, disk_type, &capacity)) { 877 return (disk_type); 878 } 879 if (force_format_dat) { 880 return (NULL); 881 } 882 } 883 884 /* 885 * Otherwise, try using generic SCSI-2 sense and inquiry. 886 */ 887 888 return (generic_disk_sense(fd, can_prompt, label, 889 &inquiry, &capacity, disk_name)); 890 } 891 892 893 894 /*ARGSUSED*/ 895 static struct disk_type * 896 generic_disk_sense( 897 int fd, 898 int can_prompt, 899 struct dk_label *label, 900 struct scsi_inquiry *inquiry, 901 struct scsi_capacity_16 *capacity, 902 char *disk_name) 903 { 904 struct disk_type *disk; 905 int setdefault = 0; 906 uint_t pcyl = 0; 907 uint_t ncyl = 0; 908 uint_t acyl = 0; 909 uint_t nhead = 0; 910 uint_t nsect = 0; 911 int rpm = 0; 912 diskaddr_t nblocks = 0; 913 diskaddr_t tblocks = 0; 914 union { 915 struct mode_format page3; 916 uchar_t buf3[MAX_MODE_SENSE_SIZE]; 917 } u_page3; 918 union { 919 struct mode_geometry page4; 920 uchar_t buf4[MAX_MODE_SENSE_SIZE]; 921 } u_page4; 922 struct mode_format *page3 = &u_page3.page3; 923 struct mode_geometry *page4 = &u_page4.page4; 924 struct scsi_ms_header header; 925 926 /* 927 * If the name of this disk appears to be "SUN", use it, 928 * otherwise construct a name out of the generic 929 * Inquiry info. If it turns out that we already 930 * have a SUN disk type of this name that differs 931 * in geometry, we will revert to the generic name 932 * anyway. 933 */ 934 if (memcmp(disk_name, "SUN", strlen("SUN")) != 0) { 935 (void) get_generic_disk_name(disk_name, inquiry); 936 } 937 938 /* 939 * Get the number of blocks from Read Capacity data. Note that 940 * the logical block address range from 0 to capacity->sc_capacity. 941 * Limit the size to 2 TB (UINT32_MAX) to use with SMI labels. 942 */ 943 tblocks = (capacity->sc_capacity + 1); 944 if (tblocks > UINT32_MAX) 945 nblocks = UINT32_MAX; 946 else 947 nblocks = tblocks; 948 949 /* 950 * Get current Page 3 - Format Parameters page 951 */ 952 if (uscsi_mode_sense(fd, DAD_MODE_FORMAT, MODE_SENSE_PC_CURRENT, 953 (caddr_t)&u_page3, MAX_MODE_SENSE_SIZE, &header)) { 954 setdefault = 1; 955 } 956 957 /* 958 * Get current Page 4 - Drive Geometry page 959 */ 960 if (uscsi_mode_sense(fd, DAD_MODE_GEOMETRY, MODE_SENSE_PC_CURRENT, 961 (caddr_t)&u_page4, MAX_MODE_SENSE_SIZE, &header)) { 962 setdefault = 1; 963 } 964 965 if (setdefault != 1) { 966 /* The inquiry of mode page 3 & page 4 are successful */ 967 /* 968 * Correct for byte order if necessary 969 */ 970 page4->rpm = BE_16(page4->rpm); 971 page4->step_rate = BE_16(page4->step_rate); 972 page3->tracks_per_zone = BE_16(page3->tracks_per_zone); 973 page3->alt_sect_zone = BE_16(page3->alt_sect_zone); 974 page3->alt_tracks_zone = BE_16(page3->alt_tracks_zone); 975 page3->alt_tracks_vol = BE_16(page3->alt_tracks_vol); 976 page3->sect_track = BE_16(page3->sect_track); 977 page3->data_bytes_sect = BE_16(page3->data_bytes_sect); 978 page3->interleave = BE_16(page3->interleave); 979 page3->track_skew = BE_16(page3->track_skew); 980 page3->cylinder_skew = BE_16(page3->cylinder_skew); 981 982 983 /* 984 * Construct a new label out of the sense data, 985 * Inquiry and Capacity. 986 * 987 * If the disk capacity is > 1TB then simply compute 988 * the CHS values based on the total disk capacity and 989 * not use the values from mode-sense data. 990 */ 991 if (tblocks > INT32_MAX) { 992 compute_chs_values(tblocks, nblocks, &pcyl, &nhead, 993 &nsect); 994 } else { 995 pcyl = (page4->cyl_ub << 16) + (page4->cyl_mb << 8) + 996 page4->cyl_lb; 997 nhead = page4->heads; 998 nsect = page3->sect_track; 999 } 1000 1001 rpm = page4->rpm; 1002 1003 /* 1004 * If the number of physical cylinders reported is less 1005 * the SUN_MIN_CYL(3) then try to adjust the geometry so that 1006 * we have atleast SUN_MIN_CYL cylinders. 1007 */ 1008 if (pcyl < SUN_MIN_CYL) { 1009 if (nhead == 0 || nsect == 0) { 1010 setdefault = 1; 1011 } else if (adjust_disk_geometry( 1012 (diskaddr_t)(capacity->sc_capacity + 1), 1013 &pcyl, &nhead, &nsect)) { 1014 setdefault = 1; 1015 } 1016 } 1017 } 1018 1019 /* 1020 * Mode sense page 3 and page 4 are obsolete in SCSI-3. For 1021 * newly developed large sector size disk, we will not rely on 1022 * those two pages but compute geometry directly. 1023 */ 1024 if ((setdefault == 1) || (capacity->sc_lbasize != DEV_BSIZE)) { 1025 /* 1026 * If the number of cylinders or the number of heads reported 1027 * is zero, we think the inquiry of page 3 and page 4 failed. 1028 * We will set the geometry infomation by ourselves. 1029 */ 1030 compute_chs_values(tblocks, nblocks, &pcyl, &nhead, &nsect); 1031 } 1032 1033 /* 1034 * The sd driver reserves 2 cylinders the backup disk label and 1035 * the deviceid. Set the number of data cylinders to pcyl-acyl. 1036 */ 1037 acyl = DK_ACYL; 1038 ncyl = pcyl - acyl; 1039 1040 if (option_msg && diag_msg) { 1041 err_print("Geometry:\n"); 1042 err_print(" pcyl: %u\n", pcyl); 1043 err_print(" ncyl: %u\n", ncyl); 1044 err_print(" heads: %u\n", nhead); 1045 err_print(" nsects: %u\n", nsect); 1046 err_print(" acyl: %u\n", acyl); 1047 1048 #if defined(_SUNOS_VTOC_16) 1049 err_print(" bcyl: %u\n", bcyl); 1050 #endif /* defined(_SUNOS_VTOC_16) */ 1051 1052 err_print(" rpm: %d\n", rpm); 1053 err_print(" nblocks: %llu\n", nblocks); 1054 } 1055 1056 /* 1057 * Some drives do not support page4 or report 0 for page4->rpm, 1058 * adjust it to AVG_RPM, 3600. 1059 */ 1060 if (rpm < MIN_RPM || rpm > MAX_RPM) { 1061 if (option_msg && diag_msg) 1062 err_print("The current rpm value %d is invalid," 1063 " adjusting it to %d\n", rpm, AVG_RPM); 1064 rpm = AVG_RPM; 1065 } 1066 1067 /* 1068 * Some drives report 0 for nsect (page 3, byte 10 and 11) if they 1069 * have variable number of sectors per track. So adjust nsect. 1070 * Also the value is defined as vendor specific, hence check if 1071 * it is in a tolerable range. The values (32 and 4 below) are 1072 * chosen so that this change below does not generate a different 1073 * geometry for currently supported sun disks. 1074 */ 1075 if ((nsect == 0) || 1076 ((diskaddr_t)pcyl * nhead * nsect) < (nblocks - nblocks/32) || 1077 ((diskaddr_t)pcyl * nhead * nsect) > (nblocks + nblocks/4)) { 1078 if (nblocks > (pcyl * nhead)) { 1079 err_print("Mode sense page(3) reports nsect value" 1080 " as %d, adjusting it to %llu\n", 1081 nsect, nblocks / (pcyl * nhead)); 1082 nsect = nblocks / (pcyl * nhead); 1083 } else { 1084 /* convert capacity to nsect * nhead * pcyl */ 1085 err_print("\nWARNING: Disk geometry is based on " 1086 "capacity data.\n\n"); 1087 compute_chs_values(tblocks, nblocks, &pcyl, &nhead, 1088 &nsect); 1089 ncyl = pcyl - acyl; 1090 if (option_msg && diag_msg) { 1091 err_print("Geometry:(after adjustment)\n"); 1092 err_print(" pcyl: %u\n", pcyl); 1093 err_print(" ncyl: %u\n", ncyl); 1094 err_print(" heads: %u\n", nhead); 1095 err_print(" nsects: %u\n", nsect); 1096 err_print(" acyl: %u\n", acyl); 1097 1098 #if defined(_SUNOS_VTOC_16) 1099 err_print(" bcyl: %u\n", bcyl); 1100 #endif 1101 1102 err_print(" rpm: %d\n", rpm); 1103 err_print(" nblocks: %llu\n", nblocks); 1104 } 1105 } 1106 } 1107 1108 /* 1109 * Some drives report their physical geometry such that 1110 * it is greater than the actual capacity. Adjust the 1111 * geometry to allow for this, so we don't run off 1112 * the end of the disk. 1113 */ 1114 if (((diskaddr_t)pcyl * nhead * nsect) > nblocks) { 1115 uint_t p = pcyl; 1116 if (option_msg && diag_msg) { 1117 err_print("Computed capacity (%llu) exceeds actual " 1118 "disk capacity (%llu)\n", 1119 (diskaddr_t)pcyl * nhead * nsect, nblocks); 1120 } 1121 do { 1122 pcyl--; 1123 } while (((diskaddr_t)pcyl * nhead * nsect) > nblocks); 1124 1125 if (can_prompt && expert_mode && !option_f) { 1126 /* 1127 * Try to adjust nsect instead of pcyl to see if we 1128 * can optimize. For compatability reasons do this 1129 * only in expert mode (refer to bug 1144812). 1130 */ 1131 uint_t n = nsect; 1132 do { 1133 n--; 1134 } while (((diskaddr_t)p * nhead * n) > nblocks); 1135 if (((diskaddr_t)p * nhead * n) > 1136 ((diskaddr_t)pcyl * nhead * nsect)) { 1137 u_ioparam_t ioparam; 1138 int deflt = 1; 1139 /* 1140 * Ask the user for a choice here. 1141 */ 1142 ioparam.io_bounds.lower = 1; 1143 ioparam.io_bounds.upper = 2; 1144 err_print("1. Capacity = %llu, with pcyl = %u " 1145 "nhead = %u nsect = %u\n", 1146 ((diskaddr_t)pcyl * nhead * nsect), 1147 pcyl, nhead, nsect); 1148 err_print("2. Capacity = %llu, with pcyl = %u " 1149 "nhead = %u nsect = %u\n", 1150 ((diskaddr_t)p * nhead * n), 1151 p, nhead, n); 1152 if (input(FIO_INT, "Select one of the above " 1153 "choices ", ':', &ioparam, 1154 &deflt, DATA_INPUT) == 2) { 1155 pcyl = p; 1156 nsect = n; 1157 } 1158 } 1159 } 1160 } 1161 1162 #if defined(_SUNOS_VTOC_8) 1163 /* 1164 * Finally, we need to make sure we don't overflow any of the 1165 * fields in our disk label. To do this we need to `square 1166 * the box' so to speak. We will lose bits here. 1167 */ 1168 1169 if ((pcyl > MAXIMUM_NO_CYLINDERS && 1170 ((nsect > MAXIMUM_NO_SECTORS) || 1171 (nhead > MAXIMUM_NO_HEADS))) || 1172 ((nsect > MAXIMUM_NO_SECTORS) && 1173 (nhead > MAXIMUM_NO_HEADS))) { 1174 err_print("This disk is too big to label. " 1175 " You will lose some blocks.\n"); 1176 } 1177 if ((pcyl > MAXIMUM_NO_CYLINDERS) || 1178 (nsect > MAXIMUM_NO_SECTORS) || 1179 (nhead > MAXIMUM_NO_HEADS)) { 1180 u_ioparam_t ioparam; 1181 int order; 1182 char msg[256]; 1183 1184 order = ((pcyl > nhead)<<2) | 1185 ((pcyl > nsect)<<1) | 1186 (nhead > nsect); 1187 switch (order) { 1188 case 0x7: /* pcyl > nhead > nsect */ 1189 nblocks = 1190 square_box(nblocks, 1191 &pcyl, MAXIMUM_NO_CYLINDERS, 1192 &nhead, MAXIMUM_NO_HEADS, 1193 &nsect, MAXIMUM_NO_SECTORS); 1194 break; 1195 case 0x6: /* pcyl > nsect > nhead */ 1196 nblocks = 1197 square_box(nblocks, 1198 &pcyl, MAXIMUM_NO_CYLINDERS, 1199 &nsect, MAXIMUM_NO_SECTORS, 1200 &nhead, MAXIMUM_NO_HEADS); 1201 break; 1202 case 0x4: /* nsect > pcyl > nhead */ 1203 nblocks = 1204 square_box(nblocks, 1205 &nsect, MAXIMUM_NO_SECTORS, 1206 &pcyl, MAXIMUM_NO_CYLINDERS, 1207 &nhead, MAXIMUM_NO_HEADS); 1208 break; 1209 case 0x0: /* nsect > nhead > pcyl */ 1210 nblocks = 1211 square_box(nblocks, 1212 &nsect, MAXIMUM_NO_SECTORS, 1213 &nhead, MAXIMUM_NO_HEADS, 1214 &pcyl, MAXIMUM_NO_CYLINDERS); 1215 break; 1216 case 0x3: /* nhead > pcyl > nsect */ 1217 nblocks = 1218 square_box(nblocks, 1219 &nhead, MAXIMUM_NO_HEADS, 1220 &pcyl, MAXIMUM_NO_CYLINDERS, 1221 &nsect, MAXIMUM_NO_SECTORS); 1222 break; 1223 case 0x1: /* nhead > nsect > pcyl */ 1224 nblocks = 1225 square_box(nblocks, 1226 &nhead, MAXIMUM_NO_HEADS, 1227 &nsect, MAXIMUM_NO_SECTORS, 1228 &pcyl, MAXIMUM_NO_CYLINDERS); 1229 break; 1230 default: 1231 /* How did we get here? */ 1232 impossible("label overflow adjustment"); 1233 1234 /* Do something useful */ 1235 nblocks = 1236 square_box(nblocks, 1237 &nhead, MAXIMUM_NO_HEADS, 1238 &nsect, MAXIMUM_NO_SECTORS, 1239 &pcyl, MAXIMUM_NO_CYLINDERS); 1240 break; 1241 } 1242 if (option_msg && diag_msg && 1243 (capacity->sc_capacity + 1 != nblocks)) { 1244 err_print("After adjusting geometry you lost" 1245 " %llu of %llu blocks.\n", 1246 (capacity->sc_capacity + 1 - nblocks), 1247 capacity->sc_capacity + 1); 1248 } 1249 while (can_prompt && expert_mode && !option_f) { 1250 int deflt = 1; 1251 1252 /* 1253 * Allow user to modify this by hand if desired. 1254 */ 1255 (void) sprintf(msg, 1256 "\nGeometry: %u heads, %u sectors %u cylinders" 1257 " result in %llu out of %llu blocks.\n" 1258 "Do you want to modify the device geometry", 1259 nhead, nsect, pcyl, 1260 nblocks, capacity->sc_capacity + 1); 1261 1262 ioparam.io_charlist = confirm_list; 1263 if (input(FIO_MSTR, msg, '?', &ioparam, 1264 &deflt, DATA_INPUT) != 0) 1265 break; 1266 1267 ioparam.io_bounds.lower = MINIMUM_NO_HEADS; 1268 ioparam.io_bounds.upper = MAXIMUM_NO_HEADS; 1269 nhead = input(FIO_INT, "Number of heads", ':', 1270 &ioparam, (int *)&nhead, DATA_INPUT); 1271 ioparam.io_bounds.lower = MINIMUM_NO_SECTORS; 1272 ioparam.io_bounds.upper = MAXIMUM_NO_SECTORS; 1273 nsect = input(FIO_INT, 1274 "Number of sectors per track", 1275 ':', &ioparam, (int *)&nsect, DATA_INPUT); 1276 ioparam.io_bounds.lower = SUN_MIN_CYL; 1277 ioparam.io_bounds.upper = MAXIMUM_NO_CYLINDERS; 1278 pcyl = input(FIO_INT, "Number of cylinders", 1279 ':', &ioparam, (int *)&pcyl, DATA_INPUT); 1280 nblocks = (diskaddr_t)nhead * nsect * pcyl; 1281 if (nblocks > capacity->sc_capacity + 1) { 1282 err_print("Warning: %llu blocks exceeds " 1283 "disk capacity of %llu blocks\n", 1284 nblocks, 1285 capacity->sc_capacity + 1); 1286 } 1287 } 1288 } 1289 #endif /* defined(_SUNOS_VTOC_8) */ 1290 1291 ncyl = pcyl - acyl; 1292 1293 if (option_msg && diag_msg) { 1294 err_print("\nGeometry after adjusting for capacity:\n"); 1295 err_print(" pcyl: %u\n", pcyl); 1296 err_print(" ncyl: %u\n", ncyl); 1297 err_print(" heads: %u\n", nhead); 1298 err_print(" nsects: %u\n", nsect); 1299 err_print(" acyl: %u\n", acyl); 1300 err_print(" rpm: %d\n", rpm); 1301 } 1302 1303 (void) memset((char *)label, 0, sizeof (struct dk_label)); 1304 1305 label->dkl_magic = DKL_MAGIC; 1306 1307 (void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel), 1308 "%s cyl %u alt %u hd %u sec %u", 1309 disk_name, ncyl, acyl, nhead, nsect); 1310 1311 label->dkl_pcyl = pcyl; 1312 label->dkl_ncyl = ncyl; 1313 label->dkl_acyl = acyl; 1314 label->dkl_nhead = nhead; 1315 label->dkl_nsect = nsect; 1316 label->dkl_apc = 0; 1317 label->dkl_intrlv = 1; 1318 label->dkl_rpm = rpm; 1319 1320 #if defined(_FIRMWARE_NEEDS_FDISK) 1321 if (auto_solaris_part(label) == -1) 1322 goto err; 1323 ncyl = label->dkl_ncyl; 1324 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 1325 1326 1327 if (!build_default_partition(label, DKC_SCSI_CCS)) { 1328 goto err; 1329 } 1330 1331 (void) checksum(label, CK_MAKESUM); 1332 1333 /* 1334 * Find an existing disk type defined for this disk. 1335 * For this to work, both the name and geometry must 1336 * match. If there is no such type, but there already 1337 * is a disk defined with that name, but with a different 1338 * geometry, construct a new generic disk name out of 1339 * the inquiry information. Whatever name we're 1340 * finally using, if there's no such disk type defined, 1341 * build a new disk definition. 1342 */ 1343 if ((disk = find_scsi_disk_type(disk_name, label)) == NULL) { 1344 if (find_scsi_disk_by_name(disk_name) != NULL) { 1345 char old_name[DISK_NAME_MAX]; 1346 (void) strcpy(old_name, disk_name); 1347 (void) get_generic_disk_name(disk_name, 1348 inquiry); 1349 if (option_msg && diag_msg) { 1350 err_print( 1351 "Changing disk type name from '%s' to '%s'\n", old_name, disk_name); 1352 } 1353 (void) snprintf(label->dkl_asciilabel, 1354 sizeof (label->dkl_asciilabel), 1355 "%s cyl %u alt %u hd %u sec %u", 1356 disk_name, ncyl, acyl, nhead, nsect); 1357 (void) checksum(label, CK_MAKESUM); 1358 disk = find_scsi_disk_type(disk_name, label); 1359 } 1360 if (disk == NULL) { 1361 disk = new_scsi_disk_type(fd, disk_name, label); 1362 if (disk == NULL) 1363 goto err; 1364 } 1365 } 1366 1367 return (disk); 1368 1369 err: 1370 if (option_msg && diag_msg) { 1371 err_print( 1372 "Configuration via generic SCSI-2 information failed\n"); 1373 } 1374 return (NULL); 1375 } 1376 1377 1378 /*ARGSUSED*/ 1379 static int 1380 use_existing_disk_type( 1381 int fd, 1382 int can_prompt, 1383 struct dk_label *label, 1384 struct scsi_inquiry *inquiry, 1385 struct disk_type *disk_type, 1386 struct scsi_capacity_16 *capacity) 1387 { 1388 int pcyl; 1389 int acyl; 1390 int nhead; 1391 int nsect; 1392 int rpm; 1393 1394 /* 1395 * Construct a new label out of the format.dat 1396 */ 1397 pcyl = disk_type->dtype_pcyl; 1398 acyl = disk_type->dtype_acyl; 1399 ncyl = disk_type->dtype_ncyl; 1400 nhead = disk_type->dtype_nhead; 1401 nsect = disk_type->dtype_nsect; 1402 rpm = disk_type->dtype_rpm; 1403 1404 if (option_msg && diag_msg) { 1405 err_print("Format.dat geometry:\n"); 1406 err_print(" pcyl: %u\n", pcyl); 1407 err_print(" heads: %u\n", nhead); 1408 err_print(" nsects: %u\n", nsect); 1409 err_print(" acyl: %u\n", acyl); 1410 err_print(" rpm: %d\n", rpm); 1411 } 1412 1413 (void) memset((char *)label, 0, sizeof (struct dk_label)); 1414 1415 label->dkl_magic = DKL_MAGIC; 1416 1417 (void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel), 1418 "%s cyl %u alt %u hd %u sec %u", 1419 disk_type->dtype_asciilabel, 1420 ncyl, acyl, nhead, nsect); 1421 1422 label->dkl_pcyl = pcyl; 1423 label->dkl_ncyl = ncyl; 1424 label->dkl_acyl = acyl; 1425 label->dkl_nhead = nhead; 1426 label->dkl_nsect = nsect; 1427 label->dkl_apc = 0; 1428 label->dkl_intrlv = 1; 1429 label->dkl_rpm = rpm; 1430 1431 if (!build_default_partition(label, DKC_SCSI_CCS)) { 1432 goto err; 1433 } 1434 1435 (void) checksum(label, CK_MAKESUM); 1436 return (1); 1437 1438 err: 1439 if (option_msg && diag_msg) { 1440 err_print( 1441 "Configuration via format.dat geometry failed\n"); 1442 } 1443 return (0); 1444 } 1445 1446 int 1447 build_default_partition( 1448 struct dk_label *label, 1449 int ctrl_type) 1450 { 1451 int i; 1452 int ncyls[NDKMAP]; 1453 diskaddr_t nblks; 1454 int cyl; 1455 struct dk_vtoc *vtoc; 1456 struct part_table *pt; 1457 struct default_partitions *dpt; 1458 diskaddr_t capacity; 1459 int freecyls; 1460 int blks_per_cyl; 1461 int ncyl; 1462 1463 #ifdef lint 1464 ctrl_type = ctrl_type; 1465 #endif 1466 1467 /* 1468 * Install a default vtoc 1469 */ 1470 vtoc = &label->dkl_vtoc; 1471 vtoc->v_version = V_VERSION; 1472 vtoc->v_nparts = NDKMAP; 1473 vtoc->v_sanity = VTOC_SANE; 1474 1475 for (i = 0; i < NDKMAP; i++) { 1476 vtoc->v_part[i].p_tag = default_vtoc_map[i].p_tag; 1477 vtoc->v_part[i].p_flag = default_vtoc_map[i].p_flag; 1478 } 1479 1480 /* 1481 * Find a partition that matches this disk. Capacity 1482 * is in integral number of megabytes. 1483 */ 1484 capacity = ((diskaddr_t)(label->dkl_ncyl) * label->dkl_nhead * 1485 label->dkl_nsect) / (diskaddr_t)((1024 * 1024) / cur_blksz); 1486 dpt = default_partitions; 1487 for (i = 0; i < DEFAULT_PARTITION_TABLE_SIZE; i++, dpt++) { 1488 if (capacity >= dpt->min_capacity && 1489 capacity < dpt->max_capacity) { 1490 break; 1491 } 1492 } 1493 if (i == DEFAULT_PARTITION_TABLE_SIZE) { 1494 if (option_msg && diag_msg) { 1495 err_print("No matching default partition (%llu)\n", 1496 capacity); 1497 } 1498 return (0); 1499 } 1500 pt = dpt->part_table; 1501 1502 /* 1503 * Go through default partition table, finding fixed 1504 * sized entries. 1505 */ 1506 freecyls = label->dkl_ncyl; 1507 blks_per_cyl = label->dkl_nhead * label->dkl_nsect; 1508 for (i = 0; i < NDKMAP; i++) { 1509 if (pt->partitions[i] == HOG || pt->partitions[i] == 0) { 1510 ncyls[i] = 0; 1511 } else { 1512 /* 1513 * Calculate number of cylinders necessary 1514 * for specified size, rounding up to 1515 * the next greatest integral number of 1516 * cylinders. Always give what they 1517 * asked or more, never less. 1518 */ 1519 nblks = pt->partitions[i] * ((1024*1024)/cur_blksz); 1520 nblks += (blks_per_cyl - 1); 1521 ncyls[i] = nblks / blks_per_cyl; 1522 freecyls -= ncyls[i]; 1523 } 1524 } 1525 1526 if (freecyls < 0) { 1527 if (option_msg && diag_msg) { 1528 for (i = 0; i < NDKMAP; i++) { 1529 if (ncyls[i] == 0) 1530 continue; 1531 err_print("Partition %d: %u cyls\n", 1532 i, ncyls[i]); 1533 } 1534 err_print("Free cylinders exhausted (%d)\n", 1535 freecyls); 1536 } 1537 return (0); 1538 } 1539 #if defined(i386) 1540 /* 1541 * Set the default boot partition to 1 cylinder 1542 */ 1543 ncyls[8] = 1; 1544 freecyls -= 1; 1545 1546 /* 1547 * If current disk type is not a SCSI disk, 1548 * set the default alternates partition to 2 cylinders 1549 */ 1550 if (ctrl_type != DKC_SCSI_CCS) { 1551 ncyls[9] = 2; 1552 freecyls -= 2; 1553 } 1554 #endif /* defined(i386) */ 1555 1556 /* 1557 * Set the free hog partition to whatever space remains. 1558 * It's an error to have more than one HOG partition, 1559 * but we don't verify that here. 1560 */ 1561 for (i = 0; i < NDKMAP; i++) { 1562 if (pt->partitions[i] == HOG) { 1563 assert(ncyls[i] == 0); 1564 ncyls[i] = freecyls; 1565 break; 1566 } 1567 } 1568 1569 /* 1570 * Error checking 1571 */ 1572 ncyl = 0; 1573 for (i = 0; i < NDKMAP; i++) { 1574 ncyl += ncyls[i]; 1575 } 1576 assert(ncyl == (label->dkl_ncyl)); 1577 1578 /* 1579 * Finally, install the partition in the label. 1580 */ 1581 cyl = 0; 1582 1583 #if defined(_SUNOS_VTOC_16) 1584 for (i = NDKMAP/2; i < NDKMAP; i++) { 1585 if (i == 2 || ncyls[i] == 0) 1586 continue; 1587 label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl; 1588 label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl; 1589 cyl += ncyls[i]; 1590 } 1591 for (i = 0; i < NDKMAP/2; i++) { 1592 1593 #elif defined(_SUNOS_VTOC_8) 1594 for (i = 0; i < NDKMAP; i++) { 1595 1596 #else 1597 #error No VTOC format defined. 1598 #endif /* defined(_SUNOS_VTOC_16) */ 1599 1600 if (i == 2 || ncyls[i] == 0) { 1601 #if defined(_SUNOS_VTOC_8) 1602 if (i != 2) { 1603 label->dkl_map[i].dkl_cylno = 0; 1604 label->dkl_map[i].dkl_nblk = 0; 1605 } 1606 #endif 1607 continue; 1608 } 1609 #if defined(_SUNOS_VTOC_8) 1610 label->dkl_map[i].dkl_cylno = cyl; 1611 label->dkl_map[i].dkl_nblk = ncyls[i] * blks_per_cyl; 1612 #elif defined(_SUNOS_VTOC_16) 1613 label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl; 1614 label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl; 1615 1616 #else 1617 #error No VTOC format defined. 1618 #endif /* defined(_SUNOS_VTOC_8) */ 1619 1620 cyl += ncyls[i]; 1621 } 1622 1623 /* 1624 * Set the whole disk partition 1625 */ 1626 #if defined(_SUNOS_VTOC_8) 1627 label->dkl_map[2].dkl_cylno = 0; 1628 label->dkl_map[2].dkl_nblk = 1629 label->dkl_ncyl * label->dkl_nhead * label->dkl_nsect; 1630 1631 #elif defined(_SUNOS_VTOC_16) 1632 label->dkl_vtoc.v_part[2].p_start = 0; 1633 label->dkl_vtoc.v_part[2].p_size = 1634 (label->dkl_ncyl + label->dkl_acyl) * label->dkl_nhead * 1635 label->dkl_nsect; 1636 #else 1637 #error No VTOC format defined. 1638 #endif /* defined(_SUNOS_VTOC_8) */ 1639 1640 1641 if (option_msg && diag_msg) { 1642 float scaled; 1643 err_print("\n"); 1644 for (i = 0; i < NDKMAP; i++) { 1645 #if defined(_SUNOS_VTOC_8) 1646 if (label->dkl_map[i].dkl_nblk == 0) 1647 1648 #elif defined(_SUNOS_VTOC_16) 1649 if (label->dkl_vtoc.v_part[i].p_size == 0) 1650 1651 #else 1652 #error No VTOC format defined. 1653 #endif /* defined(_SUNOS_VTOC_8) */ 1654 1655 continue; 1656 err_print("Partition %d: ", i); 1657 #if defined(_SUNOS_VTOC_8) 1658 scaled = bn2mb(label->dkl_map[i].dkl_nblk); 1659 1660 #elif defined(_SUNOS_VTOC_16) 1661 1662 scaled = bn2mb(label->dkl_vtoc.v_part[i].p_size); 1663 #else 1664 #error No VTOC format defined. 1665 #endif /* defined(_SUNOS_VTOC_8) */ 1666 1667 if (scaled > 1024.0) { 1668 err_print("%6.2fGB ", scaled/1024.0); 1669 } else { 1670 err_print("%6.2fMB ", scaled); 1671 } 1672 #if defined(_SUNOS_VTOC_8) 1673 err_print(" %6d cylinders\n", 1674 label->dkl_map[i].dkl_nblk/blks_per_cyl); 1675 #elif defined(_SUNOS_VTOC_16) 1676 err_print(" %6d cylinders\n", 1677 label->dkl_vtoc.v_part[i].p_size/blks_per_cyl); 1678 #else 1679 #error No VTOC format defined. 1680 #endif /* defined(_SUNOS_VTOC_8) */ 1681 1682 } 1683 err_print("\n"); 1684 } 1685 1686 return (1); 1687 } 1688 1689 1690 1691 /* 1692 * Find an existing scsi disk definition by this name, 1693 * if possible. 1694 */ 1695 static struct disk_type * 1696 find_scsi_disk_type( 1697 char *disk_name, 1698 struct dk_label *label) 1699 { 1700 struct ctlr_type *ctlr; 1701 struct disk_type *dp; 1702 1703 ctlr = find_scsi_ctlr_type(); 1704 for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) { 1705 if (dp->dtype_asciilabel) { 1706 if ((strcmp(dp->dtype_asciilabel, disk_name) == 0) && 1707 dp->dtype_pcyl == label->dkl_pcyl && 1708 dp->dtype_ncyl == label->dkl_ncyl && 1709 dp->dtype_acyl == label->dkl_acyl && 1710 dp->dtype_nhead == label->dkl_nhead && 1711 dp->dtype_nsect == label->dkl_nsect) { 1712 return (dp); 1713 } 1714 } 1715 } 1716 1717 return ((struct disk_type *)NULL); 1718 } 1719 1720 1721 /* 1722 * Find an existing scsi disk definition by this name, 1723 * if possible. 1724 */ 1725 static struct disk_type * 1726 find_scsi_disk_by_name( 1727 char *disk_name) 1728 { 1729 struct ctlr_type *ctlr; 1730 struct disk_type *dp; 1731 1732 ctlr = find_scsi_ctlr_type(); 1733 for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) { 1734 if (dp->dtype_asciilabel) { 1735 if ((strcmp(dp->dtype_asciilabel, disk_name) == 0)) { 1736 return (dp); 1737 } 1738 } 1739 } 1740 1741 return ((struct disk_type *)NULL); 1742 } 1743 1744 1745 /* 1746 * Return a pointer to the ctlr_type structure for SCSI 1747 * disks. This list is built into the program, so there's 1748 * no chance of not being able to find it, unless someone 1749 * totally mangles the code. 1750 */ 1751 static struct ctlr_type * 1752 find_scsi_ctlr_type() 1753 { 1754 struct mctlr_list *mlp; 1755 1756 mlp = controlp; 1757 1758 while (mlp != NULL) { 1759 if (mlp->ctlr_type->ctype_ctype == DKC_SCSI_CCS) { 1760 return (mlp->ctlr_type); 1761 } 1762 mlp = mlp->next; 1763 } 1764 1765 impossible("no SCSI controller type"); 1766 1767 return ((struct ctlr_type *)NULL); 1768 } 1769 1770 1771 1772 /* 1773 * Return a pointer to the scsi ctlr_info structure. This 1774 * structure is allocated the first time format sees a 1775 * disk on this controller, so it must be present. 1776 */ 1777 static struct ctlr_info * 1778 find_scsi_ctlr_info( 1779 struct dk_cinfo *dkinfo) 1780 { 1781 struct ctlr_info *ctlr; 1782 1783 if (dkinfo->dki_ctype != DKC_SCSI_CCS) { 1784 return (NULL); 1785 } 1786 1787 for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) { 1788 if (ctlr->ctlr_addr == dkinfo->dki_addr && 1789 ctlr->ctlr_space == dkinfo->dki_space && 1790 ctlr->ctlr_ctype->ctype_ctype == DKC_SCSI_CCS) { 1791 return (ctlr); 1792 } 1793 } 1794 1795 impossible("no SCSI controller info"); 1796 1797 return ((struct ctlr_info *)NULL); 1798 } 1799 1800 1801 1802 static struct disk_type * 1803 new_scsi_disk_type( 1804 int fd, 1805 char *disk_name, 1806 struct dk_label *label) 1807 { 1808 struct disk_type *dp; 1809 struct disk_type *disk; 1810 struct ctlr_info *ctlr; 1811 struct dk_cinfo dkinfo; 1812 struct partition_info *part; 1813 struct partition_info *pt; 1814 struct disk_info *disk_info; 1815 int i; 1816 1817 /* 1818 * Get the disk controller info for this disk 1819 */ 1820 if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) { 1821 if (option_msg && diag_msg) { 1822 err_print("DKIOCINFO failed\n"); 1823 } 1824 return (NULL); 1825 } 1826 1827 /* 1828 * Find the ctlr_info for this disk. 1829 */ 1830 ctlr = find_scsi_ctlr_info(&dkinfo); 1831 1832 /* 1833 * Allocate a new disk type for the SCSI controller. 1834 */ 1835 disk = (struct disk_type *)zalloc(sizeof (struct disk_type)); 1836 1837 /* 1838 * Find the disk_info instance for this disk. 1839 */ 1840 disk_info = find_scsi_disk_info(&dkinfo); 1841 1842 /* 1843 * The controller and the disk should match. 1844 */ 1845 assert(disk_info->disk_ctlr == ctlr); 1846 1847 /* 1848 * Link the disk into the list of disks 1849 */ 1850 dp = ctlr->ctlr_ctype->ctype_dlist; 1851 if (dp == NULL) { 1852 ctlr->ctlr_ctype->ctype_dlist = disk; 1853 } else { 1854 while (dp->dtype_next != NULL) { 1855 dp = dp->dtype_next; 1856 } 1857 dp->dtype_next = disk; 1858 } 1859 disk->dtype_next = NULL; 1860 1861 /* 1862 * Allocate and initialize the disk name. 1863 */ 1864 disk->dtype_asciilabel = alloc_string(disk_name); 1865 1866 /* 1867 * Initialize disk geometry info 1868 */ 1869 disk->dtype_pcyl = label->dkl_pcyl; 1870 disk->dtype_ncyl = label->dkl_ncyl; 1871 disk->dtype_acyl = label->dkl_acyl; 1872 disk->dtype_nhead = label->dkl_nhead; 1873 disk->dtype_nsect = label->dkl_nsect; 1874 disk->dtype_rpm = label->dkl_rpm; 1875 1876 /* 1877 * Attempt to match the partition map in the label 1878 * with a know partition for this disk type. 1879 */ 1880 for (part = disk->dtype_plist; part; part = part->pinfo_next) { 1881 if (parts_match(label, part)) { 1882 break; 1883 } 1884 } 1885 1886 /* 1887 * If no match was made, we need to create a partition 1888 * map for this disk. 1889 */ 1890 if (part == NULL) { 1891 part = (struct partition_info *) 1892 zalloc(sizeof (struct partition_info)); 1893 pt = disk->dtype_plist; 1894 if (pt == NULL) { 1895 disk->dtype_plist = part; 1896 } else { 1897 while (pt->pinfo_next != NULL) { 1898 pt = pt->pinfo_next; 1899 } 1900 pt->pinfo_next = part; 1901 } 1902 part->pinfo_next = NULL; 1903 1904 /* 1905 * Set up the partition name 1906 */ 1907 part->pinfo_name = alloc_string("default"); 1908 1909 /* 1910 * Fill in the partition info from the label 1911 */ 1912 for (i = 0; i < NDKMAP; i++) { 1913 1914 #if defined(_SUNOS_VTOC_8) 1915 part->pinfo_map[i] = label->dkl_map[i]; 1916 1917 #elif defined(_SUNOS_VTOC_16) 1918 part->pinfo_map[i].dkl_cylno = 1919 label->dkl_vtoc.v_part[i].p_start / 1920 ((blkaddr32_t)(disk->dtype_nhead * 1921 disk->dtype_nsect - apc)); 1922 part->pinfo_map[i].dkl_nblk = 1923 label->dkl_vtoc.v_part[i].p_size; 1924 #else 1925 #error No VTOC format defined. 1926 #endif /* defined(_SUNOS_VTOC_8) */ 1927 1928 } 1929 } 1930 1931 1932 /* 1933 * Use the VTOC if valid, or install a default 1934 */ 1935 if (label->dkl_vtoc.v_version == V_VERSION) { 1936 (void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume, 1937 LEN_DKL_VVOL); 1938 part->vtoc = label->dkl_vtoc; 1939 } else { 1940 (void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL); 1941 set_vtoc_defaults(part); 1942 } 1943 1944 /* 1945 * Link the disk to the partition map 1946 */ 1947 disk_info->disk_parts = part; 1948 1949 return (disk); 1950 } 1951 1952 1953 /* 1954 * Delete a disk type from disk type list. 1955 */ 1956 int 1957 delete_disk_type(struct disk_type *disk_type) 1958 { 1959 struct ctlr_type *ctlr; 1960 struct disk_type *dp, *disk; 1961 1962 if (cur_ctype->ctype_ctype == DKC_DIRECT || 1963 cur_ctype->ctype_ctype == DKC_VBD || 1964 cur_ctype->ctype_ctype == DKC_BLKDEV) 1965 ctlr = find_ctlr_type(cur_ctype->ctype_ctype); 1966 else 1967 ctlr = find_scsi_ctlr_type(); 1968 if (ctlr == NULL || ctlr->ctype_dlist == NULL) { 1969 return (-1); 1970 } 1971 1972 disk = ctlr->ctype_dlist; 1973 if (disk == disk_type) { 1974 ctlr->ctype_dlist = disk->dtype_next; 1975 if (cur_label == L_TYPE_EFI) 1976 free(disk->dtype_plist->etoc); 1977 free(disk->dtype_plist); 1978 free(disk->vendor); 1979 free(disk->product); 1980 free(disk->revision); 1981 free(disk); 1982 return (0); 1983 } else { 1984 for (dp = disk->dtype_next; dp != NULL; 1985 disk = disk->dtype_next, dp = dp->dtype_next) { 1986 if (dp == disk_type) { 1987 disk->dtype_next = dp->dtype_next; 1988 if (cur_label == L_TYPE_EFI) 1989 free(dp->dtype_plist->etoc); 1990 free(dp->dtype_plist); 1991 free(dp->vendor); 1992 free(dp->product); 1993 free(dp->revision); 1994 free(dp); 1995 return (0); 1996 } 1997 } 1998 return (-1); 1999 } 2000 } 2001 2002 2003 static struct disk_info * 2004 find_scsi_disk_info( 2005 struct dk_cinfo *dkinfo) 2006 { 2007 struct disk_info *disk; 2008 struct dk_cinfo *dp; 2009 2010 for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 2011 assert(dkinfo->dki_ctype == DKC_SCSI_CCS); 2012 dp = &disk->disk_dkinfo; 2013 if (dp->dki_ctype == dkinfo->dki_ctype && 2014 dp->dki_cnum == dkinfo->dki_cnum && 2015 dp->dki_unit == dkinfo->dki_unit && 2016 strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) { 2017 return (disk); 2018 } 2019 } 2020 2021 impossible("No SCSI disk info instance\n"); 2022 2023 return ((struct disk_info *)NULL); 2024 } 2025 2026 2027 static char * 2028 get_sun_disk_name( 2029 char *disk_name, 2030 struct scsi_inquiry *inquiry) 2031 { 2032 /* 2033 * Extract the sun name of the disk 2034 */ 2035 (void) memset(disk_name, 0, DISK_NAME_MAX); 2036 (void) memcpy(disk_name, (char *)&inquiry->inq_pid[9], 7); 2037 2038 return (disk_name); 2039 } 2040 2041 2042 char * 2043 get_generic_disk_name( 2044 char *disk_name, 2045 struct scsi_inquiry *inquiry) 2046 { 2047 char *p; 2048 2049 (void) memset(disk_name, 0, DISK_NAME_MAX); 2050 p = strcopy(disk_name, inquiry->inq_vid, 2051 sizeof (inquiry->inq_vid)); 2052 *p++ = '-'; 2053 p = strcopy(p, inquiry->inq_pid, sizeof (inquiry->inq_pid)); 2054 *p++ = '-'; 2055 p = strcopy(p, inquiry->inq_revision, 2056 sizeof (inquiry->inq_revision)); 2057 2058 return (disk_name); 2059 } 2060 2061 /* 2062 * Copy a string of characters from src to dst, for at 2063 * most n bytes. Strip all leading and trailing spaces, 2064 * and stop if there are any non-printable characters. 2065 * Return ptr to the next character to be filled. 2066 */ 2067 static char * 2068 strcopy( 2069 char *dst, 2070 char *src, 2071 int n) 2072 { 2073 int i; 2074 2075 while (*src == ' ' && n > 0) { 2076 src++; 2077 n--; 2078 } 2079 2080 for (i = 0; n-- > 0 && isascii(*src) && isprint(*src); src++) { 2081 if (*src == ' ') { 2082 i++; 2083 } else { 2084 while (i-- > 0) 2085 *dst++ = ' '; 2086 *dst++ = *src; 2087 } 2088 } 2089 2090 *dst = 0; 2091 return (dst); 2092 } 2093 2094 /* 2095 * adjust disk geometry. 2096 * This is used when disk reports a disk geometry page having 2097 * no of physical cylinders is < 3 which is the minimum required 2098 * by Solaris (2 for storing labels and at least one as a data 2099 * cylinder ) 2100 */ 2101 int 2102 adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl, uint_t *nhead, 2103 uint_t *nsect) 2104 { 2105 uint_t lcyl = *cyl; 2106 uint_t lnhead = *nhead; 2107 uint_t lnsect = *nsect; 2108 2109 assert(lcyl < SUN_MIN_CYL); 2110 2111 /* 2112 * reduce nsect by 2 for each iteration and re-calculate 2113 * the number of cylinders. 2114 */ 2115 while (lnsect > MINIMUM_NO_SECTORS && 2116 lcyl < MINIMUM_NO_CYLINDERS) { 2117 /* 2118 * make sure that we do not go below MINIMUM_NO_SECTORS. 2119 */ 2120 lnsect = max(MINIMUM_NO_SECTORS, lnsect / 2); 2121 lcyl = (capacity) / (lnhead * lnsect); 2122 } 2123 /* 2124 * If the geometry still does not satisfy 2125 * MINIMUM_NO_CYLINDERS then try to reduce the 2126 * no of heads. 2127 */ 2128 while (lnhead > MINIMUM_NO_HEADS && 2129 lcyl < MINIMUM_NO_CYLINDERS) { 2130 lnhead = max(MINIMUM_NO_HEADS, lnhead / 2); 2131 lcyl = (capacity) / (lnhead * lnsect); 2132 } 2133 /* 2134 * now we should have atleast SUN_MIN_CYL cylinders. 2135 * If we still do not get SUN_MIN_CYL with MINIMUM_NO_HEADS 2136 * and MINIMUM_NO_HEADS then return error. 2137 */ 2138 if (lcyl < SUN_MIN_CYL) 2139 return (1); 2140 else { 2141 *cyl = lcyl; 2142 *nhead = lnhead; 2143 *nsect = lnsect; 2144 return (0); 2145 } 2146 } 2147 2148 #if defined(_SUNOS_VTOC_8) 2149 /* 2150 * Reduce the size of one dimention below a specified 2151 * limit with a minimum loss of volume. Dimenstions are 2152 * assumed to be passed in form the largest value (the one 2153 * that needs to be reduced) to the smallest value. The 2154 * values will be twiddled until they are all less than or 2155 * equal to their limit. Returns the number in the new geometry. 2156 */ 2157 static diskaddr_t 2158 square_box( 2159 diskaddr_t capacity, 2160 uint_t *dim1, uint_t lim1, 2161 uint_t *dim2, uint_t lim2, 2162 uint_t *dim3, uint_t lim3) 2163 { 2164 uint_t i; 2165 2166 /* 2167 * Although the routine should work with any ordering of 2168 * parameters, it's most efficient if they are passed in 2169 * in decreasing magnitude. 2170 */ 2171 assert(*dim1 >= *dim2); 2172 assert(*dim2 >= *dim3); 2173 2174 /* 2175 * This is done in a very arbitrary manner. We could try to 2176 * find better values but I can't come up with a method that 2177 * would run in a reasonable amount of time. That could take 2178 * approximately 65535 * 65535 iterations of a dozen flops each 2179 * or well over 4G flops. 2180 * 2181 * First: 2182 * 2183 * Let's see how far we can go with bitshifts w/o losing 2184 * any blocks. 2185 */ 2186 2187 for (i = 0; (((*dim1)>>i)&1) == 0 && ((*dim1)>>i) > lim1; i++) 2188 ; 2189 if (i) { 2190 *dim1 = ((*dim1)>>i); 2191 *dim3 = ((*dim3)<<i); 2192 } 2193 2194 if (((*dim1) > lim1) || ((*dim2) > lim2) || ((*dim3) > lim3)) { 2195 double d[4]; 2196 2197 /* 2198 * Second: 2199 * 2200 * Set the highest value at its limit then calculate errors, 2201 * adjusting the 2nd highest value (we get better resolution 2202 * that way). 2203 */ 2204 d[1] = lim1; 2205 d[3] = *dim3; 2206 d[2] = (double)capacity/(d[1]*d[3]); 2207 2208 /* 2209 * If we overflowed the middle term, set it to its limit and 2210 * chose a new low term. 2211 */ 2212 if (d[2] > lim2) { 2213 d[2] = lim2; 2214 d[3] = (double)capacity/(d[1]*d[2]); 2215 } 2216 /* 2217 * Convert to integers. 2218 */ 2219 *dim1 = (int)d[1]; 2220 *dim2 = (int)d[2]; 2221 *dim3 = (int)d[3]; 2222 } 2223 /* 2224 * Fixup any other possible problems. 2225 * If this happens, we need a new disklabel format. 2226 */ 2227 if (*dim1 > lim1) *dim1 = lim1; 2228 if (*dim2 > lim2) *dim2 = lim2; 2229 if (*dim3 > lim3) *dim3 = lim3; 2230 return (*dim1 * *dim2 * *dim3); 2231 } 2232 #endif /* defined(_SUNOS_VTOC_8) */ 2233 2234 /* 2235 * Calculate CHS values based on the capacity data. 2236 * 2237 * NOTE: This function is same as cmlb_convert_geomerty() function in 2238 * cmlb kernel module. 2239 */ 2240 static void 2241 compute_chs_values(diskaddr_t total_capacity, diskaddr_t usable_capacity, 2242 uint_t *pcylp, uint_t *nheadp, uint_t *nsectp) 2243 { 2244 2245 /* Unlabeled SCSI floppy device */ 2246 if (total_capacity < 160) { 2247 /* Less than 80K */ 2248 *nheadp = 1; 2249 *pcylp = total_capacity; 2250 *nsectp = 1; 2251 return; 2252 } else if (total_capacity <= 0x1000) { 2253 *nheadp = 2; 2254 *pcylp = 80; 2255 *nsectp = total_capacity / (80 * 2); 2256 return; 2257 } 2258 2259 /* 2260 * For all devices we calculate cylinders using the heads and sectors 2261 * we assign based on capacity of the device. The algorithm is 2262 * designed to be compatible with the way other operating systems 2263 * lay out fdisk tables for X86 and to insure that the cylinders never 2264 * exceed 65535 to prevent problems with X86 ioctls that report 2265 * geometry. 2266 * For some smaller disk sizes we report geometry that matches those 2267 * used by X86 BIOS usage. For larger disks, we use SPT that are 2268 * multiples of 63, since other OSes that are not limited to 16-bits 2269 * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT. 2270 * 2271 * The following table (in order) illustrates some end result 2272 * calculations: 2273 * 2274 * Maximum number of blocks nhead nsect 2275 * 2276 * 2097152 (1GB) 64 32 2277 * 16777216 (8GB) 128 32 2278 * 1052819775 (502.02GB) 255 63 2279 * 2105639550 (0.98TB) 255 126 2280 * 3158459325 (1.47TB) 255 189 2281 * 4211279100 (1.96TB) 255 252 2282 * 5264098875 (2.45TB) 255 315 2283 * ... 2284 */ 2285 2286 if (total_capacity <= 0x200000) { 2287 *nheadp = 64; 2288 *nsectp = 32; 2289 } else if (total_capacity <= 0x01000000) { 2290 *nheadp = 128; 2291 *nsectp = 32; 2292 } else { 2293 *nheadp = 255; 2294 2295 /* make nsect be smallest multiple of 63 */ 2296 *nsectp = ((total_capacity + 2297 (UINT16_MAX * 255 * 63) - 1) / 2298 (UINT16_MAX * 255 * 63)) * 63; 2299 2300 if (*nsectp == 0) 2301 *nsectp = (UINT16_MAX / 63) * 63; 2302 } 2303 2304 if (usable_capacity < total_capacity) 2305 *pcylp = usable_capacity / ((*nheadp) * (*nsectp)); 2306 else 2307 *pcylp = total_capacity / ((*nheadp) * (*nsectp)); 2308 } 2309