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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This module provides support for labeling operations for target 31 * drivers. 32 */ 33 34 #include <sys/scsi/scsi.h> 35 #include <sys/sunddi.h> 36 #include <sys/dklabel.h> 37 #include <sys/dkio.h> 38 #include <sys/vtoc.h> 39 #include <sys/dktp/fdisk.h> 40 #include <sys/vtrace.h> 41 #include <sys/efi_partition.h> 42 #include <sys/cmlb.h> 43 #include <sys/cmlb_impl.h> 44 45 /* 46 * Driver minor node structure and data table 47 */ 48 struct driver_minor_data { 49 char *name; 50 minor_t minor; 51 int type; 52 }; 53 54 static struct driver_minor_data dk_minor_data[] = { 55 {"a", 0, S_IFBLK}, 56 {"b", 1, S_IFBLK}, 57 {"c", 2, S_IFBLK}, 58 {"d", 3, S_IFBLK}, 59 {"e", 4, S_IFBLK}, 60 {"f", 5, S_IFBLK}, 61 {"g", 6, S_IFBLK}, 62 {"h", 7, S_IFBLK}, 63 #if defined(_SUNOS_VTOC_16) 64 {"i", 8, S_IFBLK}, 65 {"j", 9, S_IFBLK}, 66 {"k", 10, S_IFBLK}, 67 {"l", 11, S_IFBLK}, 68 {"m", 12, S_IFBLK}, 69 {"n", 13, S_IFBLK}, 70 {"o", 14, S_IFBLK}, 71 {"p", 15, S_IFBLK}, 72 #endif /* defined(_SUNOS_VTOC_16) */ 73 #if defined(_FIRMWARE_NEEDS_FDISK) 74 {"q", 16, S_IFBLK}, 75 {"r", 17, S_IFBLK}, 76 {"s", 18, S_IFBLK}, 77 {"t", 19, S_IFBLK}, 78 {"u", 20, S_IFBLK}, 79 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 80 {"a,raw", 0, S_IFCHR}, 81 {"b,raw", 1, S_IFCHR}, 82 {"c,raw", 2, S_IFCHR}, 83 {"d,raw", 3, S_IFCHR}, 84 {"e,raw", 4, S_IFCHR}, 85 {"f,raw", 5, S_IFCHR}, 86 {"g,raw", 6, S_IFCHR}, 87 {"h,raw", 7, S_IFCHR}, 88 #if defined(_SUNOS_VTOC_16) 89 {"i,raw", 8, S_IFCHR}, 90 {"j,raw", 9, S_IFCHR}, 91 {"k,raw", 10, S_IFCHR}, 92 {"l,raw", 11, S_IFCHR}, 93 {"m,raw", 12, S_IFCHR}, 94 {"n,raw", 13, S_IFCHR}, 95 {"o,raw", 14, S_IFCHR}, 96 {"p,raw", 15, S_IFCHR}, 97 #endif /* defined(_SUNOS_VTOC_16) */ 98 #if defined(_FIRMWARE_NEEDS_FDISK) 99 {"q,raw", 16, S_IFCHR}, 100 {"r,raw", 17, S_IFCHR}, 101 {"s,raw", 18, S_IFCHR}, 102 {"t,raw", 19, S_IFCHR}, 103 {"u,raw", 20, S_IFCHR}, 104 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 105 {0} 106 }; 107 108 static struct driver_minor_data dk_minor_data_efi[] = { 109 {"a", 0, S_IFBLK}, 110 {"b", 1, S_IFBLK}, 111 {"c", 2, S_IFBLK}, 112 {"d", 3, S_IFBLK}, 113 {"e", 4, S_IFBLK}, 114 {"f", 5, S_IFBLK}, 115 {"g", 6, S_IFBLK}, 116 {"wd", 7, S_IFBLK}, 117 #if defined(_FIRMWARE_NEEDS_FDISK) 118 {"q", 16, S_IFBLK}, 119 {"r", 17, S_IFBLK}, 120 {"s", 18, S_IFBLK}, 121 {"t", 19, S_IFBLK}, 122 {"u", 20, S_IFBLK}, 123 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 124 {"a,raw", 0, S_IFCHR}, 125 {"b,raw", 1, S_IFCHR}, 126 {"c,raw", 2, S_IFCHR}, 127 {"d,raw", 3, S_IFCHR}, 128 {"e,raw", 4, S_IFCHR}, 129 {"f,raw", 5, S_IFCHR}, 130 {"g,raw", 6, S_IFCHR}, 131 {"wd,raw", 7, S_IFCHR}, 132 #if defined(_FIRMWARE_NEEDS_FDISK) 133 {"q,raw", 16, S_IFCHR}, 134 {"r,raw", 17, S_IFCHR}, 135 {"s,raw", 18, S_IFCHR}, 136 {"t,raw", 19, S_IFCHR}, 137 {"u,raw", 20, S_IFCHR}, 138 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 139 {0} 140 }; 141 142 143 /* 144 * External kernel interfaces 145 */ 146 extern struct mod_ops mod_miscops; 147 148 extern int ddi_create_internal_pathname(dev_info_t *dip, char *name, 149 int spec_type, minor_t minor_num); 150 151 /* 152 * Global buffer and mutex for debug logging 153 */ 154 static char cmlb_log_buffer[1024]; 155 static kmutex_t cmlb_log_mutex; 156 157 158 struct cmlb_lun *cmlb_debug_cl = NULL; 159 uint_t cmlb_level_mask = 0x0; 160 161 int cmlb_rot_delay = 4; /* default rotational delay */ 162 163 static struct modlmisc modlmisc = { 164 &mod_miscops, /* Type of module */ 165 "Common Labeling module %I%" 166 }; 167 168 static struct modlinkage modlinkage = { 169 MODREV_1, (void *)&modlmisc, NULL 170 }; 171 172 /* Local function prototypes */ 173 static dev_t cmlb_make_device(struct cmlb_lun *cl); 174 static int cmlb_validate_geometry(struct cmlb_lun *cl, int forcerevalid, 175 int flags, void *tg_cookie); 176 static void cmlb_resync_geom_caches(struct cmlb_lun *cl, diskaddr_t capacity, 177 void *tg_cookie); 178 static int cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity, 179 void *tg_cookie); 180 static void cmlb_swap_efi_gpt(efi_gpt_t *e); 181 static void cmlb_swap_efi_gpe(int nparts, efi_gpe_t *p); 182 static int cmlb_validate_efi(efi_gpt_t *labp); 183 static int cmlb_use_efi(struct cmlb_lun *cl, diskaddr_t capacity, int flags, 184 void *tg_cookie); 185 static void cmlb_build_default_label(struct cmlb_lun *cl, void *tg_cookie); 186 static int cmlb_uselabel(struct cmlb_lun *cl, struct dk_label *l, int flags); 187 #if defined(_SUNOS_VTOC_8) 188 static void cmlb_build_user_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc); 189 #endif 190 static int cmlb_build_label_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc); 191 static int cmlb_write_label(struct cmlb_lun *cl, void *tg_cookie); 192 static int cmlb_set_vtoc(struct cmlb_lun *cl, struct dk_label *dkl, 193 void *tg_cookie); 194 static void cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie); 195 static void cmlb_clear_vtoc(struct cmlb_lun *cl, void *tg_cookie); 196 static void cmlb_setup_default_geometry(struct cmlb_lun *cl, void *tg_cookie); 197 static int cmlb_create_minor_nodes(struct cmlb_lun *cl); 198 static int cmlb_check_update_blockcount(struct cmlb_lun *cl, void *tg_cookie); 199 static int cmlb_check_efi_mbr(uchar_t *buf); 200 201 #if defined(__i386) || defined(__amd64) 202 static int cmlb_update_fdisk_and_vtoc(struct cmlb_lun *cl, void *tg_cookie); 203 #endif 204 205 #if defined(_FIRMWARE_NEEDS_FDISK) 206 static int cmlb_has_max_chs_vals(struct ipart *fdp); 207 #endif 208 209 #if defined(_SUNOS_VTOC_16) 210 static void cmlb_convert_geometry(diskaddr_t capacity, struct dk_geom *cl_g); 211 #endif 212 213 static int cmlb_dkio_get_geometry(struct cmlb_lun *cl, caddr_t arg, int flag, 214 void *tg_cookie); 215 static int cmlb_dkio_set_geometry(struct cmlb_lun *cl, caddr_t arg, int flag); 216 static int cmlb_dkio_get_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 217 void *tg_cookie); 218 static int cmlb_dkio_set_partition(struct cmlb_lun *cl, caddr_t arg, int flag); 219 static int cmlb_dkio_get_efi(struct cmlb_lun *cl, caddr_t arg, int flag, 220 void *tg_cookie); 221 static int cmlb_dkio_set_efi(struct cmlb_lun *cl, dev_t dev, caddr_t arg, 222 int flag, void *tg_cookie); 223 static int cmlb_dkio_get_vtoc(struct cmlb_lun *cl, caddr_t arg, int flag, 224 void *tg_cookie); 225 static int cmlb_dkio_set_vtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg, 226 int flag, void *tg_cookie); 227 static int cmlb_dkio_get_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, 228 void *tg_cookie); 229 static int cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, 230 void *tg_cookie); 231 static int cmlb_dkio_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 232 void *tg_cookie); 233 234 #if defined(__i386) || defined(__amd64) 235 static int cmlb_dkio_get_virtgeom(struct cmlb_lun *cl, caddr_t arg, int flag); 236 static int cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t arg, int flag); 237 static int cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, 238 int flag); 239 #endif 240 241 static void cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...); 242 static void cmlb_v_log(dev_info_t *dev, char *label, uint_t level, 243 const char *fmt, va_list ap); 244 static void cmlb_log(dev_info_t *dev, char *label, uint_t level, 245 const char *fmt, ...); 246 247 int 248 _init(void) 249 { 250 mutex_init(&cmlb_log_mutex, NULL, MUTEX_DRIVER, NULL); 251 return (mod_install(&modlinkage)); 252 } 253 254 int 255 _info(struct modinfo *modinfop) 256 { 257 return (mod_info(&modlinkage, modinfop)); 258 } 259 260 int 261 _fini(void) 262 { 263 int err; 264 265 if ((err = mod_remove(&modlinkage)) != 0) { 266 return (err); 267 } 268 269 mutex_destroy(&cmlb_log_mutex); 270 return (err); 271 } 272 273 /* 274 * cmlb_dbg is used for debugging to log additional info 275 * Level of output is controlled via cmlb_level_mask setting. 276 */ 277 static void 278 cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...) 279 { 280 va_list ap; 281 dev_info_t *dev; 282 uint_t level_mask = 0; 283 284 ASSERT(cl != NULL); 285 dev = CMLB_DEVINFO(cl); 286 ASSERT(dev != NULL); 287 /* 288 * Filter messages based on the global component and level masks, 289 * also print if cl matches the value of cmlb_debug_cl, or if 290 * cmlb_debug_cl is set to NULL. 291 */ 292 if (comp & CMLB_TRACE) 293 level_mask |= CMLB_LOGMASK_TRACE; 294 295 if (comp & CMLB_INFO) 296 level_mask |= CMLB_LOGMASK_INFO; 297 298 if (comp & CMLB_ERROR) 299 level_mask |= CMLB_LOGMASK_ERROR; 300 301 if ((cmlb_level_mask & level_mask) && 302 ((cmlb_debug_cl == NULL) || (cmlb_debug_cl == cl))) { 303 va_start(ap, fmt); 304 cmlb_v_log(dev, CMLB_LABEL(cl), CE_CONT, fmt, ap); 305 va_end(ap); 306 } 307 } 308 309 /* 310 * cmlb_log is basically a duplicate of scsi_log. It is redefined here 311 * so that this module does not depend on scsi module. 312 */ 313 static void 314 cmlb_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, ...) 315 { 316 va_list ap; 317 318 va_start(ap, fmt); 319 cmlb_v_log(dev, label, level, fmt, ap); 320 va_end(ap); 321 } 322 323 static void 324 cmlb_v_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, 325 va_list ap) 326 { 327 static char name[256]; 328 int log_only = 0; 329 int boot_only = 0; 330 int console_only = 0; 331 332 mutex_enter(&cmlb_log_mutex); 333 334 if (dev) { 335 if (level == CE_PANIC || level == CE_WARN || 336 level == CE_NOTE) { 337 (void) sprintf(name, "%s (%s%d):\n", 338 ddi_pathname(dev, cmlb_log_buffer), 339 label, ddi_get_instance(dev)); 340 } else { 341 name[0] = '\0'; 342 } 343 } else { 344 (void) sprintf(name, "%s:", label); 345 } 346 347 (void) vsprintf(cmlb_log_buffer, fmt, ap); 348 349 switch (cmlb_log_buffer[0]) { 350 case '!': 351 log_only = 1; 352 break; 353 case '?': 354 boot_only = 1; 355 break; 356 case '^': 357 console_only = 1; 358 break; 359 } 360 361 switch (level) { 362 case CE_NOTE: 363 level = CE_CONT; 364 /* FALLTHROUGH */ 365 case CE_CONT: 366 case CE_WARN: 367 case CE_PANIC: 368 if (boot_only) { 369 cmn_err(level, "?%s\t%s", name, &cmlb_log_buffer[1]); 370 } else if (console_only) { 371 cmn_err(level, "^%s\t%s", name, &cmlb_log_buffer[1]); 372 } else if (log_only) { 373 cmn_err(level, "!%s\t%s", name, &cmlb_log_buffer[1]); 374 } else { 375 cmn_err(level, "%s\t%s", name, cmlb_log_buffer); 376 } 377 break; 378 case CE_IGNORE: 379 break; 380 default: 381 cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, cmlb_log_buffer); 382 break; 383 } 384 mutex_exit(&cmlb_log_mutex); 385 } 386 387 388 /* 389 * cmlb_alloc_handle: 390 * 391 * Allocates a handle. 392 * 393 * Arguments: 394 * cmlbhandlep pointer to handle 395 * 396 * Notes: 397 * Allocates a handle and stores the allocated handle in the area 398 * pointed to by cmlbhandlep 399 * 400 * Context: 401 * Kernel thread only (can sleep). 402 */ 403 void 404 cmlb_alloc_handle(cmlb_handle_t *cmlbhandlep) 405 { 406 struct cmlb_lun *cl; 407 408 cl = kmem_zalloc(sizeof (struct cmlb_lun), KM_SLEEP); 409 ASSERT(cmlbhandlep != NULL); 410 411 cl->cl_state = CMLB_INITED; 412 cl->cl_def_labeltype = CMLB_LABEL_UNDEF; 413 mutex_init(CMLB_MUTEX(cl), NULL, MUTEX_DRIVER, NULL); 414 415 *cmlbhandlep = (cmlb_handle_t)(cl); 416 } 417 418 /* 419 * cmlb_free_handle 420 * 421 * Frees handle. 422 * 423 * Arguments: 424 * cmlbhandlep pointer to handle 425 */ 426 void 427 cmlb_free_handle(cmlb_handle_t *cmlbhandlep) 428 { 429 struct cmlb_lun *cl; 430 431 cl = (struct cmlb_lun *)*cmlbhandlep; 432 if (cl != NULL) { 433 mutex_destroy(CMLB_MUTEX(cl)); 434 kmem_free(cl, sizeof (struct cmlb_lun)); 435 } 436 437 } 438 439 /* 440 * cmlb_attach: 441 * 442 * Attach handle to device, create minor nodes for device. 443 * 444 * Arguments: 445 * devi pointer to device's dev_info structure. 446 * tgopsp pointer to array of functions cmlb can use to callback 447 * to target driver. 448 * 449 * device_type Peripheral device type as defined in 450 * scsi/generic/inquiry.h 451 * 452 * is_removable whether or not device is removable. 453 * 0 non-removable, 1 removable. 454 * 455 * is_hotpluggable whether or not device is hotpluggable. 456 * 0 non-hotpluggable, 1 hotpluggable. 457 * 458 * node_type minor node type (as used by ddi_create_minor_node) 459 * 460 * alter_behavior 461 * bit flags: 462 * 463 * CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT: create 464 * an alternate slice for the default label, if 465 * device type is DTYPE_DIRECT an architectures default 466 * label type is VTOC16. 467 * Otherwise alternate slice will no be created. 468 * 469 * 470 * CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8: report a default 471 * geometry and label for DKIOCGGEOM and DKIOCGVTOC 472 * on architecture with VTOC8 label types. 473 * 474 * CMLB_OFF_BY_ONE: do the workaround for legacy off-by- 475 * one bug in obtaining capacity (in sd): 476 * SCSI READ_CAPACITY command returns the LBA number of the 477 * last logical block, but sd once treated this number as 478 * disks' capacity on x86 platform. And LBAs are addressed 479 * based 0. So the last block was lost on x86 platform. 480 * 481 * Now, we remove this workaround. In order for present sd 482 * driver to work with disks which are labeled/partitioned 483 * via previous sd, we add workaround as follows: 484 * 485 * 1) Locate backup EFI label: cmlb searches the next to 486 * last 487 * block for backup EFI label. If fails, it will 488 * turn to the last block for backup EFI label; 489 * 490 * 2) Clear backup EFI label: cmlb first search the last 491 * block for backup EFI label, and will search the 492 * next to last block only if failed for the last 493 * block. 494 * 495 * 3) Calculate geometry:refer to cmlb_convert_geometry() 496 * If capacity increasing by 1 causes disks' capacity 497 * to cross over the limits in table CHS_values, 498 * geometry info will change. This will raise an issue: 499 * In case that primary VTOC label is destroyed, format 500 * commandline can restore it via backup VTOC labels. 501 * And format locates backup VTOC labels by use of 502 * geometry. So changing geometry will 503 * prevent format from finding backup VTOC labels. To 504 * eliminate this side effect for compatibility, 505 * sd uses (capacity -1) to calculate geometry; 506 * 507 * 4) 1TB disks: some important data structures use 508 * 32-bit signed long/int (for example, daddr_t), 509 * so that sd doesn't support a disk with capacity 510 * larger than 1TB on 32-bit platform. However, 511 * for exactly 1TB disk, it was treated as (1T - 512)B 512 * in the past, and could have valid Solaris 513 * partitions. To workaround this, if an exactly 1TB 514 * disk has Solaris fdisk partition, it will be allowed 515 * to work with sd. 516 * 517 * 518 * 519 * CMLB_FAKE_LABEL_ONE_PARTITION: create s0 and s2 covering 520 * the entire disk, if there is no valid partition info. 521 * If there is a valid Solaris partition, s0 and s2 will 522 * only cover the entire Solaris partition. 523 * 524 * 525 * cmlbhandle cmlb handle associated with device 526 * 527 * tg_cookie cookie from target driver to be passed back to target 528 * driver when we call back to it through tg_ops. 529 * 530 * Notes: 531 * Assumes a default label based on capacity for non-removable devices. 532 * If capacity > 1TB, EFI is assumed otherwise VTOC (default VTOC 533 * for the architecture). 534 * 535 * For removable devices, default label type is assumed to be VTOC 536 * type. Create minor nodes based on a default label type. 537 * Label on the media is not validated. 538 * minor number consists of: 539 * if _SUNOS_VTOC_8 is defined 540 * lowest 3 bits is taken as partition number 541 * the rest is instance number 542 * if _SUNOS_VTOC_16 is defined 543 * lowest 6 bits is taken as partition number 544 * the rest is instance number 545 * 546 * 547 * Return values: 548 * 0 Success 549 * ENXIO creating minor nodes failed. 550 * EINVAL invalid arg, unsupported tg_ops version 551 */ 552 int 553 cmlb_attach(dev_info_t *devi, cmlb_tg_ops_t *tgopsp, int device_type, 554 int is_removable, int is_hotpluggable, char *node_type, 555 int alter_behavior, cmlb_handle_t cmlbhandle, void *tg_cookie) 556 { 557 558 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 559 diskaddr_t cap; 560 int status; 561 562 if (tgopsp->tg_version < TG_DK_OPS_VERSION_1) 563 return (EINVAL); 564 565 mutex_enter(CMLB_MUTEX(cl)); 566 567 CMLB_DEVINFO(cl) = devi; 568 cl->cmlb_tg_ops = tgopsp; 569 cl->cl_device_type = device_type; 570 cl->cl_is_removable = is_removable; 571 cl->cl_is_hotpluggable = is_hotpluggable; 572 cl->cl_node_type = node_type; 573 cl->cl_sys_blocksize = DEV_BSIZE; 574 cl->cl_f_geometry_is_valid = FALSE; 575 cl->cl_def_labeltype = CMLB_LABEL_VTOC; 576 cl->cl_alter_behavior = alter_behavior; 577 cl->cl_reserved = -1; 578 579 if (is_removable != 0) { 580 mutex_exit(CMLB_MUTEX(cl)); 581 status = DK_TG_GETCAP(cl, &cap, tg_cookie); 582 mutex_enter(CMLB_MUTEX(cl)); 583 if (status == 0 && cap > DK_MAX_BLOCKS) { 584 /* set default EFI if > 1TB */ 585 cl->cl_def_labeltype = CMLB_LABEL_EFI; 586 } 587 } 588 589 /* create minor nodes based on default label type */ 590 cl->cl_last_labeltype = CMLB_LABEL_UNDEF; 591 cl->cl_cur_labeltype = CMLB_LABEL_UNDEF; 592 593 if (cmlb_create_minor_nodes(cl) != 0) { 594 mutex_exit(CMLB_MUTEX(cl)); 595 return (ENXIO); 596 } 597 598 cl->cl_state = CMLB_ATTACHED; 599 600 mutex_exit(CMLB_MUTEX(cl)); 601 return (0); 602 } 603 604 /* 605 * cmlb_detach: 606 * 607 * Invalidate in-core labeling data and remove all minor nodes for 608 * the device associate with handle. 609 * 610 * Arguments: 611 * cmlbhandle cmlb handle associated with device. 612 * 613 * tg_cookie cookie from target driver to be passed back to target 614 * driver when we call back to it through tg_ops. 615 * 616 */ 617 /*ARGSUSED1*/ 618 void 619 cmlb_detach(cmlb_handle_t cmlbhandle, void *tg_cookie) 620 { 621 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 622 623 mutex_enter(CMLB_MUTEX(cl)); 624 cl->cl_def_labeltype = CMLB_LABEL_UNDEF; 625 cl->cl_f_geometry_is_valid = FALSE; 626 ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL); 627 cl->cl_state = CMLB_INITED; 628 mutex_exit(CMLB_MUTEX(cl)); 629 } 630 631 /* 632 * cmlb_validate: 633 * 634 * Validates label. 635 * 636 * Arguments 637 * cmlbhandle cmlb handle associated with device. 638 * 639 * flags operation flags. used for verbosity control 640 * 641 * tg_cookie cookie from target driver to be passed back to target 642 * driver when we call back to it through tg_ops. 643 * 644 * 645 * Notes: 646 * If new label type is different from the current, adjust minor nodes 647 * accordingly. 648 * 649 * Return values: 650 * 0 success 651 * Note: having fdisk but no solaris partition is assumed 652 * success. 653 * 654 * ENOMEM memory allocation failed 655 * EIO i/o errors during read or get capacity 656 * EACCESS reservation conflicts 657 * EINVAL label was corrupt, or no default label was assumed 658 * ENXIO invalid handle 659 */ 660 int 661 cmlb_validate(cmlb_handle_t cmlbhandle, int flags, void *tg_cookie) 662 { 663 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 664 int rval; 665 int ret = 0; 666 667 /* 668 * Temp work-around checking cl for NULL since there is a bug 669 * in sd_detach calling this routine from taskq_dispatch 670 * inited function. 671 */ 672 if (cl == NULL) 673 return (ENXIO); 674 675 mutex_enter(CMLB_MUTEX(cl)); 676 if (cl->cl_state < CMLB_ATTACHED) { 677 mutex_exit(CMLB_MUTEX(cl)); 678 return (ENXIO); 679 } 680 681 rval = cmlb_validate_geometry((struct cmlb_lun *)cmlbhandle, 1, 682 flags, tg_cookie); 683 684 if (rval == ENOTSUP) { 685 if (cl->cl_f_geometry_is_valid == TRUE) { 686 cl->cl_cur_labeltype = CMLB_LABEL_EFI; 687 ret = 0; 688 } else { 689 ret = EINVAL; 690 } 691 } else { 692 ret = rval; 693 if (ret == 0) 694 cl->cl_cur_labeltype = CMLB_LABEL_VTOC; 695 } 696 697 if (ret == 0) 698 (void) cmlb_create_minor_nodes(cl); 699 700 mutex_exit(CMLB_MUTEX(cl)); 701 return (ret); 702 } 703 704 /* 705 * cmlb_invalidate: 706 * Invalidate in core label data 707 * 708 * Arguments: 709 * cmlbhandle cmlb handle associated with device. 710 * tg_cookie cookie from target driver to be passed back to target 711 * driver when we call back to it through tg_ops. 712 */ 713 /*ARGSUSED1*/ 714 void 715 cmlb_invalidate(cmlb_handle_t cmlbhandle, void *tg_cookie) 716 { 717 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 718 719 if (cl == NULL) 720 return; 721 722 mutex_enter(CMLB_MUTEX(cl)); 723 cl->cl_f_geometry_is_valid = FALSE; 724 mutex_exit(CMLB_MUTEX(cl)); 725 } 726 727 /* 728 * cmlb_is_valid 729 * Get status on whether the incore label/geom data is valid 730 * 731 * Arguments: 732 * cmlbhandle cmlb handle associated with device. 733 * 734 * Return values: 735 * TRUE if incore label/geom data is valid. 736 * FALSE otherwise. 737 * 738 */ 739 740 741 int 742 cmlb_is_valid(cmlb_handle_t cmlbhandle) 743 { 744 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 745 746 if (cmlbhandle == NULL) 747 return (FALSE); 748 749 return (cl->cl_f_geometry_is_valid); 750 751 } 752 753 754 755 /* 756 * cmlb_close: 757 * 758 * Close the device, revert to a default label minor node for the device, 759 * if it is removable. 760 * 761 * Arguments: 762 * cmlbhandle cmlb handle associated with device. 763 * 764 * tg_cookie cookie from target driver to be passed back to target 765 * driver when we call back to it through tg_ops. 766 * Return values: 767 * 0 Success 768 * ENXIO Re-creating minor node failed. 769 */ 770 /*ARGSUSED1*/ 771 int 772 cmlb_close(cmlb_handle_t cmlbhandle, void *tg_cookie) 773 { 774 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 775 776 mutex_enter(CMLB_MUTEX(cl)); 777 cl->cl_f_geometry_is_valid = FALSE; 778 779 /* revert to default minor node for this device */ 780 if (ISREMOVABLE(cl)) { 781 cl->cl_cur_labeltype = CMLB_LABEL_UNDEF; 782 (void) cmlb_create_minor_nodes(cl); 783 } 784 785 mutex_exit(CMLB_MUTEX(cl)); 786 return (0); 787 } 788 789 /* 790 * cmlb_get_devid_block: 791 * get the block number where device id is stored. 792 * 793 * Arguments: 794 * cmlbhandle cmlb handle associated with device. 795 * devidblockp pointer to block number. 796 * tg_cookie cookie from target driver to be passed back to target 797 * driver when we call back to it through tg_ops. 798 * 799 * Notes: 800 * It stores the block number of device id in the area pointed to 801 * by devidblockp. 802 * with the block number of device id. 803 * 804 * Return values: 805 * 0 success 806 * EINVAL device id does not apply to current label type. 807 */ 808 /*ARGSUSED2*/ 809 int 810 cmlb_get_devid_block(cmlb_handle_t cmlbhandle, diskaddr_t *devidblockp, 811 void *tg_cookie) 812 { 813 daddr_t spc, blk, head, cyl; 814 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 815 816 mutex_enter(CMLB_MUTEX(cl)); 817 if (cl->cl_state < CMLB_ATTACHED) { 818 mutex_exit(CMLB_MUTEX(cl)); 819 return (EINVAL); 820 } 821 822 if ((cl->cl_f_geometry_is_valid == FALSE) || 823 (cl->cl_solaris_size < DK_LABEL_LOC)) { 824 mutex_exit(CMLB_MUTEX(cl)); 825 return (EINVAL); 826 } 827 828 829 if (cl->cl_cur_labeltype == CMLB_LABEL_EFI) { 830 if (cl->cl_reserved != -1) { 831 blk = cl->cl_map[cl->cl_reserved].dkl_cylno; 832 } else { 833 mutex_exit(CMLB_MUTEX(cl)); 834 return (EINVAL); 835 } 836 } else { 837 /* this geometry doesn't allow us to write a devid */ 838 if (cl->cl_g.dkg_acyl < 2) { 839 mutex_exit(CMLB_MUTEX(cl)); 840 return (EINVAL); 841 } 842 843 /* 844 * Subtract 2 guarantees that the next to last cylinder 845 * is used 846 */ 847 cyl = cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl - 2; 848 spc = cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 849 head = cl->cl_g.dkg_nhead - 1; 850 blk = (cyl * (spc - cl->cl_g.dkg_apc)) + 851 (head * cl->cl_g.dkg_nsect) + 1; 852 } 853 854 *devidblockp = blk; 855 mutex_exit(CMLB_MUTEX(cl)); 856 return (0); 857 } 858 859 /* 860 * cmlb_partinfo: 861 * Get partition info for specified partition number. 862 * 863 * Arguments: 864 * cmlbhandle cmlb handle associated with device. 865 * part partition number 866 * nblocksp pointer to number of blocks 867 * startblockp pointer to starting block 868 * partnamep pointer to name of partition 869 * tagp pointer to tag info 870 * tg_cookie cookie from target driver to be passed back to target 871 * driver when we call back to it through tg_ops. 872 * 873 * 874 * Notes: 875 * If in-core label is not valid, this functions tries to revalidate 876 * the label. If label is valid, it stores the total number of blocks 877 * in this partition in the area pointed to by nblocksp, starting 878 * block number in area pointed to by startblockp, pointer to partition 879 * name in area pointed to by partnamep, and tag value in area 880 * pointed by tagp. 881 * For EFI labels, tag value will be set to 0. 882 * 883 * For all nblocksp, startblockp and partnamep, tagp, a value of NULL 884 * indicates the corresponding info is not requested. 885 * 886 * 887 * Return values: 888 * 0 success 889 * EINVAL no valid label or requested partition number is invalid. 890 * 891 */ 892 int 893 cmlb_partinfo(cmlb_handle_t cmlbhandle, int part, diskaddr_t *nblocksp, 894 diskaddr_t *startblockp, char **partnamep, uint16_t *tagp, void *tg_cookie) 895 { 896 897 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 898 int rval; 899 900 ASSERT(cl != NULL); 901 mutex_enter(CMLB_MUTEX(cl)); 902 if (cl->cl_state < CMLB_ATTACHED) { 903 mutex_exit(CMLB_MUTEX(cl)); 904 return (EINVAL); 905 } 906 907 if (part < 0 || part >= MAXPART) { 908 rval = EINVAL; 909 } else { 910 if (cl->cl_f_geometry_is_valid == FALSE) 911 (void) cmlb_validate_geometry((struct cmlb_lun *)cl, 0, 912 0, tg_cookie); 913 914 if ((cl->cl_f_geometry_is_valid == FALSE) || 915 (part < NDKMAP && cl->cl_solaris_size == 0)) { 916 rval = EINVAL; 917 } else { 918 if (startblockp != NULL) 919 *startblockp = (diskaddr_t)cl->cl_offset[part]; 920 921 if (nblocksp != NULL) 922 *nblocksp = (diskaddr_t) 923 cl->cl_map[part].dkl_nblk; 924 925 if (tagp != NULL) 926 if (cl->cl_cur_labeltype == CMLB_LABEL_EFI) 927 *tagp = V_UNASSIGNED; 928 else 929 *tagp = cl->cl_vtoc.v_part[part].p_tag; 930 rval = 0; 931 } 932 933 /* consistent with behavior of sd for getting minor name */ 934 if (partnamep != NULL) 935 *partnamep = dk_minor_data[part].name; 936 937 } 938 939 mutex_exit(CMLB_MUTEX(cl)); 940 return (rval); 941 } 942 943 /* Caller should make sure Test Unit Ready succeeds before calling this. */ 944 /*ARGSUSED*/ 945 int 946 cmlb_ioctl(cmlb_handle_t cmlbhandle, dev_t dev, int cmd, intptr_t arg, 947 int flag, cred_t *cred_p, int *rval_p, void *tg_cookie) 948 { 949 950 int err; 951 struct cmlb_lun *cl; 952 int status; 953 954 cl = (struct cmlb_lun *)cmlbhandle; 955 956 ASSERT(cl != NULL); 957 958 mutex_enter(CMLB_MUTEX(cl)); 959 if (cl->cl_state < CMLB_ATTACHED) { 960 mutex_exit(CMLB_MUTEX(cl)); 961 return (EIO); 962 } 963 964 switch (cmd) { 965 case DKIOCSVTOC: 966 case DKIOCSGEOM: 967 case DKIOCSETEFI: 968 case DKIOCSMBOOT: 969 break; 970 default: 971 status = cmlb_validate_geometry(cl, 1, CMLB_SILENT, 972 tg_cookie); 973 974 /* 975 * VTOC related ioctls except SVTOC/SGEOM should 976 * fail if > 1TB disk and there is not already a VTOC 977 * on the disk.i.e either EFI or blank 978 * 979 * PHYGEOM AND VIRTGEOM succeeds when disk is 980 * EFI labeled but <1TB 981 */ 982 983 if (status == ENOTSUP && 984 cl->cl_f_geometry_is_valid == FALSE) { 985 switch (cmd) { 986 case DKIOCGAPART: 987 case DKIOCGGEOM: 988 case DKIOCGVTOC: 989 case DKIOCSAPART: 990 case DKIOCG_PHYGEOM: 991 case DKIOCG_VIRTGEOM: 992 993 mutex_exit(CMLB_MUTEX(cl)); 994 return (ENOTSUP); 995 } 996 } else { 997 if ((cl->cl_f_geometry_is_valid == TRUE) && 998 (cl->cl_solaris_size > 0)) { 999 if (cl->cl_vtoc.v_sanity != VTOC_SANE) { 1000 /* 1001 * it is EFI, so return ENOTSUP for 1002 * these 1003 */ 1004 switch (cmd) { 1005 case DKIOCGAPART: 1006 case DKIOCGGEOM: 1007 case DKIOCGVTOC: 1008 case DKIOCSVTOC: 1009 case DKIOCSAPART: 1010 1011 mutex_exit(CMLB_MUTEX(cl)); 1012 return (ENOTSUP); 1013 } 1014 } 1015 } 1016 } 1017 } 1018 1019 mutex_exit(CMLB_MUTEX(cl)); 1020 1021 switch (cmd) { 1022 case DKIOCGGEOM: 1023 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGGEOM\n"); 1024 err = cmlb_dkio_get_geometry(cl, (caddr_t)arg, flag, tg_cookie); 1025 break; 1026 1027 case DKIOCSGEOM: 1028 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSGEOM\n"); 1029 err = cmlb_dkio_set_geometry(cl, (caddr_t)arg, flag); 1030 break; 1031 1032 case DKIOCGAPART: 1033 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGAPART\n"); 1034 err = cmlb_dkio_get_partition(cl, (caddr_t)arg, 1035 flag, tg_cookie); 1036 break; 1037 1038 case DKIOCSAPART: 1039 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSAPART\n"); 1040 err = cmlb_dkio_set_partition(cl, (caddr_t)arg, flag); 1041 break; 1042 1043 case DKIOCGVTOC: 1044 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGVTOC\n"); 1045 err = cmlb_dkio_get_vtoc(cl, (caddr_t)arg, flag, tg_cookie); 1046 break; 1047 1048 case DKIOCGETEFI: 1049 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGETEFI\n"); 1050 err = cmlb_dkio_get_efi(cl, (caddr_t)arg, flag, tg_cookie); 1051 break; 1052 1053 case DKIOCPARTITION: 1054 cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTITION\n"); 1055 err = cmlb_dkio_partition(cl, (caddr_t)arg, flag, tg_cookie); 1056 break; 1057 1058 case DKIOCSVTOC: 1059 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSVTOC\n"); 1060 err = cmlb_dkio_set_vtoc(cl, dev, (caddr_t)arg, flag, 1061 tg_cookie); 1062 break; 1063 1064 case DKIOCSETEFI: 1065 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSETEFI\n"); 1066 err = cmlb_dkio_set_efi(cl, dev, (caddr_t)arg, flag, tg_cookie); 1067 break; 1068 1069 case DKIOCGMBOOT: 1070 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGMBOOT\n"); 1071 err = cmlb_dkio_get_mboot(cl, (caddr_t)arg, flag, tg_cookie); 1072 break; 1073 1074 case DKIOCSMBOOT: 1075 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSMBOOT\n"); 1076 err = cmlb_dkio_set_mboot(cl, (caddr_t)arg, flag, tg_cookie); 1077 break; 1078 case DKIOCG_PHYGEOM: 1079 cmlb_dbg(CMLB_TRACE, cl, "DKIOCG_PHYGEOM\n"); 1080 #if defined(__i386) || defined(__amd64) 1081 err = cmlb_dkio_get_phygeom(cl, (caddr_t)arg, flag); 1082 #else 1083 err = ENOTTY; 1084 #endif 1085 break; 1086 case DKIOCG_VIRTGEOM: 1087 cmlb_dbg(CMLB_TRACE, cl, "DKIOCG_VIRTGEOM\n"); 1088 #if defined(__i386) || defined(__amd64) 1089 err = cmlb_dkio_get_virtgeom(cl, (caddr_t)arg, flag); 1090 #else 1091 err = ENOTTY; 1092 #endif 1093 break; 1094 case DKIOCPARTINFO: 1095 cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTINFO"); 1096 #if defined(__i386) || defined(__amd64) 1097 err = cmlb_dkio_partinfo(cl, dev, (caddr_t)arg, flag); 1098 #else 1099 err = ENOTTY; 1100 #endif 1101 break; 1102 1103 default: 1104 err = ENOTTY; 1105 1106 } 1107 return (err); 1108 } 1109 1110 dev_t 1111 cmlb_make_device(struct cmlb_lun *cl) 1112 { 1113 return (makedevice(ddi_name_to_major(ddi_get_name(CMLB_DEVINFO(cl))), 1114 ddi_get_instance(CMLB_DEVINFO(cl)) << CMLBUNIT_SHIFT)); 1115 } 1116 1117 /* 1118 * Function: cmlb_check_update_blockcount 1119 * 1120 * Description: If current capacity value is invalid, obtains the 1121 * current capacity from target driver. 1122 * 1123 * Return Code: 0 success 1124 * EIO failure 1125 */ 1126 static int 1127 cmlb_check_update_blockcount(struct cmlb_lun *cl, void *tg_cookie) 1128 { 1129 int status; 1130 diskaddr_t capacity; 1131 uint32_t lbasize; 1132 1133 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1134 1135 if (cl->cl_f_geometry_is_valid == FALSE) { 1136 mutex_exit(CMLB_MUTEX(cl)); 1137 status = DK_TG_GETCAP(cl, &capacity, tg_cookie); 1138 if (status != 0) { 1139 mutex_enter(CMLB_MUTEX(cl)); 1140 return (EIO); 1141 } 1142 1143 status = DK_TG_GETBLOCKSIZE(cl, &lbasize, tg_cookie); 1144 mutex_enter(CMLB_MUTEX(cl)); 1145 if (status != 0) 1146 return (EIO); 1147 1148 if ((capacity != 0) && (lbasize != 0)) { 1149 cl->cl_blockcount = capacity; 1150 cl->cl_tgt_blocksize = lbasize; 1151 return (0); 1152 } else 1153 return (EIO); 1154 } else 1155 return (0); 1156 } 1157 1158 static int 1159 cmlb_create_minor(dev_info_t *dip, char *name, int spec_type, 1160 minor_t minor_num, char *node_type, int flag, boolean_t internal) 1161 { 1162 if (internal) 1163 return (ddi_create_internal_pathname(dip, 1164 name, spec_type, minor_num)); 1165 else 1166 return (ddi_create_minor_node(dip, 1167 name, spec_type, minor_num, node_type, flag)); 1168 } 1169 1170 /* 1171 * Function: cmlb_create_minor_nodes 1172 * 1173 * Description: Create or adjust the minor device nodes for the instance. 1174 * Minor nodes are created based on default label type, 1175 * current label type and last label type we created 1176 * minor nodes based on. 1177 * 1178 * 1179 * Arguments: cl - driver soft state (unit) structure 1180 * 1181 * Return Code: 0 success 1182 * ENXIO failure. 1183 * 1184 * Context: Kernel thread context 1185 */ 1186 static int 1187 cmlb_create_minor_nodes(struct cmlb_lun *cl) 1188 { 1189 struct driver_minor_data *dmdp; 1190 int instance; 1191 char name[48]; 1192 cmlb_label_t newlabeltype; 1193 boolean_t internal; 1194 1195 ASSERT(cl != NULL); 1196 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1197 1198 internal = ((cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0); 1199 1200 /* check the most common case */ 1201 if (cl->cl_cur_labeltype != CMLB_LABEL_UNDEF && 1202 cl->cl_last_labeltype == cl->cl_cur_labeltype) { 1203 /* do nothing */ 1204 return (0); 1205 } 1206 1207 if (cl->cl_def_labeltype == CMLB_LABEL_UNDEF) { 1208 /* we should never get here */ 1209 return (ENXIO); 1210 } 1211 1212 if (cl->cl_last_labeltype == CMLB_LABEL_UNDEF) { 1213 /* first time during attach */ 1214 newlabeltype = cl->cl_def_labeltype; 1215 1216 instance = ddi_get_instance(CMLB_DEVINFO(cl)); 1217 1218 /* Create all the minor nodes for this target. */ 1219 dmdp = (newlabeltype == CMLB_LABEL_EFI) ? dk_minor_data_efi : 1220 dk_minor_data; 1221 while (dmdp->name != NULL) { 1222 1223 (void) sprintf(name, "%s", dmdp->name); 1224 1225 if (cmlb_create_minor(CMLB_DEVINFO(cl), name, 1226 dmdp->type, 1227 (instance << CMLBUNIT_SHIFT) | dmdp->minor, 1228 cl->cl_node_type, NULL, internal) == DDI_FAILURE) { 1229 /* 1230 * Clean up any nodes that may have been 1231 * created, in case this fails in the middle 1232 * of the loop. 1233 */ 1234 ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL); 1235 return (ENXIO); 1236 } 1237 dmdp++; 1238 } 1239 cl->cl_last_labeltype = newlabeltype; 1240 return (0); 1241 } 1242 1243 /* Not first time */ 1244 if (cl->cl_cur_labeltype == CMLB_LABEL_UNDEF) { 1245 if (cl->cl_last_labeltype != cl->cl_def_labeltype) { 1246 /* close time, revert to default. */ 1247 newlabeltype = cl->cl_def_labeltype; 1248 } else { 1249 /* 1250 * do nothing since the type for which we last created 1251 * nodes matches the default 1252 */ 1253 return (0); 1254 } 1255 } else { 1256 if (cl->cl_cur_labeltype != cl->cl_last_labeltype) { 1257 /* We are not closing, use current label type */ 1258 newlabeltype = cl->cl_cur_labeltype; 1259 } else { 1260 /* 1261 * do nothing since the type for which we last created 1262 * nodes matches the current label type 1263 */ 1264 return (0); 1265 } 1266 } 1267 1268 instance = ddi_get_instance(CMLB_DEVINFO(cl)); 1269 1270 /* 1271 * Currently we only fix up the s7 node when we are switching 1272 * label types from or to EFI. This is consistent with 1273 * current behavior of sd. 1274 */ 1275 if (newlabeltype == CMLB_LABEL_EFI && 1276 cl->cl_last_labeltype != CMLB_LABEL_EFI) { 1277 /* from vtoc to EFI */ 1278 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h"); 1279 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h,raw"); 1280 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd", 1281 S_IFBLK, (instance << CMLBUNIT_SHIFT) | WD_NODE, 1282 cl->cl_node_type, NULL, internal); 1283 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd,raw", 1284 S_IFCHR, (instance << CMLBUNIT_SHIFT) | WD_NODE, 1285 cl->cl_node_type, NULL, internal); 1286 } else { 1287 /* from efi to vtoc */ 1288 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd"); 1289 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd,raw"); 1290 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h", 1291 S_IFBLK, (instance << CMLBUNIT_SHIFT) | WD_NODE, 1292 cl->cl_node_type, NULL, internal); 1293 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h,raw", 1294 S_IFCHR, (instance << CMLBUNIT_SHIFT) | WD_NODE, 1295 cl->cl_node_type, NULL, internal); 1296 } 1297 1298 cl->cl_last_labeltype = newlabeltype; 1299 return (0); 1300 } 1301 1302 /* 1303 * Function: cmlb_validate_geometry 1304 * 1305 * Description: Read the label from the disk (if present). Update the unit's 1306 * geometry and vtoc information from the data in the label. 1307 * Verify that the label is valid. 1308 * 1309 * Arguments: 1310 * cl driver soft state (unit) structure 1311 * 1312 * forcerevalid force revalidation even if we are already valid. 1313 * flags operation flags from target driver. Used for verbosity 1314 * control at this time. 1315 * tg_cookie cookie from target driver to be passed back to target 1316 * driver when we call back to it through tg_ops. 1317 * 1318 * Return Code: 0 - Successful completion 1319 * EINVAL - Invalid value in cl->cl_tgt_blocksize or 1320 * cl->cl_blockcount; or label on disk is corrupted 1321 * or unreadable. 1322 * EACCES - Reservation conflict at the device. 1323 * ENOMEM - Resource allocation error 1324 * ENOTSUP - geometry not applicable 1325 * 1326 * Context: Kernel thread only (can sleep). 1327 */ 1328 static int 1329 cmlb_validate_geometry(struct cmlb_lun *cl, int forcerevalid, int flags, 1330 void *tg_cookie) 1331 { 1332 int label_error = 0; 1333 diskaddr_t capacity; 1334 int count; 1335 #if defined(__i386) || defined(__amd64) 1336 int forced_under_1t = 0; 1337 #endif 1338 1339 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1340 1341 if ((cl->cl_f_geometry_is_valid == TRUE) && (forcerevalid == 0)) { 1342 if (cl->cl_cur_labeltype == CMLB_LABEL_EFI) 1343 return (ENOTSUP); 1344 return (0); 1345 } 1346 1347 if (cmlb_check_update_blockcount(cl, tg_cookie) != 0) 1348 return (EIO); 1349 1350 capacity = cl->cl_blockcount; 1351 1352 #if defined(_SUNOS_VTOC_16) 1353 /* 1354 * Set up the "whole disk" fdisk partition; this should always 1355 * exist, regardless of whether the disk contains an fdisk table 1356 * or vtoc. 1357 */ 1358 cl->cl_map[P0_RAW_DISK].dkl_cylno = 0; 1359 /* 1360 * note if capacity > uint32_max we should be using efi, 1361 * and not use p0, so the truncation does not matter. 1362 */ 1363 cl->cl_map[P0_RAW_DISK].dkl_nblk = capacity; 1364 #endif 1365 /* 1366 * Refresh the logical and physical geometry caches. 1367 * (data from MODE SENSE format/rigid disk geometry pages, 1368 * and scsi_ifgetcap("geometry"). 1369 */ 1370 cmlb_resync_geom_caches(cl, capacity, tg_cookie); 1371 1372 label_error = cmlb_use_efi(cl, capacity, flags, tg_cookie); 1373 if (label_error == 0) { 1374 1375 /* found a valid EFI label */ 1376 cmlb_dbg(CMLB_TRACE, cl, 1377 "cmlb_validate_geometry: found EFI label\n"); 1378 /* 1379 * solaris_size and geometry_is_valid are set in 1380 * cmlb_use_efi 1381 */ 1382 return (ENOTSUP); 1383 } 1384 1385 /* NO EFI label found */ 1386 1387 if (capacity > DK_MAX_BLOCKS) { 1388 if (label_error == ESRCH) { 1389 /* 1390 * they've configured a LUN over 1TB, but used 1391 * format.dat to restrict format's view of the 1392 * capacity to be under 1TB 1393 */ 1394 /* i.e > 1Tb with a VTOC < 1TB */ 1395 if (!(flags & CMLB_SILENT)) { 1396 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 1397 CE_WARN, "is >1TB and has a VTOC label: " 1398 "use format(1M) to either decrease the"); 1399 1400 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 1401 CE_NOTE, "size to be < 1TB or relabel the " 1402 "disk with an EFI label"); 1403 #if defined(__i386) || defined(__amd64) 1404 forced_under_1t = 1; 1405 #endif 1406 } 1407 } else { 1408 /* unlabeled disk over 1TB */ 1409 #if defined(__i386) || defined(__amd64) 1410 1411 /* 1412 * Refer to comments on off-by-1 at the head of the file 1413 * A 1TB disk was treated as (1T - 512)B in the past, 1414 * thus, it might have valid solaris partition. We 1415 * will return ENOTSUP later only if this disk has no 1416 * valid solaris partition. 1417 */ 1418 if (!(cl->cl_alter_behavior & CMLB_OFF_BY_ONE) || 1419 (cl->cl_sys_blocksize != cl->cl_tgt_blocksize) || 1420 (capacity - 1 > DK_MAX_BLOCKS)) 1421 #endif 1422 return (ENOTSUP); 1423 } 1424 } 1425 1426 label_error = 0; 1427 1428 /* 1429 * at this point it is either labeled with a VTOC or it is 1430 * under 1TB (<= 1TB actually for off-by-1) 1431 */ 1432 1433 /* 1434 * Only DIRECT ACCESS devices will have Scl labels. 1435 * CD's supposedly have a Scl label, too 1436 */ 1437 if (cl->cl_device_type == DTYPE_DIRECT || ISREMOVABLE(cl)) { 1438 struct dk_label *dkl; 1439 offset_t label_addr; 1440 int rval; 1441 size_t buffer_size; 1442 1443 /* 1444 * Note: This will set up cl->cl_solaris_size and 1445 * cl->cl_solaris_offset. 1446 */ 1447 rval = cmlb_read_fdisk(cl, capacity, tg_cookie); 1448 if ((rval != 0) && !ISCD(cl)) { 1449 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1450 return (rval); 1451 } 1452 1453 if (cl->cl_solaris_size <= DK_LABEL_LOC) { 1454 1455 #if defined(__i386) || defined(__amd64) 1456 /* 1457 * Refer to comments on off-by-1 at the head of the file 1458 * This is for 1TB disk only. Since that there is no 1459 * solaris partitions, return ENOTSUP as we do for 1460 * >1TB disk. 1461 */ 1462 if (cl->cl_blockcount > DK_MAX_BLOCKS) 1463 return (ENOTSUP); 1464 #endif 1465 /* 1466 * Found fdisk table but no Solaris partition entry, 1467 * so don't call cmlb_uselabel() and don't create 1468 * a default label. 1469 */ 1470 label_error = 0; 1471 cl->cl_f_geometry_is_valid = TRUE; 1472 goto no_solaris_partition; 1473 } 1474 1475 label_addr = (daddr_t)(cl->cl_solaris_offset + DK_LABEL_LOC); 1476 1477 #if defined(__i386) || defined(__amd64) 1478 /* 1479 * Refer to comments on off-by-1 at the head of the file 1480 * Now, this 1TB disk has valid solaris partition. It 1481 * must be created by previous sd driver, we have to 1482 * treat it as (1T-512)B. 1483 */ 1484 if ((cl->cl_blockcount > DK_MAX_BLOCKS) && 1485 (forced_under_1t != 1)) { 1486 /* 1487 * Refer to cmlb_read_fdisk, when there is no 1488 * fdisk partition table, cl_solaris_size is 1489 * set to disk's capacity. In this case, we 1490 * need to adjust it 1491 */ 1492 if (cl->cl_solaris_size > DK_MAX_BLOCKS) 1493 cl->cl_solaris_size = DK_MAX_BLOCKS; 1494 cmlb_resync_geom_caches(cl, DK_MAX_BLOCKS, tg_cookie); 1495 } 1496 #endif 1497 1498 buffer_size = sizeof (struct dk_label); 1499 1500 cmlb_dbg(CMLB_TRACE, cl, "cmlb_validate_geometry: " 1501 "label_addr: 0x%x allocation size: 0x%x\n", 1502 label_addr, buffer_size); 1503 1504 if ((dkl = kmem_zalloc(buffer_size, KM_NOSLEEP)) == NULL) 1505 return (ENOMEM); 1506 1507 mutex_exit(CMLB_MUTEX(cl)); 1508 rval = DK_TG_READ(cl, dkl, label_addr, buffer_size, tg_cookie); 1509 mutex_enter(CMLB_MUTEX(cl)); 1510 1511 switch (rval) { 1512 case 0: 1513 /* 1514 * cmlb_uselabel will establish that the geometry 1515 * is valid. 1516 */ 1517 if (cmlb_uselabel(cl, 1518 (struct dk_label *)(uintptr_t)dkl, flags) != 1519 CMLB_LABEL_IS_VALID) { 1520 label_error = EINVAL; 1521 } else 1522 cl->cl_vtoc_label_is_from_media = 1; 1523 break; 1524 case EACCES: 1525 label_error = EACCES; 1526 break; 1527 default: 1528 label_error = EINVAL; 1529 break; 1530 } 1531 1532 kmem_free(dkl, buffer_size); 1533 } 1534 1535 /* 1536 * If a valid label was not found, AND if no reservation conflict 1537 * was detected, then go ahead and create a default label (4069506). 1538 * 1539 * Note: currently, for VTOC_8 devices, the default label is created 1540 * for removables and hotpluggables only. For VTOC_16 devices, the 1541 * default label will be created for all devices. 1542 * (see cmlb_build_default_label) 1543 */ 1544 #if defined(_SUNOS_VTOC_8) 1545 if ((ISREMOVABLE(cl) || ISHOTPLUGGABLE(cl)) && 1546 (label_error != EACCES)) { 1547 #elif defined(_SUNOS_VTOC_16) 1548 if (label_error != EACCES) { 1549 #endif 1550 if (cl->cl_f_geometry_is_valid == FALSE) { 1551 cmlb_build_default_label(cl, tg_cookie); 1552 } 1553 label_error = 0; 1554 } 1555 1556 no_solaris_partition: 1557 1558 #if defined(_SUNOS_VTOC_16) 1559 /* 1560 * If we have valid geometry, set up the remaining fdisk partitions. 1561 * Note that dkl_cylno is not used for the fdisk map entries, so 1562 * we set it to an entirely bogus value. 1563 */ 1564 for (count = 0; count < FD_NUMPART; count++) { 1565 cl->cl_map[FDISK_P1 + count].dkl_cylno = -1; 1566 cl->cl_map[FDISK_P1 + count].dkl_nblk = 1567 cl->cl_fmap[count].fmap_nblk; 1568 1569 cl->cl_offset[FDISK_P1 + count] = 1570 cl->cl_fmap[count].fmap_start; 1571 } 1572 #endif 1573 1574 for (count = 0; count < NDKMAP; count++) { 1575 #if defined(_SUNOS_VTOC_8) 1576 struct dk_map *lp = &cl->cl_map[count]; 1577 cl->cl_offset[count] = 1578 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 1579 #elif defined(_SUNOS_VTOC_16) 1580 struct dkl_partition *vp = &cl->cl_vtoc.v_part[count]; 1581 1582 cl->cl_offset[count] = vp->p_start + cl->cl_solaris_offset; 1583 #else 1584 #error "No VTOC format defined." 1585 #endif 1586 } 1587 1588 return (label_error); 1589 } 1590 1591 #if defined(_SUNOS_VTOC_16) 1592 /* 1593 * Macro: MAX_BLKS 1594 * 1595 * This macro is used for table entries where we need to have the largest 1596 * possible sector value for that head & SPT (sectors per track) 1597 * combination. Other entries for some smaller disk sizes are set by 1598 * convention to match those used by X86 BIOS usage. 1599 */ 1600 #define MAX_BLKS(heads, spt) UINT16_MAX * heads * spt, heads, spt 1601 1602 /* 1603 * Function: cmlb_convert_geometry 1604 * 1605 * Description: Convert physical geometry into a dk_geom structure. In 1606 * other words, make sure we don't wrap 16-bit values. 1607 * e.g. converting from geom_cache to dk_geom 1608 * 1609 * Context: Kernel thread only 1610 */ 1611 static void 1612 cmlb_convert_geometry(diskaddr_t capacity, struct dk_geom *cl_g) 1613 { 1614 int i; 1615 static const struct chs_values { 1616 uint_t max_cap; /* Max Capacity for this HS. */ 1617 uint_t nhead; /* Heads to use. */ 1618 uint_t nsect; /* SPT to use. */ 1619 } CHS_values[] = { 1620 {0x00200000, 64, 32}, /* 1GB or smaller disk. */ 1621 {0x01000000, 128, 32}, /* 8GB or smaller disk. */ 1622 {MAX_BLKS(255, 63)}, /* 502.02GB or smaller disk. */ 1623 {MAX_BLKS(255, 126)}, /* .98TB or smaller disk. */ 1624 {DK_MAX_BLOCKS, 255, 189} /* Max size is just under 1TB */ 1625 }; 1626 1627 /* Unlabeled SCSI floppy device */ 1628 if (capacity <= 0x1000) { 1629 cl_g->dkg_nhead = 2; 1630 cl_g->dkg_ncyl = 80; 1631 cl_g->dkg_nsect = capacity / (cl_g->dkg_nhead * cl_g->dkg_ncyl); 1632 return; 1633 } 1634 1635 /* 1636 * For all devices we calculate cylinders using the 1637 * heads and sectors we assign based on capacity of the 1638 * device. The table is designed to be compatible with the 1639 * way other operating systems lay out fdisk tables for X86 1640 * and to insure that the cylinders never exceed 65535 to 1641 * prevent problems with X86 ioctls that report geometry. 1642 * We use SPT that are multiples of 63, since other OSes that 1643 * are not limited to 16-bits for cylinders stop at 63 SPT 1644 * we make do by using multiples of 63 SPT. 1645 * 1646 * Note than capacities greater than or equal to 1TB will simply 1647 * get the largest geometry from the table. This should be okay 1648 * since disks this large shouldn't be using CHS values anyway. 1649 */ 1650 for (i = 0; CHS_values[i].max_cap < capacity && 1651 CHS_values[i].max_cap != DK_MAX_BLOCKS; i++) 1652 ; 1653 1654 cl_g->dkg_nhead = CHS_values[i].nhead; 1655 cl_g->dkg_nsect = CHS_values[i].nsect; 1656 } 1657 #endif 1658 1659 /* 1660 * Function: cmlb_resync_geom_caches 1661 * 1662 * Description: (Re)initialize both geometry caches: the virtual geometry 1663 * information is extracted from the HBA (the "geometry" 1664 * capability), and the physical geometry cache data is 1665 * generated by issuing MODE SENSE commands. 1666 * 1667 * Arguments: 1668 * cl driver soft state (unit) structure 1669 * capacity disk capacity in #blocks 1670 * tg_cookie cookie from target driver to be passed back to target 1671 * driver when we call back to it through tg_ops. 1672 * 1673 * Context: Kernel thread only (can sleep). 1674 */ 1675 static void 1676 cmlb_resync_geom_caches(struct cmlb_lun *cl, diskaddr_t capacity, 1677 void *tg_cookie) 1678 { 1679 struct cmlb_geom pgeom; 1680 struct cmlb_geom lgeom; 1681 struct cmlb_geom *pgeomp = &pgeom; 1682 unsigned short nhead; 1683 unsigned short nsect; 1684 int spc; 1685 int ret; 1686 1687 ASSERT(cl != NULL); 1688 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1689 1690 /* 1691 * Ask the controller for its logical geometry. 1692 * Note: if the HBA does not support scsi_ifgetcap("geometry"), 1693 * then the lgeom cache will be invalid. 1694 */ 1695 mutex_exit(CMLB_MUTEX(cl)); 1696 bzero(&lgeom, sizeof (struct cmlb_geom)); 1697 ret = DK_TG_GETVIRTGEOM(cl, &lgeom, tg_cookie); 1698 mutex_enter(CMLB_MUTEX(cl)); 1699 1700 bcopy(&lgeom, &cl->cl_lgeom, sizeof (cl->cl_lgeom)); 1701 1702 /* 1703 * Initialize the pgeom cache from lgeom, so that if MODE SENSE 1704 * doesn't work, DKIOCG_PHYSGEOM can return reasonable values. 1705 */ 1706 if (ret != 0 || cl->cl_lgeom.g_nsect == 0 || 1707 cl->cl_lgeom.g_nhead == 0) { 1708 /* 1709 * Note: Perhaps this needs to be more adaptive? The rationale 1710 * is that, if there's no HBA geometry from the HBA driver, any 1711 * guess is good, since this is the physical geometry. If MODE 1712 * SENSE fails this gives a max cylinder size for non-LBA access 1713 */ 1714 nhead = 255; 1715 nsect = 63; 1716 } else { 1717 nhead = cl->cl_lgeom.g_nhead; 1718 nsect = cl->cl_lgeom.g_nsect; 1719 } 1720 1721 if (ISCD(cl)) { 1722 pgeomp->g_nhead = 1; 1723 pgeomp->g_nsect = nsect * nhead; 1724 } else { 1725 pgeomp->g_nhead = nhead; 1726 pgeomp->g_nsect = nsect; 1727 } 1728 1729 spc = pgeomp->g_nhead * pgeomp->g_nsect; 1730 pgeomp->g_capacity = capacity; 1731 pgeomp->g_ncyl = pgeomp->g_capacity / spc; 1732 pgeomp->g_acyl = 0; 1733 1734 /* 1735 * Retrieve fresh geometry data from the hardware, stash it 1736 * here temporarily before we rebuild the incore label. 1737 * 1738 * We want to use the MODE SENSE commands to derive the 1739 * physical geometry of the device, but if either command 1740 * fails, the logical geometry is used as the fallback for 1741 * disk label geometry. 1742 */ 1743 1744 mutex_exit(CMLB_MUTEX(cl)); 1745 (void) DK_TG_GETPHYGEOM(cl, pgeomp, tg_cookie); 1746 mutex_enter(CMLB_MUTEX(cl)); 1747 1748 /* 1749 * Now update the real copy while holding the mutex. This 1750 * way the global copy is never in an inconsistent state. 1751 */ 1752 bcopy(pgeomp, &cl->cl_pgeom, sizeof (cl->cl_pgeom)); 1753 1754 cmlb_dbg(CMLB_INFO, cl, "cmlb_resync_geom_caches: " 1755 "(cached from lgeom)\n"); 1756 cmlb_dbg(CMLB_INFO, cl, 1757 " ncyl: %ld; acyl: %d; nhead: %d; nsect: %d\n", 1758 cl->cl_pgeom.g_ncyl, cl->cl_pgeom.g_acyl, 1759 cl->cl_pgeom.g_nhead, cl->cl_pgeom.g_nsect); 1760 cmlb_dbg(CMLB_INFO, cl, " lbasize: %d; capacity: %ld; " 1761 "intrlv: %d; rpm: %d\n", cl->cl_pgeom.g_secsize, 1762 cl->cl_pgeom.g_capacity, cl->cl_pgeom.g_intrlv, 1763 cl->cl_pgeom.g_rpm); 1764 } 1765 1766 1767 /* 1768 * Function: cmlb_read_fdisk 1769 * 1770 * Description: utility routine to read the fdisk table. 1771 * 1772 * Arguments: 1773 * cl driver soft state (unit) structure 1774 * capacity disk capacity in #blocks 1775 * tg_cookie cookie from target driver to be passed back to target 1776 * driver when we call back to it through tg_ops. 1777 * 1778 * Return Code: 0 for success (includes not reading for no_fdisk_present case 1779 * errnos from tg_rw if failed to read the first block. 1780 * 1781 * Context: Kernel thread only (can sleep). 1782 */ 1783 /*ARGSUSED*/ 1784 static int 1785 cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity, void *tg_cookie) 1786 { 1787 #if defined(_NO_FDISK_PRESENT) 1788 1789 cl->cl_solaris_offset = 0; 1790 cl->cl_solaris_size = capacity; 1791 bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART); 1792 return (0); 1793 1794 #elif defined(_FIRMWARE_NEEDS_FDISK) 1795 1796 struct ipart *fdp; 1797 struct mboot *mbp; 1798 struct ipart fdisk[FD_NUMPART]; 1799 int i; 1800 char sigbuf[2]; 1801 caddr_t bufp; 1802 int uidx; 1803 int rval; 1804 int lba = 0; 1805 uint_t solaris_offset; /* offset to solaris part. */ 1806 daddr_t solaris_size; /* size of solaris partition */ 1807 uint32_t blocksize; 1808 1809 ASSERT(cl != NULL); 1810 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1811 1812 /* 1813 * Start off assuming no fdisk table 1814 */ 1815 solaris_offset = 0; 1816 solaris_size = capacity; 1817 1818 blocksize = cl->cl_tgt_blocksize; 1819 1820 bufp = kmem_zalloc(blocksize, KM_SLEEP); 1821 1822 mutex_exit(CMLB_MUTEX(cl)); 1823 rval = DK_TG_READ(cl, bufp, 0, blocksize, tg_cookie); 1824 mutex_enter(CMLB_MUTEX(cl)); 1825 1826 if (rval != 0) { 1827 cmlb_dbg(CMLB_ERROR, cl, 1828 "cmlb_read_fdisk: fdisk read err\n"); 1829 bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART); 1830 goto done; 1831 } 1832 1833 mbp = (struct mboot *)bufp; 1834 1835 /* 1836 * The fdisk table does not begin on a 4-byte boundary within the 1837 * master boot record, so we copy it to an aligned structure to avoid 1838 * alignment exceptions on some processors. 1839 */ 1840 bcopy(&mbp->parts[0], fdisk, sizeof (fdisk)); 1841 1842 /* 1843 * Check for lba support before verifying sig; sig might not be 1844 * there, say on a blank disk, but the max_chs mark may still 1845 * be present. 1846 * 1847 * Note: LBA support and BEFs are an x86-only concept but this 1848 * code should work OK on SPARC as well. 1849 */ 1850 1851 /* 1852 * First, check for lba-access-ok on root node (or prom root node) 1853 * if present there, don't need to search fdisk table. 1854 */ 1855 if (ddi_getprop(DDI_DEV_T_ANY, ddi_root_node(), 0, 1856 "lba-access-ok", 0) != 0) { 1857 /* All drives do LBA; don't search fdisk table */ 1858 lba = 1; 1859 } else { 1860 /* Okay, look for mark in fdisk table */ 1861 for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { 1862 /* accumulate "lba" value from all partitions */ 1863 lba = (lba || cmlb_has_max_chs_vals(fdp)); 1864 } 1865 } 1866 1867 if (lba != 0) { 1868 dev_t dev = cmlb_make_device(cl); 1869 1870 if (ddi_getprop(dev, CMLB_DEVINFO(cl), DDI_PROP_DONTPASS, 1871 "lba-access-ok", 0) == 0) { 1872 /* not found; create it */ 1873 if (ddi_prop_create(dev, CMLB_DEVINFO(cl), 0, 1874 "lba-access-ok", (caddr_t)NULL, 0) != 1875 DDI_PROP_SUCCESS) { 1876 cmlb_dbg(CMLB_ERROR, cl, 1877 "cmlb_read_fdisk: Can't create lba " 1878 "property for instance %d\n", 1879 ddi_get_instance(CMLB_DEVINFO(cl))); 1880 } 1881 } 1882 } 1883 1884 bcopy(&mbp->signature, sigbuf, sizeof (sigbuf)); 1885 1886 /* 1887 * Endian-independent signature check 1888 */ 1889 if (((sigbuf[1] & 0xFF) != ((MBB_MAGIC >> 8) & 0xFF)) || 1890 (sigbuf[0] != (MBB_MAGIC & 0xFF))) { 1891 cmlb_dbg(CMLB_ERROR, cl, 1892 "cmlb_read_fdisk: no fdisk\n"); 1893 bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART); 1894 goto done; 1895 } 1896 1897 #ifdef CMLBDEBUG 1898 if (cmlb_level_mask & CMLB_LOGMASK_INFO) { 1899 fdp = fdisk; 1900 cmlb_dbg(CMLB_INFO, cl, "cmlb_read_fdisk:\n"); 1901 cmlb_dbg(CMLB_INFO, cl, " relsect " 1902 "numsect sysid bootid\n"); 1903 for (i = 0; i < FD_NUMPART; i++, fdp++) { 1904 cmlb_dbg(CMLB_INFO, cl, 1905 " %d: %8d %8d 0x%08x 0x%08x\n", 1906 i, fdp->relsect, fdp->numsect, 1907 fdp->systid, fdp->bootid); 1908 } 1909 } 1910 #endif 1911 1912 /* 1913 * Try to find the unix partition 1914 */ 1915 uidx = -1; 1916 solaris_offset = 0; 1917 solaris_size = 0; 1918 1919 for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { 1920 int relsect; 1921 int numsect; 1922 1923 if (fdp->numsect == 0) { 1924 cl->cl_fmap[i].fmap_start = 0; 1925 cl->cl_fmap[i].fmap_nblk = 0; 1926 continue; 1927 } 1928 1929 /* 1930 * Data in the fdisk table is little-endian. 1931 */ 1932 relsect = LE_32(fdp->relsect); 1933 numsect = LE_32(fdp->numsect); 1934 1935 cl->cl_fmap[i].fmap_start = relsect; 1936 cl->cl_fmap[i].fmap_nblk = numsect; 1937 1938 if (fdp->systid != SUNIXOS && 1939 fdp->systid != SUNIXOS2 && 1940 fdp->systid != EFI_PMBR) { 1941 continue; 1942 } 1943 1944 /* 1945 * use the last active solaris partition id found 1946 * (there should only be 1 active partition id) 1947 * 1948 * if there are no active solaris partition id 1949 * then use the first inactive solaris partition id 1950 */ 1951 if ((uidx == -1) || (fdp->bootid == ACTIVE)) { 1952 uidx = i; 1953 solaris_offset = relsect; 1954 solaris_size = numsect; 1955 } 1956 } 1957 1958 cmlb_dbg(CMLB_INFO, cl, "fdisk 0x%x 0x%lx", 1959 cl->cl_solaris_offset, cl->cl_solaris_size); 1960 done: 1961 1962 /* 1963 * Clear the VTOC info, only if the Solaris partition entry 1964 * has moved, changed size, been deleted, or if the size of 1965 * the partition is too small to even fit the label sector. 1966 */ 1967 if ((cl->cl_solaris_offset != solaris_offset) || 1968 (cl->cl_solaris_size != solaris_size) || 1969 solaris_size <= DK_LABEL_LOC) { 1970 cmlb_dbg(CMLB_INFO, cl, "fdisk moved 0x%x 0x%lx", 1971 solaris_offset, solaris_size); 1972 bzero(&cl->cl_g, sizeof (struct dk_geom)); 1973 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 1974 bzero(&cl->cl_map, NDKMAP * (sizeof (struct dk_map))); 1975 cl->cl_f_geometry_is_valid = FALSE; 1976 } 1977 cl->cl_solaris_offset = solaris_offset; 1978 cl->cl_solaris_size = solaris_size; 1979 kmem_free(bufp, blocksize); 1980 return (rval); 1981 1982 #else /* #elif defined(_FIRMWARE_NEEDS_FDISK) */ 1983 #error "fdisk table presence undetermined for this platform." 1984 #endif /* #if defined(_NO_FDISK_PRESENT) */ 1985 } 1986 1987 static void 1988 cmlb_swap_efi_gpt(efi_gpt_t *e) 1989 { 1990 _NOTE(ASSUMING_PROTECTED(*e)) 1991 e->efi_gpt_Signature = LE_64(e->efi_gpt_Signature); 1992 e->efi_gpt_Revision = LE_32(e->efi_gpt_Revision); 1993 e->efi_gpt_HeaderSize = LE_32(e->efi_gpt_HeaderSize); 1994 e->efi_gpt_HeaderCRC32 = LE_32(e->efi_gpt_HeaderCRC32); 1995 e->efi_gpt_MyLBA = LE_64(e->efi_gpt_MyLBA); 1996 e->efi_gpt_AlternateLBA = LE_64(e->efi_gpt_AlternateLBA); 1997 e->efi_gpt_FirstUsableLBA = LE_64(e->efi_gpt_FirstUsableLBA); 1998 e->efi_gpt_LastUsableLBA = LE_64(e->efi_gpt_LastUsableLBA); 1999 UUID_LE_CONVERT(e->efi_gpt_DiskGUID, e->efi_gpt_DiskGUID); 2000 e->efi_gpt_PartitionEntryLBA = LE_64(e->efi_gpt_PartitionEntryLBA); 2001 e->efi_gpt_NumberOfPartitionEntries = 2002 LE_32(e->efi_gpt_NumberOfPartitionEntries); 2003 e->efi_gpt_SizeOfPartitionEntry = 2004 LE_32(e->efi_gpt_SizeOfPartitionEntry); 2005 e->efi_gpt_PartitionEntryArrayCRC32 = 2006 LE_32(e->efi_gpt_PartitionEntryArrayCRC32); 2007 } 2008 2009 static void 2010 cmlb_swap_efi_gpe(int nparts, efi_gpe_t *p) 2011 { 2012 int i; 2013 2014 _NOTE(ASSUMING_PROTECTED(*p)) 2015 for (i = 0; i < nparts; i++) { 2016 UUID_LE_CONVERT(p[i].efi_gpe_PartitionTypeGUID, 2017 p[i].efi_gpe_PartitionTypeGUID); 2018 p[i].efi_gpe_StartingLBA = LE_64(p[i].efi_gpe_StartingLBA); 2019 p[i].efi_gpe_EndingLBA = LE_64(p[i].efi_gpe_EndingLBA); 2020 /* PartitionAttrs */ 2021 } 2022 } 2023 2024 static int 2025 cmlb_validate_efi(efi_gpt_t *labp) 2026 { 2027 if (labp->efi_gpt_Signature != EFI_SIGNATURE) 2028 return (EINVAL); 2029 /* at least 96 bytes in this version of the spec. */ 2030 if (sizeof (efi_gpt_t) - sizeof (labp->efi_gpt_Reserved2) > 2031 labp->efi_gpt_HeaderSize) 2032 return (EINVAL); 2033 /* this should be 128 bytes */ 2034 if (labp->efi_gpt_SizeOfPartitionEntry != sizeof (efi_gpe_t)) 2035 return (EINVAL); 2036 return (0); 2037 } 2038 2039 /* 2040 * This function returns FALSE if there is a valid MBR signature and no 2041 * partition table entries of type EFI_PMBR (0xEE). Otherwise it returns TRUE. 2042 * 2043 * The EFI spec (1.10 and later) requires having a Protective MBR (PMBR) to 2044 * recognize the disk as GPT partitioned. However, some other OS creates an MBR 2045 * where a PMBR entry is not the only one. Also, if the first block has been 2046 * corrupted, currently best attempt to allow data access would be to try to 2047 * check for GPT headers. Hence in case of more than one partition entry, but 2048 * at least one EFI_PMBR partition type or no valid magic number, the function 2049 * returns TRUE to continue with looking for GPT header. 2050 */ 2051 2052 static int 2053 cmlb_check_efi_mbr(uchar_t *buf) 2054 { 2055 struct ipart *fdp; 2056 struct mboot *mbp = (struct mboot *)buf; 2057 struct ipart fdisk[FD_NUMPART]; 2058 int i; 2059 2060 if (LE_16(mbp->signature) != MBB_MAGIC) 2061 return (TRUE); 2062 2063 bcopy(&mbp->parts[0], fdisk, sizeof (fdisk)); 2064 2065 for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { 2066 if (fdp->systid == EFI_PMBR) 2067 return (TRUE); 2068 } 2069 2070 return (FALSE); 2071 } 2072 2073 static int 2074 cmlb_use_efi(struct cmlb_lun *cl, diskaddr_t capacity, int flags, 2075 void *tg_cookie) 2076 { 2077 int i; 2078 int rval = 0; 2079 efi_gpe_t *partitions; 2080 uchar_t *buf; 2081 uint_t lbasize; /* is really how much to read */ 2082 diskaddr_t cap = 0; 2083 uint_t nparts; 2084 diskaddr_t gpe_lba; 2085 int iofailed = 0; 2086 struct uuid uuid_type_reserved = EFI_RESERVED; 2087 2088 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2089 2090 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) { 2091 rval = EINVAL; 2092 goto done_err1; 2093 } 2094 2095 2096 lbasize = cl->cl_sys_blocksize; 2097 2098 cl->cl_reserved = -1; 2099 mutex_exit(CMLB_MUTEX(cl)); 2100 2101 buf = kmem_zalloc(EFI_MIN_ARRAY_SIZE, KM_SLEEP); 2102 2103 rval = DK_TG_READ(cl, buf, 0, lbasize, tg_cookie); 2104 if (rval) { 2105 iofailed = 1; 2106 goto done_err; 2107 } 2108 if (((struct dk_label *)buf)->dkl_magic == DKL_MAGIC) { 2109 /* not ours */ 2110 rval = ESRCH; 2111 goto done_err; 2112 } 2113 2114 if (cmlb_check_efi_mbr(buf) == FALSE) { 2115 rval = EINVAL; 2116 goto done_err; 2117 } 2118 2119 rval = DK_TG_READ(cl, buf, 1, lbasize, tg_cookie); 2120 if (rval) { 2121 iofailed = 1; 2122 goto done_err; 2123 } 2124 cmlb_swap_efi_gpt((efi_gpt_t *)buf); 2125 2126 if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) { 2127 /* 2128 * Couldn't read the primary, try the backup. Our 2129 * capacity at this point could be based on CHS, so 2130 * check what the device reports. 2131 */ 2132 rval = DK_TG_GETCAP(cl, &cap, tg_cookie); 2133 if (rval) { 2134 iofailed = 1; 2135 goto done_err; 2136 } 2137 2138 /* 2139 * CMLB_OFF_BY_ONE case, we check the next to last block first 2140 * for backup GPT header, otherwise check the last block. 2141 */ 2142 2143 if ((rval = DK_TG_READ(cl, buf, 2144 cap - ((cl->cl_alter_behavior & CMLB_OFF_BY_ONE) ? 2 : 1), 2145 lbasize, tg_cookie)) 2146 != 0) { 2147 iofailed = 1; 2148 goto done_err; 2149 } 2150 cmlb_swap_efi_gpt((efi_gpt_t *)buf); 2151 2152 if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) { 2153 2154 if (!(cl->cl_alter_behavior & CMLB_OFF_BY_ONE)) 2155 goto done_err; 2156 if ((rval = DK_TG_READ(cl, buf, cap - 1, lbasize, 2157 tg_cookie)) != 0) 2158 goto done_err; 2159 cmlb_swap_efi_gpt((efi_gpt_t *)buf); 2160 if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) 2161 goto done_err; 2162 } 2163 if (!(flags & CMLB_SILENT)) 2164 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 2165 "primary label corrupt; using backup\n"); 2166 } 2167 2168 nparts = ((efi_gpt_t *)buf)->efi_gpt_NumberOfPartitionEntries; 2169 gpe_lba = ((efi_gpt_t *)buf)->efi_gpt_PartitionEntryLBA; 2170 2171 rval = DK_TG_READ(cl, buf, gpe_lba, EFI_MIN_ARRAY_SIZE, tg_cookie); 2172 if (rval) { 2173 iofailed = 1; 2174 goto done_err; 2175 } 2176 partitions = (efi_gpe_t *)buf; 2177 2178 if (nparts > MAXPART) { 2179 nparts = MAXPART; 2180 } 2181 cmlb_swap_efi_gpe(nparts, partitions); 2182 2183 mutex_enter(CMLB_MUTEX(cl)); 2184 2185 /* Fill in partition table. */ 2186 for (i = 0; i < nparts; i++) { 2187 if (partitions->efi_gpe_StartingLBA != 0 || 2188 partitions->efi_gpe_EndingLBA != 0) { 2189 cl->cl_map[i].dkl_cylno = 2190 partitions->efi_gpe_StartingLBA; 2191 cl->cl_map[i].dkl_nblk = 2192 partitions->efi_gpe_EndingLBA - 2193 partitions->efi_gpe_StartingLBA + 1; 2194 cl->cl_offset[i] = 2195 partitions->efi_gpe_StartingLBA; 2196 } 2197 2198 if (cl->cl_reserved == -1) { 2199 if (bcmp(&partitions->efi_gpe_PartitionTypeGUID, 2200 &uuid_type_reserved, sizeof (struct uuid)) == 0) { 2201 cl->cl_reserved = i; 2202 } 2203 } 2204 if (i == WD_NODE) { 2205 /* 2206 * minor number 7 corresponds to the whole disk 2207 */ 2208 cl->cl_map[i].dkl_cylno = 0; 2209 cl->cl_map[i].dkl_nblk = capacity; 2210 cl->cl_offset[i] = 0; 2211 } 2212 partitions++; 2213 } 2214 cl->cl_solaris_offset = 0; 2215 cl->cl_solaris_size = capacity; 2216 cl->cl_f_geometry_is_valid = TRUE; 2217 2218 /* clear the vtoc label */ 2219 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 2220 2221 kmem_free(buf, EFI_MIN_ARRAY_SIZE); 2222 return (0); 2223 2224 done_err: 2225 kmem_free(buf, EFI_MIN_ARRAY_SIZE); 2226 mutex_enter(CMLB_MUTEX(cl)); 2227 done_err1: 2228 /* 2229 * if we didn't find something that could look like a VTOC 2230 * and the disk is over 1TB, we know there isn't a valid label. 2231 * Otherwise let cmlb_uselabel decide what to do. We only 2232 * want to invalidate this if we're certain the label isn't 2233 * valid because cmlb_prop_op will now fail, which in turn 2234 * causes things like opens and stats on the partition to fail. 2235 */ 2236 if ((capacity > DK_MAX_BLOCKS) && (rval != ESRCH) && !iofailed) { 2237 cl->cl_f_geometry_is_valid = FALSE; 2238 } 2239 return (rval); 2240 } 2241 2242 2243 /* 2244 * Function: cmlb_uselabel 2245 * 2246 * Description: Validate the disk label and update the relevant data (geometry, 2247 * partition, vtoc, and capacity data) in the cmlb_lun struct. 2248 * Marks the geometry of the unit as being valid. 2249 * 2250 * Arguments: cl: unit struct. 2251 * dk_label: disk label 2252 * 2253 * Return Code: CMLB_LABEL_IS_VALID: Label read from disk is OK; geometry, 2254 * partition, vtoc, and capacity data are good. 2255 * 2256 * CMLB_LABEL_IS_INVALID: Magic number or checksum error in the 2257 * label; or computed capacity does not jibe with capacity 2258 * reported from the READ CAPACITY command. 2259 * 2260 * Context: Kernel thread only (can sleep). 2261 */ 2262 static int 2263 cmlb_uselabel(struct cmlb_lun *cl, struct dk_label *labp, int flags) 2264 { 2265 short *sp; 2266 short sum; 2267 short count; 2268 int label_error = CMLB_LABEL_IS_VALID; 2269 int i; 2270 diskaddr_t label_capacity; 2271 int part_end; 2272 diskaddr_t track_capacity; 2273 #if defined(_SUNOS_VTOC_16) 2274 struct dkl_partition *vpartp; 2275 #endif 2276 ASSERT(cl != NULL); 2277 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2278 2279 /* Validate the magic number of the label. */ 2280 if (labp->dkl_magic != DKL_MAGIC) { 2281 #if defined(__sparc) 2282 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 2283 if (!(flags & CMLB_SILENT)) 2284 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 2285 CE_WARN, 2286 "Corrupt label; wrong magic number\n"); 2287 } 2288 #endif 2289 return (CMLB_LABEL_IS_INVALID); 2290 } 2291 2292 /* Validate the checksum of the label. */ 2293 sp = (short *)labp; 2294 sum = 0; 2295 count = sizeof (struct dk_label) / sizeof (short); 2296 while (count--) { 2297 sum ^= *sp++; 2298 } 2299 2300 if (sum != 0) { 2301 #if defined(_SUNOS_VTOC_16) 2302 if (!ISCD(cl)) { 2303 #elif defined(_SUNOS_VTOC_8) 2304 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 2305 #endif 2306 if (!(flags & CMLB_SILENT)) 2307 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 2308 CE_WARN, 2309 "Corrupt label - label checksum failed\n"); 2310 } 2311 return (CMLB_LABEL_IS_INVALID); 2312 } 2313 2314 2315 /* 2316 * Fill in geometry structure with data from label. 2317 */ 2318 bzero(&cl->cl_g, sizeof (struct dk_geom)); 2319 cl->cl_g.dkg_ncyl = labp->dkl_ncyl; 2320 cl->cl_g.dkg_acyl = labp->dkl_acyl; 2321 cl->cl_g.dkg_bcyl = 0; 2322 cl->cl_g.dkg_nhead = labp->dkl_nhead; 2323 cl->cl_g.dkg_nsect = labp->dkl_nsect; 2324 cl->cl_g.dkg_intrlv = labp->dkl_intrlv; 2325 2326 #if defined(_SUNOS_VTOC_8) 2327 cl->cl_g.dkg_gap1 = labp->dkl_gap1; 2328 cl->cl_g.dkg_gap2 = labp->dkl_gap2; 2329 cl->cl_g.dkg_bhead = labp->dkl_bhead; 2330 #endif 2331 #if defined(_SUNOS_VTOC_16) 2332 cl->cl_dkg_skew = labp->dkl_skew; 2333 #endif 2334 2335 #if defined(__i386) || defined(__amd64) 2336 cl->cl_g.dkg_apc = labp->dkl_apc; 2337 #endif 2338 2339 /* 2340 * Currently we rely on the values in the label being accurate. If 2341 * dkl_rpm or dkl_pcly are zero in the label, use a default value. 2342 * 2343 * Note: In the future a MODE SENSE may be used to retrieve this data, 2344 * although this command is optional in SCSI-2. 2345 */ 2346 cl->cl_g.dkg_rpm = (labp->dkl_rpm != 0) ? labp->dkl_rpm : 3600; 2347 cl->cl_g.dkg_pcyl = (labp->dkl_pcyl != 0) ? labp->dkl_pcyl : 2348 (cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl); 2349 2350 /* 2351 * The Read and Write reinstruct values may not be valid 2352 * for older disks. 2353 */ 2354 cl->cl_g.dkg_read_reinstruct = labp->dkl_read_reinstruct; 2355 cl->cl_g.dkg_write_reinstruct = labp->dkl_write_reinstruct; 2356 2357 /* Fill in partition table. */ 2358 #if defined(_SUNOS_VTOC_8) 2359 for (i = 0; i < NDKMAP; i++) { 2360 cl->cl_map[i].dkl_cylno = labp->dkl_map[i].dkl_cylno; 2361 cl->cl_map[i].dkl_nblk = labp->dkl_map[i].dkl_nblk; 2362 } 2363 #endif 2364 #if defined(_SUNOS_VTOC_16) 2365 vpartp = labp->dkl_vtoc.v_part; 2366 track_capacity = labp->dkl_nhead * labp->dkl_nsect; 2367 2368 /* Prevent divide by zero */ 2369 if (track_capacity == 0) { 2370 if (!(flags & CMLB_SILENT)) 2371 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 2372 "Corrupt label - zero nhead or nsect value\n"); 2373 2374 return (CMLB_LABEL_IS_INVALID); 2375 } 2376 2377 for (i = 0; i < NDKMAP; i++, vpartp++) { 2378 cl->cl_map[i].dkl_cylno = vpartp->p_start / track_capacity; 2379 cl->cl_map[i].dkl_nblk = vpartp->p_size; 2380 } 2381 #endif 2382 2383 /* Fill in VTOC Structure. */ 2384 bcopy(&labp->dkl_vtoc, &cl->cl_vtoc, sizeof (struct dk_vtoc)); 2385 #if defined(_SUNOS_VTOC_8) 2386 /* 2387 * The 8-slice vtoc does not include the ascii label; save it into 2388 * the device's soft state structure here. 2389 */ 2390 bcopy(labp->dkl_asciilabel, cl->cl_asciilabel, LEN_DKL_ASCII); 2391 #endif 2392 2393 /* Now look for a valid capacity. */ 2394 track_capacity = (cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect); 2395 label_capacity = (cl->cl_g.dkg_ncyl * track_capacity); 2396 2397 if (cl->cl_g.dkg_acyl) { 2398 #if defined(__i386) || defined(__amd64) 2399 /* we may have > 1 alts cylinder */ 2400 label_capacity += (track_capacity * cl->cl_g.dkg_acyl); 2401 #else 2402 label_capacity += track_capacity; 2403 #endif 2404 } 2405 2406 /* 2407 * Force check here to ensure the computed capacity is valid. 2408 * If capacity is zero, it indicates an invalid label and 2409 * we should abort updating the relevant data then. 2410 */ 2411 if (label_capacity == 0) { 2412 if (!(flags & CMLB_SILENT)) 2413 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 2414 "Corrupt label - no valid capacity could be " 2415 "retrieved\n"); 2416 2417 return (CMLB_LABEL_IS_INVALID); 2418 } 2419 2420 /* Mark the geometry as valid. */ 2421 cl->cl_f_geometry_is_valid = TRUE; 2422 2423 /* 2424 * if we got invalidated when mutex exit and entered again, 2425 * if blockcount different than when we came in, need to 2426 * retry from beginning of cmlb_validate_geometry. 2427 * revisit this on next phase of utilizing this for 2428 * sd. 2429 */ 2430 2431 if (label_capacity <= cl->cl_blockcount) { 2432 #if defined(_SUNOS_VTOC_8) 2433 /* 2434 * We can't let this happen on drives that are subdivided 2435 * into logical disks (i.e., that have an fdisk table). 2436 * The cl_blockcount field should always hold the full media 2437 * size in sectors, period. This code would overwrite 2438 * cl_blockcount with the size of the Solaris fdisk partition. 2439 */ 2440 cmlb_dbg(CMLB_ERROR, cl, 2441 "cmlb_uselabel: Label %d blocks; Drive %d blocks\n", 2442 label_capacity, cl->cl_blockcount); 2443 cl->cl_solaris_size = label_capacity; 2444 2445 #endif /* defined(_SUNOS_VTOC_8) */ 2446 goto done; 2447 } 2448 2449 if (ISCD(cl)) { 2450 /* For CDROMs, we trust that the data in the label is OK. */ 2451 #if defined(_SUNOS_VTOC_8) 2452 for (i = 0; i < NDKMAP; i++) { 2453 part_end = labp->dkl_nhead * labp->dkl_nsect * 2454 labp->dkl_map[i].dkl_cylno + 2455 labp->dkl_map[i].dkl_nblk - 1; 2456 2457 if ((labp->dkl_map[i].dkl_nblk) && 2458 (part_end > cl->cl_blockcount)) { 2459 cl->cl_f_geometry_is_valid = FALSE; 2460 break; 2461 } 2462 } 2463 #endif 2464 #if defined(_SUNOS_VTOC_16) 2465 vpartp = &(labp->dkl_vtoc.v_part[0]); 2466 for (i = 0; i < NDKMAP; i++, vpartp++) { 2467 part_end = vpartp->p_start + vpartp->p_size; 2468 if ((vpartp->p_size > 0) && 2469 (part_end > cl->cl_blockcount)) { 2470 cl->cl_f_geometry_is_valid = FALSE; 2471 break; 2472 } 2473 } 2474 #endif 2475 } else { 2476 /* label_capacity > cl->cl_blockcount */ 2477 if (!(flags & CMLB_SILENT)) { 2478 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 2479 "Corrupt label - bad geometry\n"); 2480 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_CONT, 2481 "Label says %llu blocks; Drive says %llu blocks\n", 2482 label_capacity, cl->cl_blockcount); 2483 } 2484 cl->cl_f_geometry_is_valid = FALSE; 2485 label_error = CMLB_LABEL_IS_INVALID; 2486 } 2487 2488 done: 2489 2490 cmlb_dbg(CMLB_INFO, cl, "cmlb_uselabel: (label geometry)\n"); 2491 cmlb_dbg(CMLB_INFO, cl, 2492 " ncyl: %d; acyl: %d; nhead: %d; nsect: %d\n", 2493 cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, 2494 cl->cl_g.dkg_nhead, cl->cl_g.dkg_nsect); 2495 2496 cmlb_dbg(CMLB_INFO, cl, 2497 " label_capacity: %d; intrlv: %d; rpm: %d\n", 2498 cl->cl_blockcount, cl->cl_g.dkg_intrlv, cl->cl_g.dkg_rpm); 2499 cmlb_dbg(CMLB_INFO, cl, " wrt_reinstr: %d; rd_reinstr: %d\n", 2500 cl->cl_g.dkg_write_reinstruct, cl->cl_g.dkg_read_reinstruct); 2501 2502 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2503 2504 return (label_error); 2505 } 2506 2507 2508 /* 2509 * Function: cmlb_build_default_label 2510 * 2511 * Description: Generate a default label for those devices that do not have 2512 * one, e.g., new media, removable cartridges, etc.. 2513 * 2514 * Context: Kernel thread only 2515 */ 2516 /*ARGSUSED*/ 2517 static void 2518 cmlb_build_default_label(struct cmlb_lun *cl, void *tg_cookie) 2519 { 2520 #if defined(_SUNOS_VTOC_16) 2521 uint_t phys_spc; 2522 uint_t disksize; 2523 struct dk_geom cl_g; 2524 diskaddr_t capacity; 2525 #endif 2526 2527 ASSERT(cl != NULL); 2528 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2529 2530 #if defined(_SUNOS_VTOC_8) 2531 /* 2532 * Note: This is a legacy check for non-removable devices on VTOC_8 2533 * only. This may be a valid check for VTOC_16 as well. 2534 * Once we understand why there is this difference between SPARC and 2535 * x86 platform, we could remove this legacy check. 2536 */ 2537 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 2538 return; 2539 } 2540 #endif 2541 2542 bzero(&cl->cl_g, sizeof (struct dk_geom)); 2543 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 2544 bzero(&cl->cl_map, NDKMAP * (sizeof (struct dk_map))); 2545 2546 #if defined(_SUNOS_VTOC_8) 2547 2548 /* 2549 * It's a REMOVABLE media, therefore no label (on sparc, anyway). 2550 * But it is still necessary to set up various geometry information, 2551 * and we are doing this here. 2552 */ 2553 2554 /* 2555 * For the rpm, we use the minimum for the disk. For the head, cyl, 2556 * and number of sector per track, if the capacity <= 1GB, head = 64, 2557 * sect = 32. else head = 255, sect 63 Note: the capacity should be 2558 * equal to C*H*S values. This will cause some truncation of size due 2559 * to round off errors. For CD-ROMs, this truncation can have adverse 2560 * side effects, so returning ncyl and nhead as 1. The nsect will 2561 * overflow for most of CD-ROMs as nsect is of type ushort. (4190569) 2562 */ 2563 cl->cl_solaris_size = cl->cl_blockcount; 2564 if (ISCD(cl)) { 2565 tg_attribute_t tgattribute; 2566 int is_writable; 2567 /* 2568 * Preserve the old behavior for non-writable 2569 * medias. Since dkg_nsect is a ushort, it 2570 * will lose bits as cdroms have more than 2571 * 65536 sectors. So if we recalculate 2572 * capacity, it will become much shorter. 2573 * But the dkg_* information is not 2574 * used for CDROMs so it is OK. But for 2575 * Writable CDs we need this information 2576 * to be valid (for newfs say). So we 2577 * make nsect and nhead > 1 that way 2578 * nsect can still stay within ushort limit 2579 * without losing any bits. 2580 */ 2581 2582 bzero(&tgattribute, sizeof (tg_attribute_t)); 2583 2584 mutex_exit(CMLB_MUTEX(cl)); 2585 is_writable = 2586 (DK_TG_GETATTRIBUTE(cl, &tgattribute, tg_cookie) == 0) ? 2587 tgattribute.media_is_writable : 1; 2588 mutex_enter(CMLB_MUTEX(cl)); 2589 2590 if (is_writable) { 2591 cl->cl_g.dkg_nhead = 64; 2592 cl->cl_g.dkg_nsect = 32; 2593 cl->cl_g.dkg_ncyl = cl->cl_blockcount / (64 * 32); 2594 cl->cl_solaris_size = cl->cl_g.dkg_ncyl * 2595 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 2596 } else { 2597 cl->cl_g.dkg_ncyl = 1; 2598 cl->cl_g.dkg_nhead = 1; 2599 cl->cl_g.dkg_nsect = cl->cl_blockcount; 2600 } 2601 } else { 2602 if (cl->cl_blockcount <= 0x1000) { 2603 /* unlabeled SCSI floppy device */ 2604 cl->cl_g.dkg_nhead = 2; 2605 cl->cl_g.dkg_ncyl = 80; 2606 cl->cl_g.dkg_nsect = cl->cl_blockcount / (2 * 80); 2607 } else if (cl->cl_blockcount <= 0x200000) { 2608 cl->cl_g.dkg_nhead = 64; 2609 cl->cl_g.dkg_nsect = 32; 2610 cl->cl_g.dkg_ncyl = cl->cl_blockcount / (64 * 32); 2611 } else { 2612 cl->cl_g.dkg_nhead = 255; 2613 2614 cl->cl_g.dkg_nsect = ((cl->cl_blockcount + 2615 (UINT16_MAX * 255 * 63) - 1) / 2616 (UINT16_MAX * 255 * 63)) * 63; 2617 2618 if (cl->cl_g.dkg_nsect == 0) 2619 cl->cl_g.dkg_nsect = (UINT16_MAX / 63) * 63; 2620 2621 cl->cl_g.dkg_ncyl = cl->cl_blockcount / 2622 (255 * cl->cl_g.dkg_nsect); 2623 } 2624 2625 cl->cl_solaris_size = 2626 cl->cl_g.dkg_ncyl * cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 2627 2628 } 2629 2630 cl->cl_g.dkg_acyl = 0; 2631 cl->cl_g.dkg_bcyl = 0; 2632 cl->cl_g.dkg_rpm = 200; 2633 cl->cl_asciilabel[0] = '\0'; 2634 cl->cl_g.dkg_pcyl = cl->cl_g.dkg_ncyl; 2635 2636 cl->cl_map[0].dkl_cylno = 0; 2637 cl->cl_map[0].dkl_nblk = cl->cl_solaris_size; 2638 2639 cl->cl_map[2].dkl_cylno = 0; 2640 cl->cl_map[2].dkl_nblk = cl->cl_solaris_size; 2641 2642 #elif defined(_SUNOS_VTOC_16) 2643 2644 if (cl->cl_solaris_size == 0) { 2645 /* 2646 * Got fdisk table but no solaris entry therefore 2647 * don't create a default label 2648 */ 2649 cl->cl_f_geometry_is_valid = TRUE; 2650 return; 2651 } 2652 2653 /* 2654 * For CDs we continue to use the physical geometry to calculate 2655 * number of cylinders. All other devices must convert the 2656 * physical geometry (cmlb_geom) to values that will fit 2657 * in a dk_geom structure. 2658 */ 2659 if (ISCD(cl)) { 2660 phys_spc = cl->cl_pgeom.g_nhead * cl->cl_pgeom.g_nsect; 2661 } else { 2662 /* Convert physical geometry to disk geometry */ 2663 bzero(&cl_g, sizeof (struct dk_geom)); 2664 2665 /* 2666 * Refer to comments related to off-by-1 at the 2667 * header of this file. 2668 * Before caculating geometry, capacity should be 2669 * decreased by 1. 2670 */ 2671 2672 if (cl->cl_alter_behavior & CMLB_OFF_BY_ONE) 2673 capacity = cl->cl_blockcount - 1; 2674 else 2675 capacity = cl->cl_blockcount; 2676 2677 2678 cmlb_convert_geometry(capacity, &cl_g); 2679 bcopy(&cl_g, &cl->cl_g, sizeof (cl->cl_g)); 2680 phys_spc = cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 2681 } 2682 2683 ASSERT(phys_spc != 0); 2684 cl->cl_g.dkg_pcyl = cl->cl_solaris_size / phys_spc; 2685 if (cl->cl_alter_behavior & CMLB_FAKE_LABEL_ONE_PARTITION) { 2686 /* disable devid */ 2687 cl->cl_g.dkg_ncyl = cl->cl_g.dkg_pcyl; 2688 disksize = cl->cl_solaris_size; 2689 } else { 2690 cl->cl_g.dkg_acyl = DK_ACYL; 2691 cl->cl_g.dkg_ncyl = cl->cl_g.dkg_pcyl - DK_ACYL; 2692 disksize = cl->cl_g.dkg_ncyl * phys_spc; 2693 } 2694 2695 if (ISCD(cl)) { 2696 /* 2697 * CD's don't use the "heads * sectors * cyls"-type of 2698 * geometry, but instead use the entire capacity of the media. 2699 */ 2700 disksize = cl->cl_solaris_size; 2701 cl->cl_g.dkg_nhead = 1; 2702 cl->cl_g.dkg_nsect = 1; 2703 cl->cl_g.dkg_rpm = 2704 (cl->cl_pgeom.g_rpm == 0) ? 200 : cl->cl_pgeom.g_rpm; 2705 2706 cl->cl_vtoc.v_part[0].p_start = 0; 2707 cl->cl_vtoc.v_part[0].p_size = disksize; 2708 cl->cl_vtoc.v_part[0].p_tag = V_BACKUP; 2709 cl->cl_vtoc.v_part[0].p_flag = V_UNMNT; 2710 2711 cl->cl_map[0].dkl_cylno = 0; 2712 cl->cl_map[0].dkl_nblk = disksize; 2713 cl->cl_offset[0] = 0; 2714 2715 } else { 2716 /* 2717 * Hard disks and removable media cartridges 2718 */ 2719 cl->cl_g.dkg_rpm = 2720 (cl->cl_pgeom.g_rpm == 0) ? 3600: cl->cl_pgeom.g_rpm; 2721 cl->cl_vtoc.v_sectorsz = cl->cl_sys_blocksize; 2722 2723 /* Add boot slice */ 2724 cl->cl_vtoc.v_part[8].p_start = 0; 2725 cl->cl_vtoc.v_part[8].p_size = phys_spc; 2726 cl->cl_vtoc.v_part[8].p_tag = V_BOOT; 2727 cl->cl_vtoc.v_part[8].p_flag = V_UNMNT; 2728 2729 cl->cl_map[8].dkl_cylno = 0; 2730 cl->cl_map[8].dkl_nblk = phys_spc; 2731 cl->cl_offset[8] = 0; 2732 2733 if ((cl->cl_alter_behavior & 2734 CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT) && 2735 cl->cl_device_type == DTYPE_DIRECT) { 2736 cl->cl_vtoc.v_part[9].p_start = phys_spc; 2737 cl->cl_vtoc.v_part[9].p_size = 2 * phys_spc; 2738 cl->cl_vtoc.v_part[9].p_tag = V_ALTSCTR; 2739 cl->cl_vtoc.v_part[9].p_flag = 0; 2740 2741 cl->cl_map[9].dkl_cylno = 1; 2742 cl->cl_map[9].dkl_nblk = 2 * phys_spc; 2743 cl->cl_offset[9] = phys_spc; 2744 } 2745 } 2746 2747 cl->cl_g.dkg_apc = 0; 2748 cl->cl_vtoc.v_nparts = V_NUMPAR; 2749 cl->cl_vtoc.v_version = V_VERSION; 2750 2751 /* Add backup slice */ 2752 cl->cl_vtoc.v_part[2].p_start = 0; 2753 cl->cl_vtoc.v_part[2].p_size = disksize; 2754 cl->cl_vtoc.v_part[2].p_tag = V_BACKUP; 2755 cl->cl_vtoc.v_part[2].p_flag = V_UNMNT; 2756 2757 cl->cl_map[2].dkl_cylno = 0; 2758 cl->cl_map[2].dkl_nblk = disksize; 2759 cl->cl_offset[2] = 0; 2760 2761 /* 2762 * single slice (s0) covering the entire disk 2763 */ 2764 if (cl->cl_alter_behavior & CMLB_FAKE_LABEL_ONE_PARTITION) { 2765 cl->cl_vtoc.v_part[0].p_start = 0; 2766 cl->cl_vtoc.v_part[0].p_tag = V_UNASSIGNED; 2767 cl->cl_vtoc.v_part[0].p_flag = 0; 2768 cl->cl_vtoc.v_part[0].p_size = disksize; 2769 cl->cl_map[0].dkl_cylno = 0; 2770 cl->cl_map[0].dkl_nblk = disksize; 2771 cl->cl_offset[0] = 0; 2772 } 2773 2774 (void) sprintf(cl->cl_vtoc.v_asciilabel, "DEFAULT cyl %d alt %d" 2775 " hd %d sec %d", cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, 2776 cl->cl_g.dkg_nhead, cl->cl_g.dkg_nsect); 2777 2778 #else 2779 #error "No VTOC format defined." 2780 #endif 2781 2782 cl->cl_g.dkg_read_reinstruct = 0; 2783 cl->cl_g.dkg_write_reinstruct = 0; 2784 2785 cl->cl_g.dkg_intrlv = 1; 2786 2787 cl->cl_vtoc.v_sanity = VTOC_SANE; 2788 2789 cl->cl_f_geometry_is_valid = TRUE; 2790 cl->cl_vtoc_label_is_from_media = 0; 2791 2792 cmlb_dbg(CMLB_INFO, cl, 2793 "cmlb_build_default_label: Default label created: " 2794 "cyl: %d\tacyl: %d\tnhead: %d\tnsect: %d\tcap: %d\n", 2795 cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, cl->cl_g.dkg_nhead, 2796 cl->cl_g.dkg_nsect, cl->cl_blockcount); 2797 } 2798 2799 2800 #if defined(_FIRMWARE_NEEDS_FDISK) 2801 /* 2802 * Max CHS values, as they are encoded into bytes, for 1022/254/63 2803 */ 2804 #define LBA_MAX_SECT (63 | ((1022 & 0x300) >> 2)) 2805 #define LBA_MAX_CYL (1022 & 0xFF) 2806 #define LBA_MAX_HEAD (254) 2807 2808 2809 /* 2810 * Function: cmlb_has_max_chs_vals 2811 * 2812 * Description: Return TRUE if Cylinder-Head-Sector values are all at maximum. 2813 * 2814 * Arguments: fdp - ptr to CHS info 2815 * 2816 * Return Code: True or false 2817 * 2818 * Context: Any. 2819 */ 2820 static int 2821 cmlb_has_max_chs_vals(struct ipart *fdp) 2822 { 2823 return ((fdp->begcyl == LBA_MAX_CYL) && 2824 (fdp->beghead == LBA_MAX_HEAD) && 2825 (fdp->begsect == LBA_MAX_SECT) && 2826 (fdp->endcyl == LBA_MAX_CYL) && 2827 (fdp->endhead == LBA_MAX_HEAD) && 2828 (fdp->endsect == LBA_MAX_SECT)); 2829 } 2830 #endif 2831 2832 /* 2833 * Function: cmlb_dkio_get_geometry 2834 * 2835 * Description: This routine is the driver entry point for handling user 2836 * requests to get the device geometry (DKIOCGGEOM). 2837 * 2838 * Arguments: 2839 * arg pointer to user provided dk_geom structure specifying 2840 * the controller's notion of the current geometry. 2841 * 2842 * flag this argument is a pass through to ddi_copyxxx() 2843 * directly from the mode argument of ioctl(). 2844 * 2845 * tg_cookie cookie from target driver to be passed back to target 2846 * driver when we call back to it through tg_ops. 2847 * 2848 * Return Code: 0 2849 * EFAULT 2850 * ENXIO 2851 * EIO 2852 */ 2853 static int 2854 cmlb_dkio_get_geometry(struct cmlb_lun *cl, caddr_t arg, int flag, 2855 void *tg_cookie) 2856 { 2857 struct dk_geom *tmp_geom = NULL; 2858 int rval = 0; 2859 2860 /* 2861 * cmlb_validate_geometry does not spin a disk up 2862 * if it was spcl down. We need to make sure it 2863 * is ready. 2864 */ 2865 mutex_enter(CMLB_MUTEX(cl)); 2866 rval = cmlb_validate_geometry(cl, 1, 0, tg_cookie); 2867 #if defined(_SUNOS_VTOC_8) 2868 if (rval == EINVAL && 2869 cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8) { 2870 /* 2871 * This is to return a default label geometry even when we 2872 * do not really assume a default label for the device. 2873 * dad driver utilizes this. 2874 */ 2875 if (cl->cl_blockcount <= DK_MAX_BLOCKS) { 2876 cmlb_setup_default_geometry(cl, tg_cookie); 2877 rval = 0; 2878 } 2879 } 2880 #endif 2881 if (rval) { 2882 mutex_exit(CMLB_MUTEX(cl)); 2883 return (rval); 2884 } 2885 2886 #if defined(__i386) || defined(__amd64) 2887 if (cl->cl_solaris_size == 0) { 2888 mutex_exit(CMLB_MUTEX(cl)); 2889 return (EIO); 2890 } 2891 #endif 2892 2893 /* 2894 * Make a local copy of the soft state geometry to avoid some potential 2895 * race conditions associated with holding the mutex and updating the 2896 * write_reinstruct value 2897 */ 2898 tmp_geom = kmem_zalloc(sizeof (struct dk_geom), KM_SLEEP); 2899 bcopy(&cl->cl_g, tmp_geom, sizeof (struct dk_geom)); 2900 2901 if (tmp_geom->dkg_write_reinstruct == 0) { 2902 tmp_geom->dkg_write_reinstruct = 2903 (int)((int)(tmp_geom->dkg_nsect * tmp_geom->dkg_rpm * 2904 cmlb_rot_delay) / (int)60000); 2905 } 2906 mutex_exit(CMLB_MUTEX(cl)); 2907 2908 rval = ddi_copyout(tmp_geom, (void *)arg, sizeof (struct dk_geom), 2909 flag); 2910 if (rval != 0) { 2911 rval = EFAULT; 2912 } 2913 2914 kmem_free(tmp_geom, sizeof (struct dk_geom)); 2915 return (rval); 2916 2917 } 2918 2919 2920 /* 2921 * Function: cmlb_dkio_set_geometry 2922 * 2923 * Description: This routine is the driver entry point for handling user 2924 * requests to set the device geometry (DKIOCSGEOM). The actual 2925 * device geometry is not updated, just the driver "notion" of it. 2926 * 2927 * Arguments: 2928 * arg pointer to user provided dk_geom structure used to set 2929 * the controller's notion of the current geometry. 2930 * 2931 * flag this argument is a pass through to ddi_copyxxx() 2932 * directly from the mode argument of ioctl(). 2933 * 2934 * tg_cookie cookie from target driver to be passed back to target 2935 * driver when we call back to it through tg_ops. 2936 * 2937 * Return Code: 0 2938 * EFAULT 2939 * ENXIO 2940 * EIO 2941 */ 2942 static int 2943 cmlb_dkio_set_geometry(struct cmlb_lun *cl, caddr_t arg, int flag) 2944 { 2945 struct dk_geom *tmp_geom; 2946 struct dk_map *lp; 2947 int rval = 0; 2948 int i; 2949 2950 2951 #if defined(__i386) || defined(__amd64) 2952 if (cl->cl_solaris_size == 0) { 2953 return (EIO); 2954 } 2955 #endif 2956 /* 2957 * We need to copy the user specified geometry into local 2958 * storage and then update the softstate. We don't want to hold 2959 * the mutex and copyin directly from the user to the soft state 2960 */ 2961 tmp_geom = (struct dk_geom *) 2962 kmem_zalloc(sizeof (struct dk_geom), KM_SLEEP); 2963 rval = ddi_copyin(arg, tmp_geom, sizeof (struct dk_geom), flag); 2964 if (rval != 0) { 2965 kmem_free(tmp_geom, sizeof (struct dk_geom)); 2966 return (EFAULT); 2967 } 2968 2969 mutex_enter(CMLB_MUTEX(cl)); 2970 bcopy(tmp_geom, &cl->cl_g, sizeof (struct dk_geom)); 2971 for (i = 0; i < NDKMAP; i++) { 2972 lp = &cl->cl_map[i]; 2973 cl->cl_offset[i] = 2974 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 2975 #if defined(__i386) || defined(__amd64) 2976 cl->cl_offset[i] += cl->cl_solaris_offset; 2977 #endif 2978 } 2979 cl->cl_f_geometry_is_valid = FALSE; 2980 mutex_exit(CMLB_MUTEX(cl)); 2981 kmem_free(tmp_geom, sizeof (struct dk_geom)); 2982 2983 return (rval); 2984 } 2985 2986 /* 2987 * Function: cmlb_dkio_get_partition 2988 * 2989 * Description: This routine is the driver entry point for handling user 2990 * requests to get the partition table (DKIOCGAPART). 2991 * 2992 * Arguments: 2993 * arg pointer to user provided dk_allmap structure specifying 2994 * the controller's notion of the current partition table. 2995 * 2996 * flag this argument is a pass through to ddi_copyxxx() 2997 * directly from the mode argument of ioctl(). 2998 * 2999 * tg_cookie cookie from target driver to be passed back to target 3000 * driver when we call back to it through tg_ops. 3001 * 3002 * Return Code: 0 3003 * EFAULT 3004 * ENXIO 3005 * EIO 3006 */ 3007 static int 3008 cmlb_dkio_get_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 3009 void *tg_cookie) 3010 { 3011 int rval = 0; 3012 int size; 3013 3014 /* 3015 * Make sure the geometry is valid before getting the partition 3016 * information. 3017 */ 3018 mutex_enter(CMLB_MUTEX(cl)); 3019 if ((rval = cmlb_validate_geometry(cl, 1, 0, tg_cookie)) != 0) { 3020 mutex_exit(CMLB_MUTEX(cl)); 3021 return (rval); 3022 } 3023 mutex_exit(CMLB_MUTEX(cl)); 3024 3025 #if defined(__i386) || defined(__amd64) 3026 if (cl->cl_solaris_size == 0) { 3027 return (EIO); 3028 } 3029 #endif 3030 3031 #ifdef _MULTI_DATAMODEL 3032 switch (ddi_model_convert_from(flag & FMODELS)) { 3033 case DDI_MODEL_ILP32: { 3034 struct dk_map32 dk_map32[NDKMAP]; 3035 int i; 3036 3037 for (i = 0; i < NDKMAP; i++) { 3038 dk_map32[i].dkl_cylno = cl->cl_map[i].dkl_cylno; 3039 dk_map32[i].dkl_nblk = cl->cl_map[i].dkl_nblk; 3040 } 3041 size = NDKMAP * sizeof (struct dk_map32); 3042 rval = ddi_copyout(dk_map32, (void *)arg, size, flag); 3043 if (rval != 0) { 3044 rval = EFAULT; 3045 } 3046 break; 3047 } 3048 case DDI_MODEL_NONE: 3049 size = NDKMAP * sizeof (struct dk_map); 3050 rval = ddi_copyout(cl->cl_map, (void *)arg, size, flag); 3051 if (rval != 0) { 3052 rval = EFAULT; 3053 } 3054 break; 3055 } 3056 #else /* ! _MULTI_DATAMODEL */ 3057 size = NDKMAP * sizeof (struct dk_map); 3058 rval = ddi_copyout(cl->cl_map, (void *)arg, size, flag); 3059 if (rval != 0) { 3060 rval = EFAULT; 3061 } 3062 #endif /* _MULTI_DATAMODEL */ 3063 return (rval); 3064 } 3065 3066 /* 3067 * Function: cmlb_dkio_set_partition 3068 * 3069 * Description: This routine is the driver entry point for handling user 3070 * requests to set the partition table (DKIOCSAPART). The actual 3071 * device partition is not updated. 3072 * 3073 * Arguments: 3074 * arg - pointer to user provided dk_allmap structure used to set 3075 * the controller's notion of the partition table. 3076 * flag - this argument is a pass through to ddi_copyxxx() 3077 * directly from the mode argument of ioctl(). 3078 * 3079 * Return Code: 0 3080 * EINVAL 3081 * EFAULT 3082 * ENXIO 3083 * EIO 3084 */ 3085 static int 3086 cmlb_dkio_set_partition(struct cmlb_lun *cl, caddr_t arg, int flag) 3087 { 3088 struct dk_map dk_map[NDKMAP]; 3089 struct dk_map *lp; 3090 int rval = 0; 3091 int size; 3092 int i; 3093 #if defined(_SUNOS_VTOC_16) 3094 struct dkl_partition *vp; 3095 #endif 3096 3097 /* 3098 * Set the map for all logical partitions. We lock 3099 * the priority just to make sure an interrupt doesn't 3100 * come in while the map is half updated. 3101 */ 3102 _NOTE(DATA_READABLE_WITHOUT_LOCK(cmlb_lun::cl_solaris_size)) 3103 mutex_enter(CMLB_MUTEX(cl)); 3104 3105 if (cl->cl_blockcount > DK_MAX_BLOCKS) { 3106 mutex_exit(CMLB_MUTEX(cl)); 3107 return (ENOTSUP); 3108 } 3109 mutex_exit(CMLB_MUTEX(cl)); 3110 if (cl->cl_solaris_size == 0) { 3111 return (EIO); 3112 } 3113 3114 #ifdef _MULTI_DATAMODEL 3115 switch (ddi_model_convert_from(flag & FMODELS)) { 3116 case DDI_MODEL_ILP32: { 3117 struct dk_map32 dk_map32[NDKMAP]; 3118 3119 size = NDKMAP * sizeof (struct dk_map32); 3120 rval = ddi_copyin((void *)arg, dk_map32, size, flag); 3121 if (rval != 0) { 3122 return (EFAULT); 3123 } 3124 for (i = 0; i < NDKMAP; i++) { 3125 dk_map[i].dkl_cylno = dk_map32[i].dkl_cylno; 3126 dk_map[i].dkl_nblk = dk_map32[i].dkl_nblk; 3127 } 3128 break; 3129 } 3130 case DDI_MODEL_NONE: 3131 size = NDKMAP * sizeof (struct dk_map); 3132 rval = ddi_copyin((void *)arg, dk_map, size, flag); 3133 if (rval != 0) { 3134 return (EFAULT); 3135 } 3136 break; 3137 } 3138 #else /* ! _MULTI_DATAMODEL */ 3139 size = NDKMAP * sizeof (struct dk_map); 3140 rval = ddi_copyin((void *)arg, dk_map, size, flag); 3141 if (rval != 0) { 3142 return (EFAULT); 3143 } 3144 #endif /* _MULTI_DATAMODEL */ 3145 3146 mutex_enter(CMLB_MUTEX(cl)); 3147 /* Note: The size used in this bcopy is set based upon the data model */ 3148 bcopy(dk_map, cl->cl_map, size); 3149 #if defined(_SUNOS_VTOC_16) 3150 vp = (struct dkl_partition *)&(cl->cl_vtoc); 3151 #endif /* defined(_SUNOS_VTOC_16) */ 3152 for (i = 0; i < NDKMAP; i++) { 3153 lp = &cl->cl_map[i]; 3154 cl->cl_offset[i] = 3155 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 3156 #if defined(_SUNOS_VTOC_16) 3157 vp->p_start = cl->cl_offset[i]; 3158 vp->p_size = lp->dkl_nblk; 3159 vp++; 3160 #endif /* defined(_SUNOS_VTOC_16) */ 3161 #if defined(__i386) || defined(__amd64) 3162 cl->cl_offset[i] += cl->cl_solaris_offset; 3163 #endif 3164 } 3165 mutex_exit(CMLB_MUTEX(cl)); 3166 return (rval); 3167 } 3168 3169 3170 /* 3171 * Function: cmlb_dkio_get_vtoc 3172 * 3173 * Description: This routine is the driver entry point for handling user 3174 * requests to get the current volume table of contents 3175 * (DKIOCGVTOC). 3176 * 3177 * Arguments: 3178 * arg pointer to user provided vtoc structure specifying 3179 * the current vtoc. 3180 * 3181 * flag this argument is a pass through to ddi_copyxxx() 3182 * directly from the mode argument of ioctl(). 3183 * 3184 * tg_cookie cookie from target driver to be passed back to target 3185 * driver when we call back to it through tg_ops. 3186 * 3187 * Return Code: 0 3188 * EFAULT 3189 * ENXIO 3190 * EIO 3191 */ 3192 static int 3193 cmlb_dkio_get_vtoc(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 3194 { 3195 #if defined(_SUNOS_VTOC_8) 3196 struct vtoc user_vtoc; 3197 #endif /* defined(_SUNOS_VTOC_8) */ 3198 int rval = 0; 3199 3200 mutex_enter(CMLB_MUTEX(cl)); 3201 rval = cmlb_validate_geometry(cl, 1, 0, tg_cookie); 3202 3203 #if defined(_SUNOS_VTOC_8) 3204 if (rval == EINVAL && 3205 (cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8)) { 3206 /* 3207 * This is to return a default label even when we do not 3208 * really assume a default label for the device. 3209 * dad driver utilizes this. 3210 */ 3211 if (cl->cl_blockcount <= DK_MAX_BLOCKS) { 3212 cmlb_setup_default_geometry(cl, tg_cookie); 3213 rval = 0; 3214 } 3215 } 3216 #endif 3217 if (rval) { 3218 mutex_exit(CMLB_MUTEX(cl)); 3219 return (rval); 3220 } 3221 3222 #if defined(_SUNOS_VTOC_8) 3223 cmlb_build_user_vtoc(cl, &user_vtoc); 3224 mutex_exit(CMLB_MUTEX(cl)); 3225 3226 #ifdef _MULTI_DATAMODEL 3227 switch (ddi_model_convert_from(flag & FMODELS)) { 3228 case DDI_MODEL_ILP32: { 3229 struct vtoc32 user_vtoc32; 3230 3231 vtoctovtoc32(user_vtoc, user_vtoc32); 3232 if (ddi_copyout(&user_vtoc32, (void *)arg, 3233 sizeof (struct vtoc32), flag)) { 3234 return (EFAULT); 3235 } 3236 break; 3237 } 3238 3239 case DDI_MODEL_NONE: 3240 if (ddi_copyout(&user_vtoc, (void *)arg, 3241 sizeof (struct vtoc), flag)) { 3242 return (EFAULT); 3243 } 3244 break; 3245 } 3246 #else /* ! _MULTI_DATAMODEL */ 3247 if (ddi_copyout(&user_vtoc, (void *)arg, sizeof (struct vtoc), flag)) { 3248 return (EFAULT); 3249 } 3250 #endif /* _MULTI_DATAMODEL */ 3251 3252 #elif defined(_SUNOS_VTOC_16) 3253 mutex_exit(CMLB_MUTEX(cl)); 3254 3255 #ifdef _MULTI_DATAMODEL 3256 /* 3257 * The cl_vtoc structure is a "struct dk_vtoc" which is always 3258 * 32-bit to maintain compatibility with existing on-disk 3259 * structures. Thus, we need to convert the structure when copying 3260 * it out to a datamodel-dependent "struct vtoc" in a 64-bit 3261 * program. If the target is a 32-bit program, then no conversion 3262 * is necessary. 3263 */ 3264 /* LINTED: logical expression always true: op "||" */ 3265 ASSERT(sizeof (cl->cl_vtoc) == sizeof (struct vtoc32)); 3266 switch (ddi_model_convert_from(flag & FMODELS)) { 3267 case DDI_MODEL_ILP32: 3268 if (ddi_copyout(&(cl->cl_vtoc), (void *)arg, 3269 sizeof (cl->cl_vtoc), flag)) { 3270 return (EFAULT); 3271 } 3272 break; 3273 3274 case DDI_MODEL_NONE: { 3275 struct vtoc user_vtoc; 3276 3277 vtoc32tovtoc(cl->cl_vtoc, user_vtoc); 3278 if (ddi_copyout(&user_vtoc, (void *)arg, 3279 sizeof (struct vtoc), flag)) { 3280 return (EFAULT); 3281 } 3282 break; 3283 } 3284 } 3285 #else /* ! _MULTI_DATAMODEL */ 3286 if (ddi_copyout(&(cl->cl_vtoc), (void *)arg, sizeof (cl->cl_vtoc), 3287 flag)) { 3288 return (EFAULT); 3289 } 3290 #endif /* _MULTI_DATAMODEL */ 3291 #else 3292 #error "No VTOC format defined." 3293 #endif 3294 3295 return (rval); 3296 } 3297 3298 static int 3299 cmlb_dkio_get_efi(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 3300 { 3301 dk_efi_t user_efi; 3302 int rval = 0; 3303 void *buffer; 3304 diskaddr_t tgt_lba; 3305 3306 if (ddi_copyin(arg, &user_efi, sizeof (dk_efi_t), flag)) 3307 return (EFAULT); 3308 3309 user_efi.dki_data = (void *)(uintptr_t)user_efi.dki_data_64; 3310 3311 tgt_lba = user_efi.dki_lba; 3312 3313 mutex_enter(CMLB_MUTEX(cl)); 3314 if ((cmlb_check_update_blockcount(cl, tg_cookie) != 0) || 3315 (cl->cl_tgt_blocksize == 0)) { 3316 mutex_exit(CMLB_MUTEX(cl)); 3317 return (EINVAL); 3318 } 3319 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) 3320 tgt_lba = tgt_lba * cl->cl_tgt_blocksize / 3321 cl->cl_sys_blocksize; 3322 mutex_exit(CMLB_MUTEX(cl)); 3323 3324 buffer = kmem_alloc(user_efi.dki_length, KM_SLEEP); 3325 rval = DK_TG_READ(cl, buffer, tgt_lba, user_efi.dki_length, tg_cookie); 3326 if (rval == 0 && ddi_copyout(buffer, user_efi.dki_data, 3327 user_efi.dki_length, flag) != 0) 3328 rval = EFAULT; 3329 3330 kmem_free(buffer, user_efi.dki_length); 3331 return (rval); 3332 } 3333 3334 #if defined(_SUNOS_VTOC_8) 3335 /* 3336 * Function: cmlb_build_user_vtoc 3337 * 3338 * Description: This routine populates a pass by reference variable with the 3339 * current volume table of contents. 3340 * 3341 * Arguments: cl - driver soft state (unit) structure 3342 * user_vtoc - pointer to vtoc structure to be populated 3343 */ 3344 static void 3345 cmlb_build_user_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc) 3346 { 3347 struct dk_map2 *lpart; 3348 struct dk_map *lmap; 3349 struct partition *vpart; 3350 int nblks; 3351 int i; 3352 3353 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 3354 3355 /* 3356 * Return vtoc structure fields in the provided VTOC area, addressed 3357 * by *vtoc. 3358 */ 3359 bzero(user_vtoc, sizeof (struct vtoc)); 3360 user_vtoc->v_bootinfo[0] = cl->cl_vtoc.v_bootinfo[0]; 3361 user_vtoc->v_bootinfo[1] = cl->cl_vtoc.v_bootinfo[1]; 3362 user_vtoc->v_bootinfo[2] = cl->cl_vtoc.v_bootinfo[2]; 3363 user_vtoc->v_sanity = VTOC_SANE; 3364 user_vtoc->v_version = cl->cl_vtoc.v_version; 3365 bcopy(cl->cl_vtoc.v_volume, user_vtoc->v_volume, LEN_DKL_VVOL); 3366 user_vtoc->v_sectorsz = cl->cl_sys_blocksize; 3367 user_vtoc->v_nparts = cl->cl_vtoc.v_nparts; 3368 3369 for (i = 0; i < 10; i++) 3370 user_vtoc->v_reserved[i] = cl->cl_vtoc.v_reserved[i]; 3371 3372 /* 3373 * Convert partitioning information. 3374 * 3375 * Note the conversion from starting cylinder number 3376 * to starting sector number. 3377 */ 3378 lmap = cl->cl_map; 3379 lpart = (struct dk_map2 *)cl->cl_vtoc.v_part; 3380 vpart = user_vtoc->v_part; 3381 3382 nblks = cl->cl_g.dkg_nsect * cl->cl_g.dkg_nhead; 3383 3384 for (i = 0; i < V_NUMPAR; i++) { 3385 vpart->p_tag = lpart->p_tag; 3386 vpart->p_flag = lpart->p_flag; 3387 vpart->p_start = lmap->dkl_cylno * nblks; 3388 vpart->p_size = lmap->dkl_nblk; 3389 lmap++; 3390 lpart++; 3391 vpart++; 3392 3393 /* (4364927) */ 3394 user_vtoc->timestamp[i] = (time_t)cl->cl_vtoc.v_timestamp[i]; 3395 } 3396 3397 bcopy(cl->cl_asciilabel, user_vtoc->v_asciilabel, LEN_DKL_ASCII); 3398 } 3399 #endif 3400 3401 static int 3402 cmlb_dkio_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 3403 void *tg_cookie) 3404 { 3405 struct partition64 p64; 3406 int rval = 0; 3407 uint_t nparts; 3408 efi_gpe_t *partitions; 3409 efi_gpt_t *buffer; 3410 diskaddr_t gpe_lba; 3411 3412 if (ddi_copyin((const void *)arg, &p64, 3413 sizeof (struct partition64), flag)) { 3414 return (EFAULT); 3415 } 3416 3417 buffer = kmem_alloc(EFI_MIN_ARRAY_SIZE, KM_SLEEP); 3418 rval = DK_TG_READ(cl, buffer, 1, DEV_BSIZE, tg_cookie); 3419 if (rval != 0) 3420 goto done_error; 3421 3422 cmlb_swap_efi_gpt(buffer); 3423 3424 if ((rval = cmlb_validate_efi(buffer)) != 0) 3425 goto done_error; 3426 3427 nparts = buffer->efi_gpt_NumberOfPartitionEntries; 3428 gpe_lba = buffer->efi_gpt_PartitionEntryLBA; 3429 if (p64.p_partno > nparts) { 3430 /* couldn't find it */ 3431 rval = ESRCH; 3432 goto done_error; 3433 } 3434 /* 3435 * if we're dealing with a partition that's out of the normal 3436 * 16K block, adjust accordingly 3437 */ 3438 gpe_lba += p64.p_partno / sizeof (efi_gpe_t); 3439 rval = DK_TG_READ(cl, buffer, gpe_lba, EFI_MIN_ARRAY_SIZE, tg_cookie); 3440 3441 if (rval) { 3442 goto done_error; 3443 } 3444 partitions = (efi_gpe_t *)buffer; 3445 3446 cmlb_swap_efi_gpe(nparts, partitions); 3447 3448 partitions += p64.p_partno; 3449 bcopy(&partitions->efi_gpe_PartitionTypeGUID, &p64.p_type, 3450 sizeof (struct uuid)); 3451 p64.p_start = partitions->efi_gpe_StartingLBA; 3452 p64.p_size = partitions->efi_gpe_EndingLBA - 3453 p64.p_start + 1; 3454 3455 if (ddi_copyout(&p64, (void *)arg, sizeof (struct partition64), flag)) 3456 rval = EFAULT; 3457 3458 done_error: 3459 kmem_free(buffer, EFI_MIN_ARRAY_SIZE); 3460 return (rval); 3461 } 3462 3463 3464 /* 3465 * Function: cmlb_dkio_set_vtoc 3466 * 3467 * Description: This routine is the driver entry point for handling user 3468 * requests to set the current volume table of contents 3469 * (DKIOCSVTOC). 3470 * 3471 * Arguments: 3472 * dev the device number 3473 * arg pointer to user provided vtoc structure used to set the 3474 * current vtoc. 3475 * 3476 * flag this argument is a pass through to ddi_copyxxx() 3477 * directly from the mode argument of ioctl(). 3478 * 3479 * tg_cookie cookie from target driver to be passed back to target 3480 * driver when we call back to it through tg_ops. 3481 * 3482 * Return Code: 0 3483 * EFAULT 3484 * ENXIO 3485 * EINVAL 3486 * ENOTSUP 3487 */ 3488 static int 3489 cmlb_dkio_set_vtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag, 3490 void *tg_cookie) 3491 { 3492 struct vtoc user_vtoc; 3493 int rval = 0; 3494 boolean_t internal; 3495 3496 internal = ((cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0); 3497 3498 #ifdef _MULTI_DATAMODEL 3499 switch (ddi_model_convert_from(flag & FMODELS)) { 3500 case DDI_MODEL_ILP32: { 3501 struct vtoc32 user_vtoc32; 3502 3503 if (ddi_copyin((const void *)arg, &user_vtoc32, 3504 sizeof (struct vtoc32), flag)) { 3505 return (EFAULT); 3506 } 3507 vtoc32tovtoc(user_vtoc32, user_vtoc); 3508 break; 3509 } 3510 3511 case DDI_MODEL_NONE: 3512 if (ddi_copyin((const void *)arg, &user_vtoc, 3513 sizeof (struct vtoc), flag)) { 3514 return (EFAULT); 3515 } 3516 break; 3517 } 3518 #else /* ! _MULTI_DATAMODEL */ 3519 if (ddi_copyin((const void *)arg, &user_vtoc, 3520 sizeof (struct vtoc), flag)) { 3521 return (EFAULT); 3522 } 3523 #endif /* _MULTI_DATAMODEL */ 3524 3525 mutex_enter(CMLB_MUTEX(cl)); 3526 if (cl->cl_blockcount > DK_MAX_BLOCKS) { 3527 mutex_exit(CMLB_MUTEX(cl)); 3528 return (ENOTSUP); 3529 } 3530 3531 #if defined(__i386) || defined(__amd64) 3532 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) { 3533 mutex_exit(CMLB_MUTEX(cl)); 3534 return (EINVAL); 3535 } 3536 #endif 3537 3538 if (cl->cl_g.dkg_ncyl == 0) { 3539 mutex_exit(CMLB_MUTEX(cl)); 3540 return (EINVAL); 3541 } 3542 3543 mutex_exit(CMLB_MUTEX(cl)); 3544 cmlb_clear_efi(cl, tg_cookie); 3545 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd"); 3546 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd,raw"); 3547 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h", 3548 S_IFBLK, (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 3549 cl->cl_node_type, NULL, internal); 3550 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h,raw", 3551 S_IFCHR, (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 3552 cl->cl_node_type, NULL, internal); 3553 mutex_enter(CMLB_MUTEX(cl)); 3554 3555 if ((rval = cmlb_build_label_vtoc(cl, &user_vtoc)) == 0) { 3556 if ((rval = cmlb_write_label(cl, tg_cookie)) == 0) { 3557 if (cmlb_validate_geometry(cl, 1, 0, tg_cookie) != 0) { 3558 cmlb_dbg(CMLB_ERROR, cl, 3559 "cmlb_dkio_set_vtoc: " 3560 "Failed validate geometry\n"); 3561 } 3562 } 3563 } 3564 mutex_exit(CMLB_MUTEX(cl)); 3565 return (rval); 3566 } 3567 3568 3569 /* 3570 * Function: cmlb_build_label_vtoc 3571 * 3572 * Description: This routine updates the driver soft state current volume table 3573 * of contents based on a user specified vtoc. 3574 * 3575 * Arguments: cl - driver soft state (unit) structure 3576 * user_vtoc - pointer to vtoc structure specifying vtoc to be used 3577 * to update the driver soft state. 3578 * 3579 * Return Code: 0 3580 * EINVAL 3581 */ 3582 static int 3583 cmlb_build_label_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc) 3584 { 3585 struct dk_map *lmap; 3586 struct partition *vpart; 3587 int nblks; 3588 #if defined(_SUNOS_VTOC_8) 3589 int ncyl; 3590 struct dk_map2 *lpart; 3591 #endif /* defined(_SUNOS_VTOC_8) */ 3592 int i; 3593 3594 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 3595 3596 /* Sanity-check the vtoc */ 3597 if (user_vtoc->v_sanity != VTOC_SANE || 3598 user_vtoc->v_sectorsz != cl->cl_sys_blocksize || 3599 user_vtoc->v_nparts != V_NUMPAR) { 3600 cmlb_dbg(CMLB_INFO, cl, 3601 "cmlb_build_label_vtoc: vtoc not valid\n"); 3602 return (EINVAL); 3603 } 3604 3605 nblks = cl->cl_g.dkg_nsect * cl->cl_g.dkg_nhead; 3606 if (nblks == 0) { 3607 cmlb_dbg(CMLB_INFO, cl, 3608 "cmlb_build_label_vtoc: geom nblks is 0\n"); 3609 return (EINVAL); 3610 } 3611 3612 #if defined(_SUNOS_VTOC_8) 3613 vpart = user_vtoc->v_part; 3614 for (i = 0; i < V_NUMPAR; i++) { 3615 if ((vpart->p_start % nblks) != 0) { 3616 cmlb_dbg(CMLB_INFO, cl, 3617 "cmlb_build_label_vtoc: p_start not multiply of" 3618 "nblks part %d p_start %d nblks %d\n", i, 3619 vpart->p_start, nblks); 3620 return (EINVAL); 3621 } 3622 ncyl = vpart->p_start / nblks; 3623 ncyl += vpart->p_size / nblks; 3624 if ((vpart->p_size % nblks) != 0) { 3625 ncyl++; 3626 } 3627 if (ncyl > (int)cl->cl_g.dkg_ncyl) { 3628 cmlb_dbg(CMLB_INFO, cl, 3629 "cmlb_build_label_vtoc: ncyl %d > dkg_ncyl %d" 3630 "p_size %ld p_start %ld nblks %d part number %d" 3631 "tag %d\n", 3632 ncyl, cl->cl_g.dkg_ncyl, vpart->p_size, 3633 vpart->p_start, nblks, 3634 i, vpart->p_tag); 3635 3636 return (EINVAL); 3637 } 3638 vpart++; 3639 } 3640 #endif /* defined(_SUNOS_VTOC_8) */ 3641 3642 /* Put appropriate vtoc structure fields into the disk label */ 3643 #if defined(_SUNOS_VTOC_16) 3644 /* 3645 * The vtoc is always a 32bit data structure to maintain the 3646 * on-disk format. Convert "in place" instead of doing bcopy. 3647 */ 3648 vtoctovtoc32((*user_vtoc), (*((struct vtoc32 *)&(cl->cl_vtoc)))); 3649 3650 /* 3651 * in the 16-slice vtoc, starting sectors are expressed in 3652 * numbers *relative* to the start of the Solaris fdisk partition. 3653 */ 3654 lmap = cl->cl_map; 3655 vpart = user_vtoc->v_part; 3656 3657 for (i = 0; i < (int)user_vtoc->v_nparts; i++, lmap++, vpart++) { 3658 lmap->dkl_cylno = vpart->p_start / nblks; 3659 lmap->dkl_nblk = vpart->p_size; 3660 } 3661 3662 #elif defined(_SUNOS_VTOC_8) 3663 3664 cl->cl_vtoc.v_bootinfo[0] = (uint32_t)user_vtoc->v_bootinfo[0]; 3665 cl->cl_vtoc.v_bootinfo[1] = (uint32_t)user_vtoc->v_bootinfo[1]; 3666 cl->cl_vtoc.v_bootinfo[2] = (uint32_t)user_vtoc->v_bootinfo[2]; 3667 3668 cl->cl_vtoc.v_sanity = (uint32_t)user_vtoc->v_sanity; 3669 cl->cl_vtoc.v_version = (uint32_t)user_vtoc->v_version; 3670 3671 bcopy(user_vtoc->v_volume, cl->cl_vtoc.v_volume, LEN_DKL_VVOL); 3672 3673 cl->cl_vtoc.v_nparts = user_vtoc->v_nparts; 3674 3675 for (i = 0; i < 10; i++) 3676 cl->cl_vtoc.v_reserved[i] = user_vtoc->v_reserved[i]; 3677 3678 /* 3679 * Note the conversion from starting sector number 3680 * to starting cylinder number. 3681 * Return error if division results in a remainder. 3682 */ 3683 lmap = cl->cl_map; 3684 lpart = cl->cl_vtoc.v_part; 3685 vpart = user_vtoc->v_part; 3686 3687 for (i = 0; i < (int)user_vtoc->v_nparts; i++) { 3688 lpart->p_tag = vpart->p_tag; 3689 lpart->p_flag = vpart->p_flag; 3690 lmap->dkl_cylno = vpart->p_start / nblks; 3691 lmap->dkl_nblk = vpart->p_size; 3692 3693 lmap++; 3694 lpart++; 3695 vpart++; 3696 3697 /* (4387723) */ 3698 #ifdef _LP64 3699 if (user_vtoc->timestamp[i] > TIME32_MAX) { 3700 cl->cl_vtoc.v_timestamp[i] = TIME32_MAX; 3701 } else { 3702 cl->cl_vtoc.v_timestamp[i] = user_vtoc->timestamp[i]; 3703 } 3704 #else 3705 cl->cl_vtoc.v_timestamp[i] = user_vtoc->timestamp[i]; 3706 #endif 3707 } 3708 3709 bcopy(user_vtoc->v_asciilabel, cl->cl_asciilabel, LEN_DKL_ASCII); 3710 #else 3711 #error "No VTOC format defined." 3712 #endif 3713 return (0); 3714 } 3715 3716 /* 3717 * Function: cmlb_clear_efi 3718 * 3719 * Description: This routine clears all EFI labels. 3720 * 3721 * Arguments: 3722 * cl driver soft state (unit) structure 3723 * 3724 * tg_cookie cookie from target driver to be passed back to target 3725 * driver when we call back to it through tg_ops. 3726 * Return Code: void 3727 */ 3728 static void 3729 cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie) 3730 { 3731 efi_gpt_t *gpt; 3732 diskaddr_t cap; 3733 int rval; 3734 3735 ASSERT(!mutex_owned(CMLB_MUTEX(cl))); 3736 3737 mutex_enter(CMLB_MUTEX(cl)); 3738 cl->cl_reserved = -1; 3739 mutex_exit(CMLB_MUTEX(cl)); 3740 3741 gpt = kmem_alloc(sizeof (efi_gpt_t), KM_SLEEP); 3742 3743 if (DK_TG_READ(cl, gpt, 1, DEV_BSIZE, tg_cookie) != 0) { 3744 goto done; 3745 } 3746 3747 cmlb_swap_efi_gpt(gpt); 3748 rval = cmlb_validate_efi(gpt); 3749 if (rval == 0) { 3750 /* clear primary */ 3751 bzero(gpt, sizeof (efi_gpt_t)); 3752 if (rval = DK_TG_WRITE(cl, gpt, 1, EFI_LABEL_SIZE, tg_cookie)) { 3753 cmlb_dbg(CMLB_INFO, cl, 3754 "cmlb_clear_efi: clear primary label failed\n"); 3755 } 3756 } 3757 /* the backup */ 3758 rval = DK_TG_GETCAP(cl, &cap, tg_cookie); 3759 if (rval) { 3760 goto done; 3761 } 3762 3763 if ((rval = DK_TG_READ(cl, gpt, cap - 1, EFI_LABEL_SIZE, tg_cookie)) 3764 != 0) { 3765 goto done; 3766 } 3767 cmlb_swap_efi_gpt(gpt); 3768 rval = cmlb_validate_efi(gpt); 3769 if (rval == 0) { 3770 /* clear backup */ 3771 cmlb_dbg(CMLB_TRACE, cl, 3772 "cmlb_clear_efi clear backup@%lu\n", cap - 1); 3773 bzero(gpt, sizeof (efi_gpt_t)); 3774 if ((rval = DK_TG_WRITE(cl, gpt, cap - 1, EFI_LABEL_SIZE, 3775 tg_cookie))) { 3776 cmlb_dbg(CMLB_INFO, cl, 3777 "cmlb_clear_efi: clear backup label failed\n"); 3778 } 3779 } else { 3780 /* 3781 * Refer to comments related to off-by-1 at the 3782 * header of this file 3783 */ 3784 if ((rval = DK_TG_READ(cl, gpt, cap - 2, 3785 EFI_LABEL_SIZE, tg_cookie)) != 0) { 3786 goto done; 3787 } 3788 cmlb_swap_efi_gpt(gpt); 3789 rval = cmlb_validate_efi(gpt); 3790 if (rval == 0) { 3791 /* clear legacy backup EFI label */ 3792 cmlb_dbg(CMLB_TRACE, cl, 3793 "cmlb_clear_efi clear legacy backup@%lu\n", 3794 cap - 2); 3795 bzero(gpt, sizeof (efi_gpt_t)); 3796 if ((rval = DK_TG_WRITE(cl, gpt, cap - 2, 3797 EFI_LABEL_SIZE, tg_cookie))) { 3798 cmlb_dbg(CMLB_INFO, cl, 3799 "cmlb_clear_efi: clear legacy backup label " 3800 "failed\n"); 3801 } 3802 } 3803 } 3804 3805 done: 3806 kmem_free(gpt, sizeof (efi_gpt_t)); 3807 } 3808 3809 /* 3810 * Function: cmlb_set_vtoc 3811 * 3812 * Description: This routine writes data to the appropriate positions 3813 * 3814 * Arguments: 3815 * cl driver soft state (unit) structure 3816 * 3817 * dkl the data to be written 3818 * 3819 * tg_cookie cookie from target driver to be passed back to target 3820 * driver when we call back to it through tg_ops. 3821 * 3822 * Return: void 3823 */ 3824 static int 3825 cmlb_set_vtoc(struct cmlb_lun *cl, struct dk_label *dkl, void *tg_cookie) 3826 { 3827 uint_t label_addr; 3828 int sec; 3829 int blk; 3830 int head; 3831 int cyl; 3832 int rval; 3833 3834 #if defined(__i386) || defined(__amd64) 3835 label_addr = cl->cl_solaris_offset + DK_LABEL_LOC; 3836 #else 3837 /* Write the primary label at block 0 of the solaris partition. */ 3838 label_addr = 0; 3839 #endif 3840 3841 rval = DK_TG_WRITE(cl, dkl, label_addr, cl->cl_sys_blocksize, 3842 tg_cookie); 3843 3844 if (rval != 0) { 3845 return (rval); 3846 } 3847 3848 /* 3849 * Calculate where the backup labels go. They are always on 3850 * the last alternate cylinder, but some older drives put them 3851 * on head 2 instead of the last head. They are always on the 3852 * first 5 odd sectors of the appropriate track. 3853 * 3854 * We have no choice at this point, but to believe that the 3855 * disk label is valid. Use the geometry of the disk 3856 * as described in the label. 3857 */ 3858 cyl = dkl->dkl_ncyl + dkl->dkl_acyl - 1; 3859 head = dkl->dkl_nhead - 1; 3860 3861 /* 3862 * Write and verify the backup labels. Make sure we don't try to 3863 * write past the last cylinder. 3864 */ 3865 for (sec = 1; ((sec < 5 * 2 + 1) && (sec < dkl->dkl_nsect)); sec += 2) { 3866 blk = (daddr_t)( 3867 (cyl * ((dkl->dkl_nhead * dkl->dkl_nsect) - dkl->dkl_apc)) + 3868 (head * dkl->dkl_nsect) + sec); 3869 #if defined(__i386) || defined(__amd64) 3870 blk += cl->cl_solaris_offset; 3871 #endif 3872 rval = DK_TG_WRITE(cl, dkl, blk, cl->cl_sys_blocksize, 3873 tg_cookie); 3874 cmlb_dbg(CMLB_INFO, cl, 3875 "cmlb_set_vtoc: wrote backup label %d\n", blk); 3876 if (rval != 0) { 3877 goto exit; 3878 } 3879 } 3880 exit: 3881 return (rval); 3882 } 3883 3884 /* 3885 * Function: cmlb_clear_vtoc 3886 * 3887 * Description: This routine clears out the VTOC labels. 3888 * 3889 * Arguments: 3890 * cl driver soft state (unit) structure 3891 * 3892 * tg_cookie cookie from target driver to be passed back to target 3893 * driver when we call back to it through tg_ops. 3894 * 3895 * Return: void 3896 */ 3897 static void 3898 cmlb_clear_vtoc(struct cmlb_lun *cl, void *tg_cookie) 3899 { 3900 struct dk_label *dkl; 3901 3902 mutex_exit(CMLB_MUTEX(cl)); 3903 dkl = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 3904 mutex_enter(CMLB_MUTEX(cl)); 3905 /* 3906 * cmlb_set_vtoc uses these fields in order to figure out 3907 * where to overwrite the backup labels 3908 */ 3909 dkl->dkl_apc = cl->cl_g.dkg_apc; 3910 dkl->dkl_ncyl = cl->cl_g.dkg_ncyl; 3911 dkl->dkl_acyl = cl->cl_g.dkg_acyl; 3912 dkl->dkl_nhead = cl->cl_g.dkg_nhead; 3913 dkl->dkl_nsect = cl->cl_g.dkg_nsect; 3914 mutex_exit(CMLB_MUTEX(cl)); 3915 (void) cmlb_set_vtoc(cl, dkl, tg_cookie); 3916 kmem_free(dkl, sizeof (struct dk_label)); 3917 3918 mutex_enter(CMLB_MUTEX(cl)); 3919 } 3920 3921 /* 3922 * Function: cmlb_write_label 3923 * 3924 * Description: This routine will validate and write the driver soft state vtoc 3925 * contents to the device. 3926 * 3927 * Arguments: 3928 * cl cmlb handle 3929 * 3930 * tg_cookie cookie from target driver to be passed back to target 3931 * driver when we call back to it through tg_ops. 3932 * 3933 * 3934 * Return Code: the code returned by cmlb_send_scsi_cmd() 3935 * 0 3936 * EINVAL 3937 * ENXIO 3938 * ENOMEM 3939 */ 3940 static int 3941 cmlb_write_label(struct cmlb_lun *cl, void *tg_cookie) 3942 { 3943 struct dk_label *dkl; 3944 short sum; 3945 short *sp; 3946 int i; 3947 int rval; 3948 3949 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 3950 mutex_exit(CMLB_MUTEX(cl)); 3951 dkl = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 3952 mutex_enter(CMLB_MUTEX(cl)); 3953 3954 bcopy(&cl->cl_vtoc, &dkl->dkl_vtoc, sizeof (struct dk_vtoc)); 3955 dkl->dkl_rpm = cl->cl_g.dkg_rpm; 3956 dkl->dkl_pcyl = cl->cl_g.dkg_pcyl; 3957 dkl->dkl_apc = cl->cl_g.dkg_apc; 3958 dkl->dkl_intrlv = cl->cl_g.dkg_intrlv; 3959 dkl->dkl_ncyl = cl->cl_g.dkg_ncyl; 3960 dkl->dkl_acyl = cl->cl_g.dkg_acyl; 3961 dkl->dkl_nhead = cl->cl_g.dkg_nhead; 3962 dkl->dkl_nsect = cl->cl_g.dkg_nsect; 3963 3964 #if defined(_SUNOS_VTOC_8) 3965 dkl->dkl_obs1 = cl->cl_g.dkg_obs1; 3966 dkl->dkl_obs2 = cl->cl_g.dkg_obs2; 3967 dkl->dkl_obs3 = cl->cl_g.dkg_obs3; 3968 for (i = 0; i < NDKMAP; i++) { 3969 dkl->dkl_map[i].dkl_cylno = cl->cl_map[i].dkl_cylno; 3970 dkl->dkl_map[i].dkl_nblk = cl->cl_map[i].dkl_nblk; 3971 } 3972 bcopy(cl->cl_asciilabel, dkl->dkl_asciilabel, LEN_DKL_ASCII); 3973 #elif defined(_SUNOS_VTOC_16) 3974 dkl->dkl_skew = cl->cl_dkg_skew; 3975 #else 3976 #error "No VTOC format defined." 3977 #endif 3978 3979 dkl->dkl_magic = DKL_MAGIC; 3980 dkl->dkl_write_reinstruct = cl->cl_g.dkg_write_reinstruct; 3981 dkl->dkl_read_reinstruct = cl->cl_g.dkg_read_reinstruct; 3982 3983 /* Construct checksum for the new disk label */ 3984 sum = 0; 3985 sp = (short *)dkl; 3986 i = sizeof (struct dk_label) / sizeof (short); 3987 while (i--) { 3988 sum ^= *sp++; 3989 } 3990 dkl->dkl_cksum = sum; 3991 3992 mutex_exit(CMLB_MUTEX(cl)); 3993 3994 rval = cmlb_set_vtoc(cl, dkl, tg_cookie); 3995 exit: 3996 kmem_free(dkl, sizeof (struct dk_label)); 3997 mutex_enter(CMLB_MUTEX(cl)); 3998 return (rval); 3999 } 4000 4001 static int 4002 cmlb_dkio_set_efi(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag, 4003 void *tg_cookie) 4004 { 4005 dk_efi_t user_efi; 4006 int rval = 0; 4007 void *buffer; 4008 diskaddr_t tgt_lba; 4009 boolean_t internal; 4010 4011 if (ddi_copyin(arg, &user_efi, sizeof (dk_efi_t), flag)) 4012 return (EFAULT); 4013 4014 internal = ((cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0); 4015 4016 user_efi.dki_data = (void *)(uintptr_t)user_efi.dki_data_64; 4017 4018 buffer = kmem_alloc(user_efi.dki_length, KM_SLEEP); 4019 if (ddi_copyin(user_efi.dki_data, buffer, user_efi.dki_length, flag)) { 4020 rval = EFAULT; 4021 } else { 4022 /* 4023 * let's clear the vtoc labels and clear the softstate 4024 * vtoc. 4025 */ 4026 mutex_enter(CMLB_MUTEX(cl)); 4027 if (cl->cl_vtoc.v_sanity == VTOC_SANE) { 4028 cmlb_dbg(CMLB_TRACE, cl, 4029 "cmlb_dkio_set_efi: CLEAR VTOC\n"); 4030 if (cl->cl_vtoc_label_is_from_media) 4031 cmlb_clear_vtoc(cl, tg_cookie); 4032 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 4033 mutex_exit(CMLB_MUTEX(cl)); 4034 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h"); 4035 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h,raw"); 4036 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd", 4037 S_IFBLK, 4038 (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 4039 cl->cl_node_type, NULL, internal); 4040 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd,raw", 4041 S_IFCHR, 4042 (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 4043 cl->cl_node_type, NULL, internal); 4044 } else 4045 mutex_exit(CMLB_MUTEX(cl)); 4046 4047 tgt_lba = user_efi.dki_lba; 4048 4049 mutex_enter(CMLB_MUTEX(cl)); 4050 if ((cmlb_check_update_blockcount(cl, tg_cookie) != 0) || 4051 (cl->cl_tgt_blocksize == 0)) { 4052 kmem_free(buffer, user_efi.dki_length); 4053 mutex_exit(CMLB_MUTEX(cl)); 4054 return (EINVAL); 4055 } 4056 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) 4057 tgt_lba = tgt_lba * 4058 cl->cl_tgt_blocksize / cl->cl_sys_blocksize; 4059 4060 mutex_exit(CMLB_MUTEX(cl)); 4061 rval = DK_TG_WRITE(cl, buffer, tgt_lba, user_efi.dki_length, 4062 tg_cookie); 4063 4064 if (rval == 0) { 4065 mutex_enter(CMLB_MUTEX(cl)); 4066 cl->cl_f_geometry_is_valid = FALSE; 4067 mutex_exit(CMLB_MUTEX(cl)); 4068 } 4069 } 4070 kmem_free(buffer, user_efi.dki_length); 4071 return (rval); 4072 } 4073 4074 /* 4075 * Function: cmlb_dkio_get_mboot 4076 * 4077 * Description: This routine is the driver entry point for handling user 4078 * requests to get the current device mboot (DKIOCGMBOOT) 4079 * 4080 * Arguments: 4081 * arg pointer to user provided mboot structure specifying 4082 * the current mboot. 4083 * 4084 * flag this argument is a pass through to ddi_copyxxx() 4085 * directly from the mode argument of ioctl(). 4086 * 4087 * tg_cookie cookie from target driver to be passed back to target 4088 * driver when we call back to it through tg_ops. 4089 * 4090 * Return Code: 0 4091 * EINVAL 4092 * EFAULT 4093 * ENXIO 4094 */ 4095 static int 4096 cmlb_dkio_get_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 4097 { 4098 struct mboot *mboot; 4099 int rval; 4100 size_t buffer_size; 4101 4102 4103 #if defined(_SUNOS_VTOC_8) 4104 if ((!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) || (arg == NULL)) { 4105 #elif defined(_SUNOS_VTOC_16) 4106 if (arg == NULL) { 4107 #endif 4108 return (EINVAL); 4109 } 4110 4111 /* 4112 * Read the mboot block, located at absolute block 0 on the target. 4113 */ 4114 buffer_size = sizeof (struct mboot); 4115 4116 cmlb_dbg(CMLB_TRACE, cl, 4117 "cmlb_dkio_get_mboot: allocation size: 0x%x\n", buffer_size); 4118 4119 mboot = kmem_zalloc(buffer_size, KM_SLEEP); 4120 if ((rval = DK_TG_READ(cl, mboot, 0, buffer_size, tg_cookie)) == 0) { 4121 if (ddi_copyout(mboot, (void *)arg, 4122 sizeof (struct mboot), flag) != 0) { 4123 rval = EFAULT; 4124 } 4125 } 4126 kmem_free(mboot, buffer_size); 4127 return (rval); 4128 } 4129 4130 4131 /* 4132 * Function: cmlb_dkio_set_mboot 4133 * 4134 * Description: This routine is the driver entry point for handling user 4135 * requests to validate and set the device master boot 4136 * (DKIOCSMBOOT). 4137 * 4138 * Arguments: 4139 * arg pointer to user provided mboot structure used to set the 4140 * master boot. 4141 * 4142 * flag this argument is a pass through to ddi_copyxxx() 4143 * directly from the mode argument of ioctl(). 4144 * 4145 * tg_cookie cookie from target driver to be passed back to target 4146 * driver when we call back to it through tg_ops. 4147 * 4148 * Return Code: 0 4149 * EINVAL 4150 * EFAULT 4151 * ENXIO 4152 */ 4153 static int 4154 cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 4155 { 4156 struct mboot *mboot = NULL; 4157 int rval; 4158 ushort_t magic; 4159 4160 4161 ASSERT(!mutex_owned(CMLB_MUTEX(cl))); 4162 4163 #if defined(_SUNOS_VTOC_8) 4164 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 4165 return (EINVAL); 4166 } 4167 #endif 4168 4169 if (arg == NULL) { 4170 return (EINVAL); 4171 } 4172 4173 mboot = kmem_zalloc(sizeof (struct mboot), KM_SLEEP); 4174 4175 if (ddi_copyin((const void *)arg, mboot, 4176 sizeof (struct mboot), flag) != 0) { 4177 kmem_free(mboot, (size_t)(sizeof (struct mboot))); 4178 return (EFAULT); 4179 } 4180 4181 /* Is this really a master boot record? */ 4182 magic = LE_16(mboot->signature); 4183 if (magic != MBB_MAGIC) { 4184 kmem_free(mboot, (size_t)(sizeof (struct mboot))); 4185 return (EINVAL); 4186 } 4187 4188 rval = DK_TG_WRITE(cl, mboot, 0, cl->cl_sys_blocksize, tg_cookie); 4189 4190 mutex_enter(CMLB_MUTEX(cl)); 4191 #if defined(__i386) || defined(__amd64) 4192 if (rval == 0) { 4193 /* 4194 * mboot has been written successfully. 4195 * update the fdisk and vtoc tables in memory 4196 */ 4197 rval = cmlb_update_fdisk_and_vtoc(cl, tg_cookie); 4198 if ((cl->cl_f_geometry_is_valid == FALSE) || (rval != 0)) { 4199 mutex_exit(CMLB_MUTEX(cl)); 4200 kmem_free(mboot, (size_t)(sizeof (struct mboot))); 4201 return (rval); 4202 } 4203 } 4204 4205 #ifdef __lock_lint 4206 cmlb_setup_default_geometry(cl, tg_cookie); 4207 #endif 4208 4209 #else 4210 if (rval == 0) { 4211 /* 4212 * mboot has been written successfully. 4213 * set up the default geometry and VTOC 4214 */ 4215 if (cl->cl_blockcount <= DK_MAX_BLOCKS) 4216 cmlb_setup_default_geometry(cl, tg_cookie); 4217 } 4218 #endif 4219 mutex_exit(CMLB_MUTEX(cl)); 4220 kmem_free(mboot, (size_t)(sizeof (struct mboot))); 4221 return (rval); 4222 } 4223 4224 4225 /* 4226 * Function: cmlb_setup_default_geometry 4227 * 4228 * Description: This local utility routine sets the default geometry as part of 4229 * setting the device mboot. 4230 * 4231 * Arguments: 4232 * cl driver soft state (unit) structure 4233 * 4234 * tg_cookie cookie from target driver to be passed back to target 4235 * driver when we call back to it through tg_ops. 4236 * 4237 * 4238 * Note: This may be redundant with cmlb_build_default_label. 4239 */ 4240 static void 4241 cmlb_setup_default_geometry(struct cmlb_lun *cl, void *tg_cookie) 4242 { 4243 struct cmlb_geom pgeom; 4244 struct cmlb_geom *pgeomp = &pgeom; 4245 int ret; 4246 int geom_base_cap = 1; 4247 4248 4249 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4250 4251 /* zero out the soft state geometry and partition table. */ 4252 bzero(&cl->cl_g, sizeof (struct dk_geom)); 4253 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 4254 bzero(cl->cl_map, NDKMAP * (sizeof (struct dk_map))); 4255 4256 /* 4257 * For the rpm, we use the minimum for the disk. 4258 * For the head, cyl and number of sector per track, 4259 * if the capacity <= 1GB, head = 64, sect = 32. 4260 * else head = 255, sect 63 4261 * Note: the capacity should be equal to C*H*S values. 4262 * This will cause some truncation of size due to 4263 * round off errors. For CD-ROMs, this truncation can 4264 * have adverse side effects, so returning ncyl and 4265 * nhead as 1. The nsect will overflow for most of 4266 * CD-ROMs as nsect is of type ushort. 4267 */ 4268 if (cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8) { 4269 /* 4270 * newfs currently can not handle 255 ntracks for SPARC 4271 * so get the geometry from target driver instead of coming up 4272 * with one based on capacity. 4273 */ 4274 mutex_exit(CMLB_MUTEX(cl)); 4275 ret = DK_TG_GETPHYGEOM(cl, pgeomp, tg_cookie); 4276 mutex_enter(CMLB_MUTEX(cl)); 4277 4278 if (ret == 0) { 4279 geom_base_cap = 0; 4280 } else { 4281 cmlb_dbg(CMLB_ERROR, cl, 4282 "cmlb_setup_default_geometry: " 4283 "tg_getphygeom failed %d\n", ret); 4284 4285 /* do default setting, geometry based on capacity */ 4286 } 4287 } 4288 4289 if (geom_base_cap) { 4290 if (ISCD(cl)) { 4291 cl->cl_g.dkg_ncyl = 1; 4292 cl->cl_g.dkg_nhead = 1; 4293 cl->cl_g.dkg_nsect = cl->cl_blockcount; 4294 } else if (cl->cl_blockcount <= 0x1000) { 4295 /* Needed for unlabeled SCSI floppies. */ 4296 cl->cl_g.dkg_nhead = 2; 4297 cl->cl_g.dkg_ncyl = 80; 4298 cl->cl_g.dkg_pcyl = 80; 4299 cl->cl_g.dkg_nsect = cl->cl_blockcount / (2 * 80); 4300 } else if (cl->cl_blockcount <= 0x200000) { 4301 cl->cl_g.dkg_nhead = 64; 4302 cl->cl_g.dkg_nsect = 32; 4303 cl->cl_g.dkg_ncyl = cl->cl_blockcount / (64 * 32); 4304 } else { 4305 cl->cl_g.dkg_nhead = 255; 4306 4307 cl->cl_g.dkg_nsect = ((cl->cl_blockcount + 4308 (UINT16_MAX * 255 * 63) - 1) / 4309 (UINT16_MAX * 255 * 63)) * 63; 4310 4311 if (cl->cl_g.dkg_nsect == 0) 4312 cl->cl_g.dkg_nsect = (UINT16_MAX / 63) * 63; 4313 4314 cl->cl_g.dkg_ncyl = cl->cl_blockcount / 4315 (255 * cl->cl_g.dkg_nsect); 4316 } 4317 4318 cl->cl_g.dkg_acyl = 0; 4319 cl->cl_g.dkg_bcyl = 0; 4320 cl->cl_g.dkg_intrlv = 1; 4321 cl->cl_g.dkg_rpm = 200; 4322 if (cl->cl_g.dkg_pcyl == 0) 4323 cl->cl_g.dkg_pcyl = cl->cl_g.dkg_ncyl + 4324 cl->cl_g.dkg_acyl; 4325 } else { 4326 cl->cl_g.dkg_ncyl = (short)pgeomp->g_ncyl; 4327 cl->cl_g.dkg_acyl = pgeomp->g_acyl; 4328 cl->cl_g.dkg_nhead = pgeomp->g_nhead; 4329 cl->cl_g.dkg_nsect = pgeomp->g_nsect; 4330 cl->cl_g.dkg_intrlv = pgeomp->g_intrlv; 4331 cl->cl_g.dkg_rpm = pgeomp->g_rpm; 4332 cl->cl_g.dkg_pcyl = cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl; 4333 } 4334 4335 cl->cl_g.dkg_read_reinstruct = 0; 4336 cl->cl_g.dkg_write_reinstruct = 0; 4337 cl->cl_solaris_size = cl->cl_g.dkg_ncyl * 4338 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 4339 4340 cl->cl_map['a'-'a'].dkl_cylno = 0; 4341 cl->cl_map['a'-'a'].dkl_nblk = cl->cl_solaris_size; 4342 4343 cl->cl_map['c'-'a'].dkl_cylno = 0; 4344 cl->cl_map['c'-'a'].dkl_nblk = cl->cl_solaris_size; 4345 4346 cl->cl_vtoc.v_part[2].p_tag = V_BACKUP; 4347 cl->cl_vtoc.v_part[2].p_flag = V_UNMNT; 4348 cl->cl_vtoc.v_nparts = V_NUMPAR; 4349 cl->cl_vtoc.v_version = V_VERSION; 4350 (void) sprintf((char *)cl->cl_asciilabel, "DEFAULT cyl %d alt %d" 4351 " hd %d sec %d", cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, 4352 cl->cl_g.dkg_nhead, cl->cl_g.dkg_nsect); 4353 4354 cl->cl_f_geometry_is_valid = FALSE; 4355 } 4356 4357 4358 #if defined(__i386) || defined(__amd64) 4359 /* 4360 * Function: cmlb_update_fdisk_and_vtoc 4361 * 4362 * Description: This local utility routine updates the device fdisk and vtoc 4363 * as part of setting the device mboot. 4364 * 4365 * Arguments: 4366 * cl driver soft state (unit) structure 4367 * 4368 * tg_cookie cookie from target driver to be passed back to target 4369 * driver when we call back to it through tg_ops. 4370 * 4371 * 4372 * Return Code: 0 for success or errno-type return code. 4373 * 4374 * Note:x86: This looks like a duplicate of cmlb_validate_geometry(), but 4375 * these did exist separately in x86 sd.c. 4376 */ 4377 static int 4378 cmlb_update_fdisk_and_vtoc(struct cmlb_lun *cl, void *tg_cookie) 4379 { 4380 int count; 4381 int label_rc = 0; 4382 int fdisk_rval; 4383 diskaddr_t capacity; 4384 4385 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4386 4387 if (cmlb_check_update_blockcount(cl, tg_cookie) != 0) 4388 return (EINVAL); 4389 4390 #if defined(_SUNOS_VTOC_16) 4391 /* 4392 * Set up the "whole disk" fdisk partition; this should always 4393 * exist, regardless of whether the disk contains an fdisk table 4394 * or vtoc. 4395 */ 4396 cl->cl_map[P0_RAW_DISK].dkl_cylno = 0; 4397 cl->cl_map[P0_RAW_DISK].dkl_nblk = cl->cl_blockcount; 4398 #endif /* defined(_SUNOS_VTOC_16) */ 4399 4400 /* 4401 * copy the lbasize and capacity so that if they're 4402 * reset while we're not holding the CMLB_MUTEX(cl), we will 4403 * continue to use valid values after the CMLB_MUTEX(cl) is 4404 * reacquired. 4405 */ 4406 capacity = cl->cl_blockcount; 4407 4408 /* 4409 * refresh the logical and physical geometry caches. 4410 * (data from mode sense format/rigid disk geometry pages, 4411 * and scsi_ifgetcap("geometry"). 4412 */ 4413 cmlb_resync_geom_caches(cl, capacity, tg_cookie); 4414 4415 /* 4416 * Only DIRECT ACCESS devices will have Scl labels. 4417 * CD's supposedly have a Scl label, too 4418 */ 4419 if (cl->cl_device_type == DTYPE_DIRECT || ISREMOVABLE(cl)) { 4420 fdisk_rval = cmlb_read_fdisk(cl, capacity, tg_cookie); 4421 if (fdisk_rval != 0) { 4422 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4423 return (fdisk_rval); 4424 } 4425 4426 if (cl->cl_solaris_size <= DK_LABEL_LOC) { 4427 /* 4428 * Found fdisk table but no Solaris partition entry, 4429 * so don't call cmlb_uselabel() and don't create 4430 * a default label. 4431 */ 4432 label_rc = 0; 4433 cl->cl_f_geometry_is_valid = TRUE; 4434 goto no_solaris_partition; 4435 } 4436 } else if (capacity < 0) { 4437 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4438 return (EINVAL); 4439 } 4440 4441 /* 4442 * For Removable media We reach here if we have found a 4443 * SOLARIS PARTITION. 4444 * If cl_f_geometry_is_valid is FALSE it indicates that the SOLARIS 4445 * PARTITION has changed from the previous one, hence we will setup a 4446 * default VTOC in this case. 4447 */ 4448 if (cl->cl_f_geometry_is_valid == FALSE) { 4449 /* if we get here it is writable */ 4450 /* we are called from SMBOOT, and after a write of fdisk */ 4451 cmlb_build_default_label(cl, tg_cookie); 4452 label_rc = 0; 4453 } 4454 4455 no_solaris_partition: 4456 4457 #if defined(_SUNOS_VTOC_16) 4458 /* 4459 * If we have valid geometry, set up the remaining fdisk partitions. 4460 * Note that dkl_cylno is not used for the fdisk map entries, so 4461 * we set it to an entirely bogus value. 4462 */ 4463 for (count = 0; count < FD_NUMPART; count++) { 4464 cl->cl_map[FDISK_P1 + count].dkl_cylno = -1; 4465 cl->cl_map[FDISK_P1 + count].dkl_nblk = 4466 cl->cl_fmap[count].fmap_nblk; 4467 cl->cl_offset[FDISK_P1 + count] = 4468 cl->cl_fmap[count].fmap_start; 4469 } 4470 #endif 4471 4472 for (count = 0; count < NDKMAP; count++) { 4473 #if defined(_SUNOS_VTOC_8) 4474 struct dk_map *lp = &cl->cl_map[count]; 4475 cl->cl_offset[count] = 4476 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 4477 #elif defined(_SUNOS_VTOC_16) 4478 struct dkl_partition *vp = &cl->cl_vtoc.v_part[count]; 4479 cl->cl_offset[count] = vp->p_start + cl->cl_solaris_offset; 4480 #else 4481 #error "No VTOC format defined." 4482 #endif 4483 } 4484 4485 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4486 return (label_rc); 4487 } 4488 #endif 4489 4490 #if defined(__i386) || defined(__amd64) 4491 static int 4492 cmlb_dkio_get_virtgeom(struct cmlb_lun *cl, caddr_t arg, int flag) 4493 { 4494 int err = 0; 4495 4496 /* Return the driver's notion of the media's logical geometry */ 4497 struct dk_geom disk_geom; 4498 struct dk_geom *dkgp = &disk_geom; 4499 4500 mutex_enter(CMLB_MUTEX(cl)); 4501 /* 4502 * If there is no HBA geometry available, or 4503 * if the HBA returned us something that doesn't 4504 * really fit into an Int 13/function 8 geometry 4505 * result, just fail the ioctl. See PSARC 1998/313. 4506 */ 4507 if (cl->cl_lgeom.g_nhead == 0 || 4508 cl->cl_lgeom.g_nsect == 0 || 4509 cl->cl_lgeom.g_ncyl > 1024) { 4510 mutex_exit(CMLB_MUTEX(cl)); 4511 err = EINVAL; 4512 } else { 4513 dkgp->dkg_ncyl = cl->cl_lgeom.g_ncyl; 4514 dkgp->dkg_acyl = cl->cl_lgeom.g_acyl; 4515 dkgp->dkg_pcyl = dkgp->dkg_ncyl + dkgp->dkg_acyl; 4516 dkgp->dkg_nhead = cl->cl_lgeom.g_nhead; 4517 dkgp->dkg_nsect = cl->cl_lgeom.g_nsect; 4518 4519 mutex_exit(CMLB_MUTEX(cl)); 4520 if (ddi_copyout(dkgp, (void *)arg, 4521 sizeof (struct dk_geom), flag)) { 4522 err = EFAULT; 4523 } else { 4524 err = 0; 4525 } 4526 } 4527 return (err); 4528 } 4529 #endif 4530 4531 #if defined(__i386) || defined(__amd64) 4532 static int 4533 cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t arg, int flag) 4534 { 4535 int err = 0; 4536 diskaddr_t capacity; 4537 4538 4539 /* Return the driver's notion of the media physical geometry */ 4540 struct dk_geom disk_geom; 4541 struct dk_geom *dkgp = &disk_geom; 4542 4543 mutex_enter(CMLB_MUTEX(cl)); 4544 4545 if (cl->cl_g.dkg_nhead != 0 && 4546 cl->cl_g.dkg_nsect != 0) { 4547 /* 4548 * We succeeded in getting a geometry, but 4549 * right now it is being reported as just the 4550 * Solaris fdisk partition, just like for 4551 * DKIOCGGEOM. We need to change that to be 4552 * correct for the entire disk now. 4553 */ 4554 bcopy(&cl->cl_g, dkgp, sizeof (*dkgp)); 4555 dkgp->dkg_acyl = 0; 4556 dkgp->dkg_ncyl = cl->cl_blockcount / 4557 (dkgp->dkg_nhead * dkgp->dkg_nsect); 4558 } else { 4559 bzero(dkgp, sizeof (struct dk_geom)); 4560 /* 4561 * This disk does not have a Solaris VTOC 4562 * so we must present a physical geometry 4563 * that will remain consistent regardless 4564 * of how the disk is used. This will ensure 4565 * that the geometry does not change regardless 4566 * of the fdisk partition type (ie. EFI, FAT32, 4567 * Solaris, etc). 4568 */ 4569 if (ISCD(cl)) { 4570 dkgp->dkg_nhead = cl->cl_pgeom.g_nhead; 4571 dkgp->dkg_nsect = cl->cl_pgeom.g_nsect; 4572 dkgp->dkg_ncyl = cl->cl_pgeom.g_ncyl; 4573 dkgp->dkg_acyl = cl->cl_pgeom.g_acyl; 4574 } else { 4575 /* 4576 * Invalid cl_blockcount can generate invalid 4577 * dk_geom and may result in division by zero 4578 * system failure. Should make sure blockcount 4579 * is valid before using it here. 4580 */ 4581 if (cl->cl_blockcount == 0) { 4582 mutex_exit(CMLB_MUTEX(cl)); 4583 err = EIO; 4584 return (err); 4585 } 4586 /* 4587 * Refer to comments related to off-by-1 at the 4588 * header of this file 4589 */ 4590 if (cl->cl_alter_behavior & CMLB_OFF_BY_ONE) 4591 capacity = cl->cl_blockcount - 1; 4592 else 4593 capacity = cl->cl_blockcount; 4594 4595 cmlb_convert_geometry(capacity, dkgp); 4596 dkgp->dkg_acyl = 0; 4597 dkgp->dkg_ncyl = capacity / 4598 (dkgp->dkg_nhead * dkgp->dkg_nsect); 4599 } 4600 } 4601 dkgp->dkg_pcyl = dkgp->dkg_ncyl + dkgp->dkg_acyl; 4602 4603 mutex_exit(CMLB_MUTEX(cl)); 4604 if (ddi_copyout(dkgp, (void *)arg, sizeof (struct dk_geom), flag)) 4605 err = EFAULT; 4606 4607 return (err); 4608 } 4609 #endif 4610 4611 #if defined(__i386) || defined(__amd64) 4612 static int 4613 cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag) 4614 { 4615 int err = 0; 4616 4617 /* 4618 * Return parameters describing the selected disk slice. 4619 * Note: this ioctl is for the intel platform only 4620 */ 4621 int part; 4622 4623 part = CMLBPART(dev); 4624 4625 mutex_enter(CMLB_MUTEX(cl)); 4626 /* don't check cl_solaris_size for pN */ 4627 if (part < P0_RAW_DISK && cl->cl_solaris_size == 0) { 4628 err = EIO; 4629 mutex_exit(CMLB_MUTEX(cl)); 4630 } else { 4631 struct part_info p; 4632 4633 p.p_start = (daddr_t)cl->cl_offset[part]; 4634 p.p_length = (int)cl->cl_map[part].dkl_nblk; 4635 mutex_exit(CMLB_MUTEX(cl)); 4636 #ifdef _MULTI_DATAMODEL 4637 switch (ddi_model_convert_from(flag & FMODELS)) { 4638 case DDI_MODEL_ILP32: 4639 { 4640 struct part_info32 p32; 4641 4642 p32.p_start = (daddr32_t)p.p_start; 4643 p32.p_length = p.p_length; 4644 if (ddi_copyout(&p32, (void *)arg, 4645 sizeof (p32), flag)) 4646 err = EFAULT; 4647 break; 4648 } 4649 4650 case DDI_MODEL_NONE: 4651 { 4652 if (ddi_copyout(&p, (void *)arg, sizeof (p), 4653 flag)) 4654 err = EFAULT; 4655 break; 4656 } 4657 } 4658 #else /* ! _MULTI_DATAMODEL */ 4659 if (ddi_copyout(&p, (void *)arg, sizeof (p), flag)) 4660 err = EFAULT; 4661 #endif /* _MULTI_DATAMODEL */ 4662 } 4663 return (err); 4664 } 4665 #endif 4666