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