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