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