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 #endif 2299 2300 ASSERT(cl != NULL); 2301 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2302 2303 /* 2304 * Start off assuming no fdisk table 2305 */ 2306 solaris_offset = 0; 2307 solaris_size = capacity; 2308 2309 blocksize = cl->cl_tgt_blocksize; 2310 2311 bufp = kmem_zalloc(blocksize, KM_SLEEP); 2312 2313 mutex_exit(CMLB_MUTEX(cl)); 2314 rval = DK_TG_READ(cl, bufp, 0, blocksize, tg_cookie); 2315 mutex_enter(CMLB_MUTEX(cl)); 2316 2317 if (rval != 0) { 2318 cmlb_dbg(CMLB_ERROR, cl, 2319 "cmlb_read_fdisk: fdisk read err\n"); 2320 bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART); 2321 goto done; 2322 } 2323 2324 mbp = (struct mboot *)bufp; 2325 2326 /* 2327 * The fdisk table does not begin on a 4-byte boundary within the 2328 * master boot record, so we copy it to an aligned structure to avoid 2329 * alignment exceptions on some processors. 2330 */ 2331 bcopy(&mbp->parts[0], fdisk, sizeof (fdisk)); 2332 2333 /* 2334 * Check for lba support before verifying sig; sig might not be 2335 * there, say on a blank disk, but the max_chs mark may still 2336 * be present. 2337 * 2338 * Note: LBA support and BEFs are an x86-only concept but this 2339 * code should work OK on SPARC as well. 2340 */ 2341 2342 /* 2343 * First, check for lba-access-ok on root node (or prom root node) 2344 * if present there, don't need to search fdisk table. 2345 */ 2346 if (ddi_getprop(DDI_DEV_T_ANY, ddi_root_node(), 0, 2347 "lba-access-ok", 0) != 0) { 2348 /* All drives do LBA; don't search fdisk table */ 2349 lba = 1; 2350 } else { 2351 /* Okay, look for mark in fdisk table */ 2352 for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { 2353 /* accumulate "lba" value from all partitions */ 2354 lba = (lba || cmlb_has_max_chs_vals(fdp)); 2355 } 2356 } 2357 2358 if (lba != 0) { 2359 dev_t dev = cmlb_make_device(cl); 2360 2361 if (ddi_getprop(dev, CMLB_DEVINFO(cl), DDI_PROP_DONTPASS, 2362 "lba-access-ok", 0) == 0) { 2363 /* not found; create it */ 2364 if (ddi_prop_create(dev, CMLB_DEVINFO(cl), 0, 2365 "lba-access-ok", (caddr_t)NULL, 0) != 2366 DDI_PROP_SUCCESS) { 2367 cmlb_dbg(CMLB_ERROR, cl, 2368 "cmlb_read_fdisk: Can't create lba " 2369 "property for instance %d\n", 2370 ddi_get_instance(CMLB_DEVINFO(cl))); 2371 } 2372 } 2373 } 2374 2375 bcopy(&mbp->signature, sigbuf, sizeof (sigbuf)); 2376 2377 /* 2378 * Endian-independent signature check 2379 */ 2380 if (((sigbuf[1] & 0xFF) != ((MBB_MAGIC >> 8) & 0xFF)) || 2381 (sigbuf[0] != (MBB_MAGIC & 0xFF))) { 2382 cmlb_dbg(CMLB_ERROR, cl, 2383 "cmlb_read_fdisk: no fdisk\n"); 2384 bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART); 2385 goto done; 2386 } 2387 2388 #ifdef CMLBDEBUG 2389 if (cmlb_level_mask & CMLB_LOGMASK_INFO) { 2390 fdp = fdisk; 2391 cmlb_dbg(CMLB_INFO, cl, "cmlb_read_fdisk:\n"); 2392 cmlb_dbg(CMLB_INFO, cl, " relsect " 2393 "numsect sysid bootid\n"); 2394 for (i = 0; i < FD_NUMPART; i++, fdp++) { 2395 cmlb_dbg(CMLB_INFO, cl, 2396 " %d: %8d %8d 0x%08x 0x%08x\n", 2397 i, fdp->relsect, fdp->numsect, 2398 fdp->systid, fdp->bootid); 2399 } 2400 } 2401 #endif 2402 2403 /* 2404 * Try to find the unix partition 2405 */ 2406 uidx = -1; 2407 solaris_offset = 0; 2408 solaris_size = 0; 2409 2410 for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { 2411 uint32_t relsect; 2412 uint32_t numsect; 2413 uchar_t systid; 2414 #if defined(__i386) || defined(__amd64) 2415 /* 2416 * Stores relative block offset from the beginning of the 2417 * Extended Partition. 2418 */ 2419 int ext_relsect = 0; 2420 #endif 2421 2422 if (fdp->numsect == 0) { 2423 cl->cl_fmap[i].fmap_start = 0; 2424 cl->cl_fmap[i].fmap_nblk = 0; 2425 continue; 2426 } 2427 2428 /* 2429 * Data in the fdisk table is little-endian. 2430 */ 2431 relsect = LE_32(fdp->relsect); 2432 numsect = LE_32(fdp->numsect); 2433 2434 cl->cl_fmap[i].fmap_start = relsect; 2435 cl->cl_fmap[i].fmap_nblk = numsect; 2436 cl->cl_fmap[i].fmap_systid = LE_8(fdp->systid); 2437 2438 #if defined(__i386) || defined(__amd64) 2439 /* Support only one extended partition per LUN */ 2440 if ((fdp->systid == EXTDOS || fdp->systid == FDISK_EXTLBA) && 2441 (ext_part_exists == 0)) { 2442 int j; 2443 uint32_t logdrive_offset; 2444 uint32_t ext_numsect; 2445 uint32_t abs_secnum; 2446 int is_linux_swap; 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 if (cmlb_is_linux_swap(cl, relsect, tg_cookie) != 0) { 2543 #endif 2544 uidx = i; 2545 solaris_offset = relsect; 2546 solaris_size = numsect; 2547 #if defined(__i386) || defined(__amd64) 2548 } 2549 #endif 2550 } 2551 } 2552 #if defined(__i386) || defined(__amd64) 2553 if (ld_count < cl->cl_logical_drive_count) { 2554 /* 2555 * Some/all logical drives were deleted. Clear out 2556 * the fmap entries correspoding to those deleted drives. 2557 */ 2558 for (k = ld_count + FD_NUMPART; 2559 k < cl->cl_logical_drive_count + FD_NUMPART; k++) { 2560 cl->cl_fmap[k].fmap_start = 0; 2561 cl->cl_fmap[k].fmap_nblk = 0; 2562 cl->cl_fmap[k].fmap_systid = 0; 2563 } 2564 cl->cl_update_ext_minor_nodes = 1; 2565 } 2566 if (cl->cl_update_ext_minor_nodes) { 2567 rval = cmlb_update_ext_minor_nodes(cl, ld_count); 2568 if (rval != 0) { 2569 goto done; 2570 } 2571 } 2572 #endif 2573 cmlb_dbg(CMLB_INFO, cl, "fdisk 0x%x 0x%lx", 2574 cl->cl_solaris_offset, cl->cl_solaris_size); 2575 done: 2576 2577 /* 2578 * Clear the VTOC info, only if the Solaris partition entry 2579 * has moved, changed size, been deleted, or if the size of 2580 * the partition is too small to even fit the label sector. 2581 */ 2582 if ((cl->cl_solaris_offset != solaris_offset) || 2583 (cl->cl_solaris_size != solaris_size) || 2584 solaris_size <= DK_LABEL_LOC) { 2585 cmlb_dbg(CMLB_INFO, cl, "fdisk moved 0x%x 0x%lx", 2586 solaris_offset, solaris_size); 2587 bzero(&cl->cl_g, sizeof (struct dk_geom)); 2588 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 2589 bzero(&cl->cl_map, NDKMAP * (sizeof (struct dk_map))); 2590 cl->cl_f_geometry_is_valid = B_FALSE; 2591 } 2592 cl->cl_solaris_offset = solaris_offset; 2593 cl->cl_solaris_size = solaris_size; 2594 kmem_free(bufp, blocksize); 2595 return (rval); 2596 2597 #else /* #elif defined(_FIRMWARE_NEEDS_FDISK) */ 2598 #error "fdisk table presence undetermined for this platform." 2599 #endif /* #if defined(_NO_FDISK_PRESENT) */ 2600 } 2601 2602 static void 2603 cmlb_swap_efi_gpt(efi_gpt_t *e) 2604 { 2605 _NOTE(ASSUMING_PROTECTED(*e)) 2606 e->efi_gpt_Signature = LE_64(e->efi_gpt_Signature); 2607 e->efi_gpt_Revision = LE_32(e->efi_gpt_Revision); 2608 e->efi_gpt_HeaderSize = LE_32(e->efi_gpt_HeaderSize); 2609 e->efi_gpt_HeaderCRC32 = LE_32(e->efi_gpt_HeaderCRC32); 2610 e->efi_gpt_MyLBA = LE_64(e->efi_gpt_MyLBA); 2611 e->efi_gpt_AlternateLBA = LE_64(e->efi_gpt_AlternateLBA); 2612 e->efi_gpt_FirstUsableLBA = LE_64(e->efi_gpt_FirstUsableLBA); 2613 e->efi_gpt_LastUsableLBA = LE_64(e->efi_gpt_LastUsableLBA); 2614 UUID_LE_CONVERT(e->efi_gpt_DiskGUID, e->efi_gpt_DiskGUID); 2615 e->efi_gpt_PartitionEntryLBA = LE_64(e->efi_gpt_PartitionEntryLBA); 2616 e->efi_gpt_NumberOfPartitionEntries = 2617 LE_32(e->efi_gpt_NumberOfPartitionEntries); 2618 e->efi_gpt_SizeOfPartitionEntry = 2619 LE_32(e->efi_gpt_SizeOfPartitionEntry); 2620 e->efi_gpt_PartitionEntryArrayCRC32 = 2621 LE_32(e->efi_gpt_PartitionEntryArrayCRC32); 2622 } 2623 2624 static void 2625 cmlb_swap_efi_gpe(int nparts, efi_gpe_t *p) 2626 { 2627 int i; 2628 2629 _NOTE(ASSUMING_PROTECTED(*p)) 2630 for (i = 0; i < nparts; i++) { 2631 UUID_LE_CONVERT(p[i].efi_gpe_PartitionTypeGUID, 2632 p[i].efi_gpe_PartitionTypeGUID); 2633 p[i].efi_gpe_StartingLBA = LE_64(p[i].efi_gpe_StartingLBA); 2634 p[i].efi_gpe_EndingLBA = LE_64(p[i].efi_gpe_EndingLBA); 2635 /* PartitionAttrs */ 2636 } 2637 } 2638 2639 static int 2640 cmlb_validate_efi(efi_gpt_t *labp) 2641 { 2642 if (labp->efi_gpt_Signature != EFI_SIGNATURE) 2643 return (EINVAL); 2644 /* at least 96 bytes in this version of the spec. */ 2645 if (sizeof (efi_gpt_t) - sizeof (labp->efi_gpt_Reserved2) > 2646 labp->efi_gpt_HeaderSize) 2647 return (EINVAL); 2648 /* this should be 128 bytes */ 2649 if (labp->efi_gpt_SizeOfPartitionEntry != sizeof (efi_gpe_t)) 2650 return (EINVAL); 2651 return (0); 2652 } 2653 2654 /* 2655 * This function returns B_FALSE if there is a valid MBR signature and no 2656 * partition table entries of type EFI_PMBR (0xEE). Otherwise it returns B_TRUE. 2657 * 2658 * The EFI spec (1.10 and later) requires having a Protective MBR (PMBR) to 2659 * recognize the disk as GPT partitioned. However, some other OS creates an MBR 2660 * where a PMBR entry is not the only one. Also, if the first block has been 2661 * corrupted, currently best attempt to allow data access would be to try to 2662 * check for GPT headers. Hence in case of more than one partition entry, but 2663 * at least one EFI_PMBR partition type or no valid magic number, the function 2664 * returns B_TRUE to continue with looking for GPT header. 2665 */ 2666 2667 static boolean_t 2668 cmlb_check_efi_mbr(uchar_t *buf, boolean_t *is_mbr) 2669 { 2670 struct ipart *fdp; 2671 struct mboot *mbp = (struct mboot *)buf; 2672 struct ipart fdisk[FD_NUMPART]; 2673 int i; 2674 2675 if (is_mbr != NULL) 2676 *is_mbr = B_TRUE; 2677 2678 if (LE_16(mbp->signature) != MBB_MAGIC) { 2679 if (is_mbr != NULL) 2680 *is_mbr = B_FALSE; 2681 return (B_TRUE); 2682 } 2683 2684 bcopy(&mbp->parts[0], fdisk, sizeof (fdisk)); 2685 2686 for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { 2687 if (fdp->systid == EFI_PMBR) 2688 return (B_TRUE); 2689 } 2690 2691 return (B_FALSE); 2692 } 2693 2694 static int 2695 cmlb_use_efi(struct cmlb_lun *cl, diskaddr_t capacity, int flags, 2696 void *tg_cookie) 2697 { 2698 int i; 2699 int rval = 0; 2700 efi_gpe_t *partitions; 2701 uchar_t *buf; 2702 uint_t lbasize; /* is really how much to read */ 2703 diskaddr_t cap = 0; 2704 uint_t nparts; 2705 diskaddr_t gpe_lba; 2706 diskaddr_t alternate_lba; 2707 int iofailed = 0; 2708 struct uuid uuid_type_reserved = EFI_RESERVED; 2709 #if defined(_FIRMWARE_NEEDS_FDISK) 2710 boolean_t is_mbr; 2711 #endif 2712 2713 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2714 2715 lbasize = cl->cl_sys_blocksize; 2716 2717 cl->cl_reserved = -1; 2718 mutex_exit(CMLB_MUTEX(cl)); 2719 2720 buf = kmem_zalloc(EFI_MIN_ARRAY_SIZE, KM_SLEEP); 2721 2722 rval = DK_TG_READ(cl, buf, 0, lbasize, tg_cookie); 2723 if (rval) { 2724 iofailed = 1; 2725 goto done_err; 2726 } 2727 if (((struct dk_label *)buf)->dkl_magic == DKL_MAGIC) { 2728 /* not ours */ 2729 rval = ESRCH; 2730 goto done_err; 2731 } 2732 2733 #if defined(_FIRMWARE_NEEDS_FDISK) 2734 if (!cmlb_check_efi_mbr(buf, &is_mbr)) { 2735 if (is_mbr) 2736 rval = ESRCH; 2737 else 2738 rval = EINVAL; 2739 goto done_err; 2740 } 2741 #else 2742 if (!cmlb_check_efi_mbr(buf, NULL)) { 2743 rval = EINVAL; 2744 goto done_err; 2745 } 2746 2747 #endif 2748 2749 rval = DK_TG_READ(cl, buf, 1, lbasize, tg_cookie); 2750 if (rval) { 2751 iofailed = 1; 2752 goto done_err; 2753 } 2754 cmlb_swap_efi_gpt((efi_gpt_t *)buf); 2755 2756 if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) { 2757 /* 2758 * Couldn't read the primary, try the backup. Our 2759 * capacity at this point could be based on CHS, so 2760 * check what the device reports. 2761 */ 2762 rval = DK_TG_GETCAP(cl, &cap, tg_cookie); 2763 if (rval) { 2764 iofailed = 1; 2765 goto done_err; 2766 } 2767 2768 /* 2769 * CMLB_OFF_BY_ONE case, we check the next to last block first 2770 * for backup GPT header, otherwise check the last block. 2771 */ 2772 2773 if ((rval = DK_TG_READ(cl, buf, 2774 cap - ((cl->cl_alter_behavior & CMLB_OFF_BY_ONE) ? 2 : 1), 2775 lbasize, tg_cookie)) 2776 != 0) { 2777 iofailed = 1; 2778 goto done_err; 2779 } 2780 cmlb_swap_efi_gpt((efi_gpt_t *)buf); 2781 2782 if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) { 2783 2784 if (!(cl->cl_alter_behavior & CMLB_OFF_BY_ONE)) 2785 goto done_err; 2786 if ((rval = DK_TG_READ(cl, buf, cap - 1, lbasize, 2787 tg_cookie)) != 0) 2788 goto done_err; 2789 cmlb_swap_efi_gpt((efi_gpt_t *)buf); 2790 if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) 2791 goto done_err; 2792 } 2793 if (!(flags & CMLB_SILENT)) 2794 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 2795 "primary label corrupt; using backup\n"); 2796 } 2797 2798 nparts = ((efi_gpt_t *)buf)->efi_gpt_NumberOfPartitionEntries; 2799 gpe_lba = ((efi_gpt_t *)buf)->efi_gpt_PartitionEntryLBA; 2800 alternate_lba = ((efi_gpt_t *)buf)->efi_gpt_AlternateLBA; 2801 2802 rval = DK_TG_READ(cl, buf, gpe_lba, EFI_MIN_ARRAY_SIZE, tg_cookie); 2803 if (rval) { 2804 iofailed = 1; 2805 goto done_err; 2806 } 2807 partitions = (efi_gpe_t *)buf; 2808 2809 if (nparts > MAXPART) { 2810 nparts = MAXPART; 2811 } 2812 cmlb_swap_efi_gpe(nparts, partitions); 2813 2814 mutex_enter(CMLB_MUTEX(cl)); 2815 2816 /* Fill in partition table. */ 2817 for (i = 0; i < nparts; i++) { 2818 if (partitions->efi_gpe_StartingLBA != 0 || 2819 partitions->efi_gpe_EndingLBA != 0) { 2820 cl->cl_map[i].dkl_cylno = 2821 partitions->efi_gpe_StartingLBA; 2822 cl->cl_map[i].dkl_nblk = 2823 partitions->efi_gpe_EndingLBA - 2824 partitions->efi_gpe_StartingLBA + 1; 2825 cl->cl_offset[i] = 2826 partitions->efi_gpe_StartingLBA; 2827 } 2828 2829 if (cl->cl_reserved == -1) { 2830 if (bcmp(&partitions->efi_gpe_PartitionTypeGUID, 2831 &uuid_type_reserved, sizeof (struct uuid)) == 0) { 2832 cl->cl_reserved = i; 2833 } 2834 } 2835 if (i == WD_NODE) { 2836 /* 2837 * minor number 7 corresponds to the whole disk 2838 * if the disk capacity is expanded after disk is 2839 * labeled, minor number 7 represents the capacity 2840 * indicated by the disk label. 2841 */ 2842 cl->cl_map[i].dkl_cylno = 0; 2843 if (alternate_lba == 1) { 2844 /* 2845 * We are using backup label. Since we can 2846 * find a valid label at the end of disk, 2847 * the disk capacity is not expanded. 2848 */ 2849 cl->cl_map[i].dkl_nblk = capacity; 2850 } else { 2851 cl->cl_map[i].dkl_nblk = alternate_lba + 1; 2852 } 2853 cl->cl_offset[i] = 0; 2854 } 2855 partitions++; 2856 } 2857 cl->cl_solaris_offset = 0; 2858 cl->cl_solaris_size = capacity; 2859 cl->cl_label_from_media = CMLB_LABEL_EFI; 2860 cl->cl_f_geometry_is_valid = B_TRUE; 2861 2862 /* clear the vtoc label */ 2863 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 2864 2865 kmem_free(buf, EFI_MIN_ARRAY_SIZE); 2866 return (0); 2867 2868 done_err: 2869 kmem_free(buf, EFI_MIN_ARRAY_SIZE); 2870 mutex_enter(CMLB_MUTEX(cl)); 2871 done_err1: 2872 /* 2873 * if we didn't find something that could look like a VTOC 2874 * and the disk is over 1TB, we know there isn't a valid label. 2875 * Otherwise let cmlb_uselabel decide what to do. We only 2876 * want to invalidate this if we're certain the label isn't 2877 * valid because cmlb_prop_op will now fail, which in turn 2878 * causes things like opens and stats on the partition to fail. 2879 */ 2880 if ((capacity > CMLB_EXTVTOC_LIMIT) && (rval != ESRCH) && !iofailed) { 2881 cl->cl_f_geometry_is_valid = B_FALSE; 2882 } 2883 return (rval); 2884 } 2885 2886 2887 /* 2888 * Function: cmlb_uselabel 2889 * 2890 * Description: Validate the disk label and update the relevant data (geometry, 2891 * partition, vtoc, and capacity data) in the cmlb_lun struct. 2892 * Marks the geometry of the unit as being valid. 2893 * 2894 * Arguments: cl: unit struct. 2895 * dk_label: disk label 2896 * 2897 * Return Code: CMLB_LABEL_IS_VALID: Label read from disk is OK; geometry, 2898 * partition, vtoc, and capacity data are good. 2899 * 2900 * CMLB_LABEL_IS_INVALID: Magic number or checksum error in the 2901 * label; or computed capacity does not jibe with capacity 2902 * reported from the READ CAPACITY command. 2903 * 2904 * Context: Kernel thread only (can sleep). 2905 */ 2906 static int 2907 cmlb_uselabel(struct cmlb_lun *cl, struct dk_label *labp, int flags) 2908 { 2909 short *sp; 2910 short sum; 2911 short count; 2912 int label_error = CMLB_LABEL_IS_VALID; 2913 int i; 2914 diskaddr_t label_capacity; 2915 uint32_t part_end; 2916 diskaddr_t track_capacity; 2917 #if defined(_SUNOS_VTOC_16) 2918 struct dkl_partition *vpartp; 2919 #endif 2920 ASSERT(cl != NULL); 2921 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2922 2923 /* Validate the magic number of the label. */ 2924 if (labp->dkl_magic != DKL_MAGIC) { 2925 #if defined(__sparc) 2926 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 2927 if (!(flags & CMLB_SILENT)) 2928 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 2929 CE_WARN, 2930 "Corrupt label; wrong magic number\n"); 2931 } 2932 #endif 2933 return (CMLB_LABEL_IS_INVALID); 2934 } 2935 2936 /* Validate the checksum of the label. */ 2937 sp = (short *)labp; 2938 sum = 0; 2939 count = sizeof (struct dk_label) / sizeof (short); 2940 while (count--) { 2941 sum ^= *sp++; 2942 } 2943 2944 if (sum != 0) { 2945 #if defined(_SUNOS_VTOC_16) 2946 if (!ISCD(cl)) { 2947 #elif defined(_SUNOS_VTOC_8) 2948 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 2949 #endif 2950 if (!(flags & CMLB_SILENT)) 2951 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 2952 CE_WARN, 2953 "Corrupt label - label checksum failed\n"); 2954 } 2955 return (CMLB_LABEL_IS_INVALID); 2956 } 2957 2958 2959 /* 2960 * Fill in geometry structure with data from label. 2961 */ 2962 bzero(&cl->cl_g, sizeof (struct dk_geom)); 2963 cl->cl_g.dkg_ncyl = labp->dkl_ncyl; 2964 cl->cl_g.dkg_acyl = labp->dkl_acyl; 2965 cl->cl_g.dkg_bcyl = 0; 2966 cl->cl_g.dkg_nhead = labp->dkl_nhead; 2967 cl->cl_g.dkg_nsect = labp->dkl_nsect; 2968 cl->cl_g.dkg_intrlv = labp->dkl_intrlv; 2969 2970 #if defined(_SUNOS_VTOC_8) 2971 cl->cl_g.dkg_gap1 = labp->dkl_gap1; 2972 cl->cl_g.dkg_gap2 = labp->dkl_gap2; 2973 cl->cl_g.dkg_bhead = labp->dkl_bhead; 2974 #endif 2975 #if defined(_SUNOS_VTOC_16) 2976 cl->cl_dkg_skew = labp->dkl_skew; 2977 #endif 2978 2979 #if defined(__i386) || defined(__amd64) 2980 cl->cl_g.dkg_apc = labp->dkl_apc; 2981 #endif 2982 2983 /* 2984 * Currently we rely on the values in the label being accurate. If 2985 * dkl_rpm or dkl_pcly are zero in the label, use a default value. 2986 * 2987 * Note: In the future a MODE SENSE may be used to retrieve this data, 2988 * although this command is optional in SCSI-2. 2989 */ 2990 cl->cl_g.dkg_rpm = (labp->dkl_rpm != 0) ? labp->dkl_rpm : 3600; 2991 cl->cl_g.dkg_pcyl = (labp->dkl_pcyl != 0) ? labp->dkl_pcyl : 2992 (cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl); 2993 2994 /* 2995 * The Read and Write reinstruct values may not be valid 2996 * for older disks. 2997 */ 2998 cl->cl_g.dkg_read_reinstruct = labp->dkl_read_reinstruct; 2999 cl->cl_g.dkg_write_reinstruct = labp->dkl_write_reinstruct; 3000 3001 /* Fill in partition table. */ 3002 #if defined(_SUNOS_VTOC_8) 3003 for (i = 0; i < NDKMAP; i++) { 3004 cl->cl_map[i].dkl_cylno = labp->dkl_map[i].dkl_cylno; 3005 cl->cl_map[i].dkl_nblk = labp->dkl_map[i].dkl_nblk; 3006 } 3007 #endif 3008 #if defined(_SUNOS_VTOC_16) 3009 vpartp = labp->dkl_vtoc.v_part; 3010 track_capacity = labp->dkl_nhead * labp->dkl_nsect; 3011 3012 /* Prevent divide by zero */ 3013 if (track_capacity == 0) { 3014 if (!(flags & CMLB_SILENT)) 3015 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 3016 "Corrupt label - zero nhead or nsect value\n"); 3017 3018 return (CMLB_LABEL_IS_INVALID); 3019 } 3020 3021 for (i = 0; i < NDKMAP; i++, vpartp++) { 3022 cl->cl_map[i].dkl_cylno = vpartp->p_start / track_capacity; 3023 cl->cl_map[i].dkl_nblk = vpartp->p_size; 3024 } 3025 #endif 3026 3027 /* Fill in VTOC Structure. */ 3028 bcopy(&labp->dkl_vtoc, &cl->cl_vtoc, sizeof (struct dk_vtoc)); 3029 #if defined(_SUNOS_VTOC_8) 3030 /* 3031 * The 8-slice vtoc does not include the ascii label; save it into 3032 * the device's soft state structure here. 3033 */ 3034 bcopy(labp->dkl_asciilabel, cl->cl_asciilabel, LEN_DKL_ASCII); 3035 #endif 3036 3037 /* Now look for a valid capacity. */ 3038 track_capacity = (cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect); 3039 label_capacity = (cl->cl_g.dkg_ncyl * track_capacity); 3040 3041 if (cl->cl_g.dkg_acyl) { 3042 #if defined(__i386) || defined(__amd64) 3043 /* we may have > 1 alts cylinder */ 3044 label_capacity += (track_capacity * cl->cl_g.dkg_acyl); 3045 #else 3046 label_capacity += track_capacity; 3047 #endif 3048 } 3049 3050 /* 3051 * Force check here to ensure the computed capacity is valid. 3052 * If capacity is zero, it indicates an invalid label and 3053 * we should abort updating the relevant data then. 3054 */ 3055 if (label_capacity == 0) { 3056 if (!(flags & CMLB_SILENT)) 3057 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 3058 "Corrupt label - no valid capacity could be " 3059 "retrieved\n"); 3060 3061 return (CMLB_LABEL_IS_INVALID); 3062 } 3063 3064 /* Mark the geometry as valid. */ 3065 cl->cl_f_geometry_is_valid = B_TRUE; 3066 3067 /* 3068 * if we got invalidated when mutex exit and entered again, 3069 * if blockcount different than when we came in, need to 3070 * retry from beginning of cmlb_validate_geometry. 3071 * revisit this on next phase of utilizing this for 3072 * sd. 3073 */ 3074 3075 if (label_capacity <= cl->cl_blockcount) { 3076 #if defined(_SUNOS_VTOC_8) 3077 /* 3078 * We can't let this happen on drives that are subdivided 3079 * into logical disks (i.e., that have an fdisk table). 3080 * The cl_blockcount field should always hold the full media 3081 * size in sectors, period. This code would overwrite 3082 * cl_blockcount with the size of the Solaris fdisk partition. 3083 */ 3084 cmlb_dbg(CMLB_ERROR, cl, 3085 "cmlb_uselabel: Label %d blocks; Drive %d blocks\n", 3086 label_capacity, cl->cl_blockcount); 3087 cl->cl_solaris_size = label_capacity; 3088 3089 #endif /* defined(_SUNOS_VTOC_8) */ 3090 goto done; 3091 } 3092 3093 if (ISCD(cl)) { 3094 /* For CDROMs, we trust that the data in the label is OK. */ 3095 #if defined(_SUNOS_VTOC_8) 3096 for (i = 0; i < NDKMAP; i++) { 3097 part_end = labp->dkl_nhead * labp->dkl_nsect * 3098 labp->dkl_map[i].dkl_cylno + 3099 labp->dkl_map[i].dkl_nblk - 1; 3100 3101 if ((labp->dkl_map[i].dkl_nblk) && 3102 (part_end > cl->cl_blockcount)) { 3103 cl->cl_f_geometry_is_valid = B_FALSE; 3104 break; 3105 } 3106 } 3107 #endif 3108 #if defined(_SUNOS_VTOC_16) 3109 vpartp = &(labp->dkl_vtoc.v_part[0]); 3110 for (i = 0; i < NDKMAP; i++, vpartp++) { 3111 part_end = vpartp->p_start + vpartp->p_size; 3112 if ((vpartp->p_size > 0) && 3113 (part_end > cl->cl_blockcount)) { 3114 cl->cl_f_geometry_is_valid = B_FALSE; 3115 break; 3116 } 3117 } 3118 #endif 3119 } else { 3120 /* label_capacity > cl->cl_blockcount */ 3121 if (!(flags & CMLB_SILENT)) { 3122 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 3123 "Corrupt label - bad geometry\n"); 3124 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_CONT, 3125 "Label says %llu blocks; Drive says %llu blocks\n", 3126 label_capacity, cl->cl_blockcount); 3127 } 3128 cl->cl_f_geometry_is_valid = B_FALSE; 3129 label_error = CMLB_LABEL_IS_INVALID; 3130 } 3131 3132 done: 3133 3134 cmlb_dbg(CMLB_INFO, cl, "cmlb_uselabel: (label geometry)\n"); 3135 cmlb_dbg(CMLB_INFO, cl, 3136 " ncyl: %d; acyl: %d; nhead: %d; nsect: %d\n", 3137 cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, 3138 cl->cl_g.dkg_nhead, cl->cl_g.dkg_nsect); 3139 3140 cmlb_dbg(CMLB_INFO, cl, 3141 " label_capacity: %d; intrlv: %d; rpm: %d\n", 3142 cl->cl_blockcount, cl->cl_g.dkg_intrlv, cl->cl_g.dkg_rpm); 3143 cmlb_dbg(CMLB_INFO, cl, " wrt_reinstr: %d; rd_reinstr: %d\n", 3144 cl->cl_g.dkg_write_reinstruct, cl->cl_g.dkg_read_reinstruct); 3145 3146 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 3147 3148 return (label_error); 3149 } 3150 3151 3152 /* 3153 * Function: cmlb_build_default_label 3154 * 3155 * Description: Generate a default label for those devices that do not have 3156 * one, e.g., new media, removable cartridges, etc.. 3157 * 3158 * Context: Kernel thread only 3159 */ 3160 /*ARGSUSED*/ 3161 static void 3162 cmlb_build_default_label(struct cmlb_lun *cl, void *tg_cookie) 3163 { 3164 #if defined(_SUNOS_VTOC_16) 3165 uint_t phys_spc; 3166 uint_t disksize; 3167 struct dk_geom cl_g; 3168 diskaddr_t capacity; 3169 #endif 3170 3171 ASSERT(cl != NULL); 3172 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 3173 3174 #if defined(_SUNOS_VTOC_8) 3175 /* 3176 * Note: This is a legacy check for non-removable devices on VTOC_8 3177 * only. This may be a valid check for VTOC_16 as well. 3178 * Once we understand why there is this difference between SPARC and 3179 * x86 platform, we could remove this legacy check. 3180 */ 3181 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 3182 return; 3183 } 3184 #endif 3185 3186 bzero(&cl->cl_g, sizeof (struct dk_geom)); 3187 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 3188 bzero(&cl->cl_map, NDKMAP * (sizeof (struct dk_map))); 3189 3190 #if defined(_SUNOS_VTOC_8) 3191 3192 /* 3193 * It's a REMOVABLE media, therefore no label (on sparc, anyway). 3194 * But it is still necessary to set up various geometry information, 3195 * and we are doing this here. 3196 */ 3197 3198 /* 3199 * For the rpm, we use the minimum for the disk. For the head, cyl, 3200 * and number of sector per track, if the capacity <= 1GB, head = 64, 3201 * sect = 32. else head = 255, sect 63 Note: the capacity should be 3202 * equal to C*H*S values. This will cause some truncation of size due 3203 * to round off errors. For CD-ROMs, this truncation can have adverse 3204 * side effects, so returning ncyl and nhead as 1. The nsect will 3205 * overflow for most of CD-ROMs as nsect is of type ushort. (4190569) 3206 */ 3207 cl->cl_solaris_size = cl->cl_blockcount; 3208 if (ISCD(cl)) { 3209 tg_attribute_t tgattribute; 3210 int is_writable; 3211 /* 3212 * Preserve the old behavior for non-writable 3213 * medias. Since dkg_nsect is a ushort, it 3214 * will lose bits as cdroms have more than 3215 * 65536 sectors. So if we recalculate 3216 * capacity, it will become much shorter. 3217 * But the dkg_* information is not 3218 * used for CDROMs so it is OK. But for 3219 * Writable CDs we need this information 3220 * to be valid (for newfs say). So we 3221 * make nsect and nhead > 1 that way 3222 * nsect can still stay within ushort limit 3223 * without losing any bits. 3224 */ 3225 3226 bzero(&tgattribute, sizeof (tg_attribute_t)); 3227 3228 mutex_exit(CMLB_MUTEX(cl)); 3229 is_writable = 3230 (DK_TG_GETATTRIBUTE(cl, &tgattribute, tg_cookie) == 0) ? 3231 tgattribute.media_is_writable : 1; 3232 mutex_enter(CMLB_MUTEX(cl)); 3233 3234 if (is_writable) { 3235 cl->cl_g.dkg_nhead = 64; 3236 cl->cl_g.dkg_nsect = 32; 3237 cl->cl_g.dkg_ncyl = cl->cl_blockcount / (64 * 32); 3238 cl->cl_solaris_size = (diskaddr_t)cl->cl_g.dkg_ncyl * 3239 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 3240 } else { 3241 cl->cl_g.dkg_ncyl = 1; 3242 cl->cl_g.dkg_nhead = 1; 3243 cl->cl_g.dkg_nsect = cl->cl_blockcount; 3244 } 3245 } else { 3246 if (cl->cl_blockcount <= 0x1000) { 3247 /* unlabeled SCSI floppy device */ 3248 cl->cl_g.dkg_nhead = 2; 3249 cl->cl_g.dkg_ncyl = 80; 3250 cl->cl_g.dkg_nsect = cl->cl_blockcount / (2 * 80); 3251 } else if (cl->cl_blockcount <= 0x200000) { 3252 cl->cl_g.dkg_nhead = 64; 3253 cl->cl_g.dkg_nsect = 32; 3254 cl->cl_g.dkg_ncyl = cl->cl_blockcount / (64 * 32); 3255 } else { 3256 cl->cl_g.dkg_nhead = 255; 3257 3258 cl->cl_g.dkg_nsect = ((cl->cl_blockcount + 3259 (UINT16_MAX * 255 * 63) - 1) / 3260 (UINT16_MAX * 255 * 63)) * 63; 3261 3262 if (cl->cl_g.dkg_nsect == 0) 3263 cl->cl_g.dkg_nsect = (UINT16_MAX / 63) * 63; 3264 3265 cl->cl_g.dkg_ncyl = cl->cl_blockcount / 3266 (255 * cl->cl_g.dkg_nsect); 3267 } 3268 3269 cl->cl_solaris_size = 3270 (diskaddr_t)cl->cl_g.dkg_ncyl * cl->cl_g.dkg_nhead * 3271 cl->cl_g.dkg_nsect; 3272 3273 } 3274 3275 cl->cl_g.dkg_acyl = 0; 3276 cl->cl_g.dkg_bcyl = 0; 3277 cl->cl_g.dkg_rpm = 200; 3278 cl->cl_asciilabel[0] = '\0'; 3279 cl->cl_g.dkg_pcyl = cl->cl_g.dkg_ncyl; 3280 3281 cl->cl_map[0].dkl_cylno = 0; 3282 cl->cl_map[0].dkl_nblk = cl->cl_solaris_size; 3283 3284 cl->cl_map[2].dkl_cylno = 0; 3285 cl->cl_map[2].dkl_nblk = cl->cl_solaris_size; 3286 3287 #elif defined(_SUNOS_VTOC_16) 3288 3289 if (cl->cl_solaris_size == 0) { 3290 /* 3291 * Got fdisk table but no solaris entry therefore 3292 * don't create a default label 3293 */ 3294 cl->cl_f_geometry_is_valid = B_TRUE; 3295 return; 3296 } 3297 3298 /* 3299 * For CDs we continue to use the physical geometry to calculate 3300 * number of cylinders. All other devices must convert the 3301 * physical geometry (cmlb_geom) to values that will fit 3302 * in a dk_geom structure. 3303 */ 3304 if (ISCD(cl)) { 3305 phys_spc = cl->cl_pgeom.g_nhead * cl->cl_pgeom.g_nsect; 3306 } else { 3307 /* Convert physical geometry to disk geometry */ 3308 bzero(&cl_g, sizeof (struct dk_geom)); 3309 3310 /* 3311 * Refer to comments related to off-by-1 at the 3312 * header of this file. 3313 * Before calculating geometry, capacity should be 3314 * decreased by 1. 3315 */ 3316 3317 if (cl->cl_alter_behavior & CMLB_OFF_BY_ONE) 3318 capacity = cl->cl_blockcount - 1; 3319 else 3320 capacity = cl->cl_blockcount; 3321 3322 3323 cmlb_convert_geometry(capacity, &cl_g); 3324 bcopy(&cl_g, &cl->cl_g, sizeof (cl->cl_g)); 3325 phys_spc = cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 3326 } 3327 3328 if (phys_spc == 0) 3329 return; 3330 cl->cl_g.dkg_pcyl = cl->cl_solaris_size / phys_spc; 3331 if (cl->cl_alter_behavior & CMLB_FAKE_LABEL_ONE_PARTITION) { 3332 /* disable devid */ 3333 cl->cl_g.dkg_ncyl = cl->cl_g.dkg_pcyl; 3334 disksize = cl->cl_solaris_size; 3335 } else { 3336 cl->cl_g.dkg_acyl = DK_ACYL; 3337 cl->cl_g.dkg_ncyl = cl->cl_g.dkg_pcyl - DK_ACYL; 3338 disksize = cl->cl_g.dkg_ncyl * phys_spc; 3339 } 3340 3341 if (ISCD(cl)) { 3342 /* 3343 * CD's don't use the "heads * sectors * cyls"-type of 3344 * geometry, but instead use the entire capacity of the media. 3345 */ 3346 disksize = cl->cl_solaris_size; 3347 cl->cl_g.dkg_nhead = 1; 3348 cl->cl_g.dkg_nsect = 1; 3349 cl->cl_g.dkg_rpm = 3350 (cl->cl_pgeom.g_rpm == 0) ? 200 : cl->cl_pgeom.g_rpm; 3351 3352 cl->cl_vtoc.v_part[0].p_start = 0; 3353 cl->cl_vtoc.v_part[0].p_size = disksize; 3354 cl->cl_vtoc.v_part[0].p_tag = V_BACKUP; 3355 cl->cl_vtoc.v_part[0].p_flag = V_UNMNT; 3356 3357 cl->cl_map[0].dkl_cylno = 0; 3358 cl->cl_map[0].dkl_nblk = disksize; 3359 cl->cl_offset[0] = 0; 3360 3361 } else { 3362 /* 3363 * Hard disks and removable media cartridges 3364 */ 3365 cl->cl_g.dkg_rpm = 3366 (cl->cl_pgeom.g_rpm == 0) ? 3600: cl->cl_pgeom.g_rpm; 3367 cl->cl_vtoc.v_sectorsz = cl->cl_sys_blocksize; 3368 3369 /* Add boot slice */ 3370 cl->cl_vtoc.v_part[8].p_start = 0; 3371 cl->cl_vtoc.v_part[8].p_size = phys_spc; 3372 cl->cl_vtoc.v_part[8].p_tag = V_BOOT; 3373 cl->cl_vtoc.v_part[8].p_flag = V_UNMNT; 3374 3375 cl->cl_map[8].dkl_cylno = 0; 3376 cl->cl_map[8].dkl_nblk = phys_spc; 3377 cl->cl_offset[8] = 0; 3378 3379 if ((cl->cl_alter_behavior & 3380 CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT) && 3381 cl->cl_device_type == DTYPE_DIRECT) { 3382 cl->cl_vtoc.v_part[9].p_start = phys_spc; 3383 cl->cl_vtoc.v_part[9].p_size = 2 * phys_spc; 3384 cl->cl_vtoc.v_part[9].p_tag = V_ALTSCTR; 3385 cl->cl_vtoc.v_part[9].p_flag = 0; 3386 3387 cl->cl_map[9].dkl_cylno = 1; 3388 cl->cl_map[9].dkl_nblk = 2 * phys_spc; 3389 cl->cl_offset[9] = phys_spc; 3390 } 3391 } 3392 3393 cl->cl_g.dkg_apc = 0; 3394 3395 /* Add backup slice */ 3396 cl->cl_vtoc.v_part[2].p_start = 0; 3397 cl->cl_vtoc.v_part[2].p_size = disksize; 3398 cl->cl_vtoc.v_part[2].p_tag = V_BACKUP; 3399 cl->cl_vtoc.v_part[2].p_flag = V_UNMNT; 3400 3401 cl->cl_map[2].dkl_cylno = 0; 3402 cl->cl_map[2].dkl_nblk = disksize; 3403 cl->cl_offset[2] = 0; 3404 3405 /* 3406 * single slice (s0) covering the entire disk 3407 */ 3408 if (cl->cl_alter_behavior & CMLB_FAKE_LABEL_ONE_PARTITION) { 3409 cl->cl_vtoc.v_part[0].p_start = 0; 3410 cl->cl_vtoc.v_part[0].p_tag = V_UNASSIGNED; 3411 cl->cl_vtoc.v_part[0].p_flag = 0; 3412 cl->cl_vtoc.v_part[0].p_size = disksize; 3413 cl->cl_map[0].dkl_cylno = 0; 3414 cl->cl_map[0].dkl_nblk = disksize; 3415 cl->cl_offset[0] = 0; 3416 } 3417 3418 (void) sprintf(cl->cl_vtoc.v_asciilabel, "DEFAULT cyl %d alt %d" 3419 " hd %d sec %d", cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, 3420 cl->cl_g.dkg_nhead, cl->cl_g.dkg_nsect); 3421 3422 #else 3423 #error "No VTOC format defined." 3424 #endif 3425 3426 cl->cl_g.dkg_read_reinstruct = 0; 3427 cl->cl_g.dkg_write_reinstruct = 0; 3428 3429 cl->cl_g.dkg_intrlv = 1; 3430 3431 cl->cl_vtoc.v_sanity = VTOC_SANE; 3432 cl->cl_vtoc.v_nparts = V_NUMPAR; 3433 cl->cl_vtoc.v_version = V_VERSION; 3434 3435 cl->cl_f_geometry_is_valid = B_TRUE; 3436 cl->cl_label_from_media = CMLB_LABEL_UNDEF; 3437 3438 cmlb_dbg(CMLB_INFO, cl, 3439 "cmlb_build_default_label: Default label created: " 3440 "cyl: %d\tacyl: %d\tnhead: %d\tnsect: %d\tcap: %d\n", 3441 cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, cl->cl_g.dkg_nhead, 3442 cl->cl_g.dkg_nsect, cl->cl_blockcount); 3443 } 3444 3445 3446 #if defined(_FIRMWARE_NEEDS_FDISK) 3447 /* 3448 * Max CHS values, as they are encoded into bytes, for 1022/254/63 3449 */ 3450 #define LBA_MAX_SECT (63 | ((1022 & 0x300) >> 2)) 3451 #define LBA_MAX_CYL (1022 & 0xFF) 3452 #define LBA_MAX_HEAD (254) 3453 3454 3455 /* 3456 * Function: cmlb_has_max_chs_vals 3457 * 3458 * Description: Return B_TRUE if Cylinder-Head-Sector values are all at maximum. 3459 * 3460 * Arguments: fdp - ptr to CHS info 3461 * 3462 * Return Code: True or false 3463 * 3464 * Context: Any. 3465 */ 3466 static boolean_t 3467 cmlb_has_max_chs_vals(struct ipart *fdp) 3468 { 3469 return ((fdp->begcyl == LBA_MAX_CYL) && 3470 (fdp->beghead == LBA_MAX_HEAD) && 3471 (fdp->begsect == LBA_MAX_SECT) && 3472 (fdp->endcyl == LBA_MAX_CYL) && 3473 (fdp->endhead == LBA_MAX_HEAD) && 3474 (fdp->endsect == LBA_MAX_SECT)); 3475 } 3476 #endif 3477 3478 /* 3479 * Function: cmlb_dkio_get_geometry 3480 * 3481 * Description: This routine is the driver entry point for handling user 3482 * requests to get the device geometry (DKIOCGGEOM). 3483 * 3484 * Arguments: 3485 * arg pointer to user provided dk_geom structure specifying 3486 * the controller's notion of the current geometry. 3487 * 3488 * flag this argument is a pass through to ddi_copyxxx() 3489 * directly from the mode argument of ioctl(). 3490 * 3491 * tg_cookie cookie from target driver to be passed back to target 3492 * driver when we call back to it through tg_ops. 3493 * 3494 * Return Code: 0 3495 * EFAULT 3496 * ENXIO 3497 * EIO 3498 */ 3499 static int 3500 cmlb_dkio_get_geometry(struct cmlb_lun *cl, caddr_t arg, int flag, 3501 void *tg_cookie) 3502 { 3503 struct dk_geom *tmp_geom = NULL; 3504 int rval = 0; 3505 3506 /* 3507 * cmlb_validate_geometry does not spin a disk up 3508 * if it was spcl down. We need to make sure it 3509 * is ready. 3510 */ 3511 mutex_enter(CMLB_MUTEX(cl)); 3512 rval = cmlb_validate_geometry(cl, B_TRUE, 0, tg_cookie); 3513 #if defined(_SUNOS_VTOC_8) 3514 if (rval == EINVAL && 3515 cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8) { 3516 /* 3517 * This is to return a default label geometry even when we 3518 * do not really assume a default label for the device. 3519 * dad driver utilizes this. 3520 */ 3521 if (cl->cl_blockcount <= CMLB_OLDVTOC_LIMIT) { 3522 cmlb_setup_default_geometry(cl, tg_cookie); 3523 rval = 0; 3524 } 3525 } 3526 #endif 3527 if (rval) { 3528 mutex_exit(CMLB_MUTEX(cl)); 3529 return (rval); 3530 } 3531 3532 #if defined(__i386) || defined(__amd64) 3533 if (cl->cl_solaris_size == 0) { 3534 mutex_exit(CMLB_MUTEX(cl)); 3535 return (EIO); 3536 } 3537 #endif 3538 3539 /* 3540 * Make a local copy of the soft state geometry to avoid some potential 3541 * race conditions associated with holding the mutex and updating the 3542 * write_reinstruct value 3543 */ 3544 tmp_geom = kmem_zalloc(sizeof (struct dk_geom), KM_SLEEP); 3545 bcopy(&cl->cl_g, tmp_geom, sizeof (struct dk_geom)); 3546 3547 if (tmp_geom->dkg_write_reinstruct == 0) { 3548 tmp_geom->dkg_write_reinstruct = 3549 (int)((int)(tmp_geom->dkg_nsect * tmp_geom->dkg_rpm * 3550 cmlb_rot_delay) / (int)60000); 3551 } 3552 mutex_exit(CMLB_MUTEX(cl)); 3553 3554 rval = ddi_copyout(tmp_geom, (void *)arg, sizeof (struct dk_geom), 3555 flag); 3556 if (rval != 0) { 3557 rval = EFAULT; 3558 } 3559 3560 kmem_free(tmp_geom, sizeof (struct dk_geom)); 3561 return (rval); 3562 3563 } 3564 3565 3566 /* 3567 * Function: cmlb_dkio_set_geometry 3568 * 3569 * Description: This routine is the driver entry point for handling user 3570 * requests to set the device geometry (DKIOCSGEOM). The actual 3571 * device geometry is not updated, just the driver "notion" of it. 3572 * 3573 * Arguments: 3574 * arg pointer to user provided dk_geom structure used to set 3575 * the controller's notion of the current geometry. 3576 * 3577 * flag this argument is a pass through to ddi_copyxxx() 3578 * directly from the mode argument of ioctl(). 3579 * 3580 * tg_cookie cookie from target driver to be passed back to target 3581 * driver when we call back to it through tg_ops. 3582 * 3583 * Return Code: 0 3584 * EFAULT 3585 * ENXIO 3586 * EIO 3587 */ 3588 static int 3589 cmlb_dkio_set_geometry(struct cmlb_lun *cl, caddr_t arg, int flag) 3590 { 3591 struct dk_geom *tmp_geom; 3592 struct dk_map *lp; 3593 int rval = 0; 3594 int i; 3595 3596 3597 #if defined(__i386) || defined(__amd64) 3598 if (cl->cl_solaris_size == 0) { 3599 return (EIO); 3600 } 3601 #endif 3602 /* 3603 * We need to copy the user specified geometry into local 3604 * storage and then update the softstate. We don't want to hold 3605 * the mutex and copyin directly from the user to the soft state 3606 */ 3607 tmp_geom = (struct dk_geom *) 3608 kmem_zalloc(sizeof (struct dk_geom), KM_SLEEP); 3609 rval = ddi_copyin(arg, tmp_geom, sizeof (struct dk_geom), flag); 3610 if (rval != 0) { 3611 kmem_free(tmp_geom, sizeof (struct dk_geom)); 3612 return (EFAULT); 3613 } 3614 3615 mutex_enter(CMLB_MUTEX(cl)); 3616 bcopy(tmp_geom, &cl->cl_g, sizeof (struct dk_geom)); 3617 for (i = 0; i < NDKMAP; i++) { 3618 lp = &cl->cl_map[i]; 3619 cl->cl_offset[i] = 3620 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 3621 #if defined(__i386) || defined(__amd64) 3622 cl->cl_offset[i] += cl->cl_solaris_offset; 3623 #endif 3624 } 3625 cl->cl_f_geometry_is_valid = B_FALSE; 3626 mutex_exit(CMLB_MUTEX(cl)); 3627 kmem_free(tmp_geom, sizeof (struct dk_geom)); 3628 3629 return (rval); 3630 } 3631 3632 /* 3633 * Function: cmlb_dkio_get_partition 3634 * 3635 * Description: This routine is the driver entry point for handling user 3636 * requests to get the partition table (DKIOCGAPART). 3637 * 3638 * Arguments: 3639 * arg pointer to user provided dk_allmap structure specifying 3640 * the controller's notion of the current partition table. 3641 * 3642 * flag this argument is a pass through to ddi_copyxxx() 3643 * directly from the mode argument of ioctl(). 3644 * 3645 * tg_cookie cookie from target driver to be passed back to target 3646 * driver when we call back to it through tg_ops. 3647 * 3648 * Return Code: 0 3649 * EFAULT 3650 * ENXIO 3651 * EIO 3652 */ 3653 static int 3654 cmlb_dkio_get_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 3655 void *tg_cookie) 3656 { 3657 int rval = 0; 3658 int size; 3659 3660 /* 3661 * Make sure the geometry is valid before getting the partition 3662 * information. 3663 */ 3664 mutex_enter(CMLB_MUTEX(cl)); 3665 if ((rval = cmlb_validate_geometry(cl, B_TRUE, 0, tg_cookie)) != 0) { 3666 mutex_exit(CMLB_MUTEX(cl)); 3667 return (rval); 3668 } 3669 mutex_exit(CMLB_MUTEX(cl)); 3670 3671 #if defined(__i386) || defined(__amd64) 3672 if (cl->cl_solaris_size == 0) { 3673 return (EIO); 3674 } 3675 #endif 3676 3677 #ifdef _MULTI_DATAMODEL 3678 switch (ddi_model_convert_from(flag & FMODELS)) { 3679 case DDI_MODEL_ILP32: { 3680 struct dk_map32 dk_map32[NDKMAP]; 3681 int i; 3682 3683 for (i = 0; i < NDKMAP; i++) { 3684 dk_map32[i].dkl_cylno = cl->cl_map[i].dkl_cylno; 3685 dk_map32[i].dkl_nblk = cl->cl_map[i].dkl_nblk; 3686 } 3687 size = NDKMAP * sizeof (struct dk_map32); 3688 rval = ddi_copyout(dk_map32, (void *)arg, size, flag); 3689 if (rval != 0) { 3690 rval = EFAULT; 3691 } 3692 break; 3693 } 3694 case DDI_MODEL_NONE: 3695 size = NDKMAP * sizeof (struct dk_map); 3696 rval = ddi_copyout(cl->cl_map, (void *)arg, size, flag); 3697 if (rval != 0) { 3698 rval = EFAULT; 3699 } 3700 break; 3701 } 3702 #else /* ! _MULTI_DATAMODEL */ 3703 size = NDKMAP * sizeof (struct dk_map); 3704 rval = ddi_copyout(cl->cl_map, (void *)arg, size, flag); 3705 if (rval != 0) { 3706 rval = EFAULT; 3707 } 3708 #endif /* _MULTI_DATAMODEL */ 3709 return (rval); 3710 } 3711 3712 /* 3713 * Function: cmlb_dkio_set_partition 3714 * 3715 * Description: This routine is the driver entry point for handling user 3716 * requests to set the partition table (DKIOCSAPART). The actual 3717 * device partition is not updated. 3718 * 3719 * Arguments: 3720 * arg - pointer to user provided dk_allmap structure used to set 3721 * the controller's notion of the partition table. 3722 * flag - this argument is a pass through to ddi_copyxxx() 3723 * directly from the mode argument of ioctl(). 3724 * 3725 * Return Code: 0 3726 * EINVAL 3727 * EFAULT 3728 * ENXIO 3729 * EIO 3730 */ 3731 static int 3732 cmlb_dkio_set_partition(struct cmlb_lun *cl, caddr_t arg, int flag) 3733 { 3734 struct dk_map dk_map[NDKMAP]; 3735 struct dk_map *lp; 3736 int rval = 0; 3737 int size; 3738 int i; 3739 #if defined(_SUNOS_VTOC_16) 3740 struct dkl_partition *vp; 3741 #endif 3742 3743 /* 3744 * Set the map for all logical partitions. We lock 3745 * the priority just to make sure an interrupt doesn't 3746 * come in while the map is half updated. 3747 */ 3748 _NOTE(DATA_READABLE_WITHOUT_LOCK(cmlb_lun::cl_solaris_size)) 3749 mutex_enter(CMLB_MUTEX(cl)); 3750 3751 if (cl->cl_blockcount > CMLB_OLDVTOC_LIMIT) { 3752 mutex_exit(CMLB_MUTEX(cl)); 3753 return (ENOTSUP); 3754 } 3755 mutex_exit(CMLB_MUTEX(cl)); 3756 if (cl->cl_solaris_size == 0) { 3757 return (EIO); 3758 } 3759 3760 #ifdef _MULTI_DATAMODEL 3761 switch (ddi_model_convert_from(flag & FMODELS)) { 3762 case DDI_MODEL_ILP32: { 3763 struct dk_map32 dk_map32[NDKMAP]; 3764 3765 size = NDKMAP * sizeof (struct dk_map32); 3766 rval = ddi_copyin((void *)arg, dk_map32, size, flag); 3767 if (rval != 0) { 3768 return (EFAULT); 3769 } 3770 for (i = 0; i < NDKMAP; i++) { 3771 dk_map[i].dkl_cylno = dk_map32[i].dkl_cylno; 3772 dk_map[i].dkl_nblk = dk_map32[i].dkl_nblk; 3773 } 3774 break; 3775 } 3776 case DDI_MODEL_NONE: 3777 size = NDKMAP * sizeof (struct dk_map); 3778 rval = ddi_copyin((void *)arg, dk_map, size, flag); 3779 if (rval != 0) { 3780 return (EFAULT); 3781 } 3782 break; 3783 } 3784 #else /* ! _MULTI_DATAMODEL */ 3785 size = NDKMAP * sizeof (struct dk_map); 3786 rval = ddi_copyin((void *)arg, dk_map, size, flag); 3787 if (rval != 0) { 3788 return (EFAULT); 3789 } 3790 #endif /* _MULTI_DATAMODEL */ 3791 3792 mutex_enter(CMLB_MUTEX(cl)); 3793 /* Note: The size used in this bcopy is set based upon the data model */ 3794 bcopy(dk_map, cl->cl_map, size); 3795 #if defined(_SUNOS_VTOC_16) 3796 vp = (struct dkl_partition *)&(cl->cl_vtoc); 3797 #endif /* defined(_SUNOS_VTOC_16) */ 3798 for (i = 0; i < NDKMAP; i++) { 3799 lp = &cl->cl_map[i]; 3800 cl->cl_offset[i] = 3801 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 3802 #if defined(_SUNOS_VTOC_16) 3803 vp->p_start = cl->cl_offset[i]; 3804 vp->p_size = lp->dkl_nblk; 3805 vp++; 3806 #endif /* defined(_SUNOS_VTOC_16) */ 3807 #if defined(__i386) || defined(__amd64) 3808 cl->cl_offset[i] += cl->cl_solaris_offset; 3809 #endif 3810 } 3811 mutex_exit(CMLB_MUTEX(cl)); 3812 return (rval); 3813 } 3814 3815 3816 /* 3817 * Function: cmlb_dkio_get_vtoc 3818 * 3819 * Description: This routine is the driver entry point for handling user 3820 * requests to get the current volume table of contents 3821 * (DKIOCGVTOC). 3822 * 3823 * Arguments: 3824 * arg pointer to user provided vtoc structure specifying 3825 * the current vtoc. 3826 * 3827 * flag this argument is a pass through to ddi_copyxxx() 3828 * directly from the mode argument of ioctl(). 3829 * 3830 * tg_cookie cookie from target driver to be passed back to target 3831 * driver when we call back to it through tg_ops. 3832 * 3833 * Return Code: 0 3834 * EFAULT 3835 * ENXIO 3836 * EIO 3837 */ 3838 static int 3839 cmlb_dkio_get_vtoc(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 3840 { 3841 #if defined(_SUNOS_VTOC_8) 3842 struct vtoc user_vtoc; 3843 #endif /* defined(_SUNOS_VTOC_8) */ 3844 int rval = 0; 3845 3846 mutex_enter(CMLB_MUTEX(cl)); 3847 if (cl->cl_blockcount > CMLB_OLDVTOC_LIMIT) { 3848 mutex_exit(CMLB_MUTEX(cl)); 3849 return (EOVERFLOW); 3850 } 3851 3852 rval = cmlb_validate_geometry(cl, B_TRUE, 0, tg_cookie); 3853 3854 #if defined(_SUNOS_VTOC_8) 3855 if (rval == EINVAL && 3856 (cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8)) { 3857 /* 3858 * This is to return a default label even when we do not 3859 * really assume a default label for the device. 3860 * dad driver utilizes this. 3861 */ 3862 if (cl->cl_blockcount <= CMLB_OLDVTOC_LIMIT) { 3863 cmlb_setup_default_geometry(cl, tg_cookie); 3864 rval = 0; 3865 } 3866 } 3867 #endif 3868 if (rval) { 3869 mutex_exit(CMLB_MUTEX(cl)); 3870 return (rval); 3871 } 3872 3873 #if defined(_SUNOS_VTOC_8) 3874 cmlb_build_user_vtoc(cl, &user_vtoc); 3875 mutex_exit(CMLB_MUTEX(cl)); 3876 3877 #ifdef _MULTI_DATAMODEL 3878 switch (ddi_model_convert_from(flag & FMODELS)) { 3879 case DDI_MODEL_ILP32: { 3880 struct vtoc32 user_vtoc32; 3881 3882 vtoctovtoc32(user_vtoc, user_vtoc32); 3883 if (ddi_copyout(&user_vtoc32, (void *)arg, 3884 sizeof (struct vtoc32), flag)) { 3885 return (EFAULT); 3886 } 3887 break; 3888 } 3889 3890 case DDI_MODEL_NONE: 3891 if (ddi_copyout(&user_vtoc, (void *)arg, 3892 sizeof (struct vtoc), flag)) { 3893 return (EFAULT); 3894 } 3895 break; 3896 } 3897 #else /* ! _MULTI_DATAMODEL */ 3898 if (ddi_copyout(&user_vtoc, (void *)arg, sizeof (struct vtoc), flag)) { 3899 return (EFAULT); 3900 } 3901 #endif /* _MULTI_DATAMODEL */ 3902 3903 #elif defined(_SUNOS_VTOC_16) 3904 mutex_exit(CMLB_MUTEX(cl)); 3905 3906 #ifdef _MULTI_DATAMODEL 3907 /* 3908 * The cl_vtoc structure is a "struct dk_vtoc" which is always 3909 * 32-bit to maintain compatibility with existing on-disk 3910 * structures. Thus, we need to convert the structure when copying 3911 * it out to a datamodel-dependent "struct vtoc" in a 64-bit 3912 * program. If the target is a 32-bit program, then no conversion 3913 * is necessary. 3914 */ 3915 /* LINTED: logical expression always true: op "||" */ 3916 ASSERT(sizeof (cl->cl_vtoc) == sizeof (struct vtoc32)); 3917 switch (ddi_model_convert_from(flag & FMODELS)) { 3918 case DDI_MODEL_ILP32: 3919 if (ddi_copyout(&(cl->cl_vtoc), (void *)arg, 3920 sizeof (cl->cl_vtoc), flag)) { 3921 return (EFAULT); 3922 } 3923 break; 3924 3925 case DDI_MODEL_NONE: { 3926 struct vtoc user_vtoc; 3927 3928 vtoc32tovtoc(cl->cl_vtoc, user_vtoc); 3929 if (ddi_copyout(&user_vtoc, (void *)arg, 3930 sizeof (struct vtoc), flag)) { 3931 return (EFAULT); 3932 } 3933 break; 3934 } 3935 } 3936 #else /* ! _MULTI_DATAMODEL */ 3937 if (ddi_copyout(&(cl->cl_vtoc), (void *)arg, sizeof (cl->cl_vtoc), 3938 flag)) { 3939 return (EFAULT); 3940 } 3941 #endif /* _MULTI_DATAMODEL */ 3942 #else 3943 #error "No VTOC format defined." 3944 #endif 3945 3946 return (rval); 3947 } 3948 3949 3950 /* 3951 * Function: cmlb_dkio_get_extvtoc 3952 */ 3953 static int 3954 cmlb_dkio_get_extvtoc(struct cmlb_lun *cl, caddr_t arg, int flag, 3955 void *tg_cookie) 3956 { 3957 struct extvtoc ext_vtoc; 3958 #if defined(_SUNOS_VTOC_8) 3959 struct vtoc user_vtoc; 3960 #endif /* defined(_SUNOS_VTOC_8) */ 3961 int rval = 0; 3962 3963 bzero(&ext_vtoc, sizeof (struct extvtoc)); 3964 mutex_enter(CMLB_MUTEX(cl)); 3965 rval = cmlb_validate_geometry(cl, B_TRUE, 0, tg_cookie); 3966 3967 #if defined(_SUNOS_VTOC_8) 3968 if (rval == EINVAL && 3969 (cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8)) { 3970 /* 3971 * This is to return a default label even when we do not 3972 * really assume a default label for the device. 3973 * dad driver utilizes this. 3974 */ 3975 if (cl->cl_blockcount <= CMLB_OLDVTOC_LIMIT) { 3976 cmlb_setup_default_geometry(cl, tg_cookie); 3977 rval = 0; 3978 } 3979 } 3980 #endif 3981 if (rval) { 3982 mutex_exit(CMLB_MUTEX(cl)); 3983 return (rval); 3984 } 3985 3986 #if defined(_SUNOS_VTOC_8) 3987 cmlb_build_user_vtoc(cl, &user_vtoc); 3988 mutex_exit(CMLB_MUTEX(cl)); 3989 3990 /* 3991 * Checking callers data model does not make much sense here 3992 * since extvtoc will always be equivalent to 64bit vtoc. 3993 * What is important is whether the kernel is in 32 or 64 bit 3994 */ 3995 3996 #ifdef _LP64 3997 if (ddi_copyout(&user_vtoc, (void *)arg, 3998 sizeof (struct extvtoc), flag)) { 3999 return (EFAULT); 4000 } 4001 #else 4002 vtoc32tovtoc(user_vtoc, ext_vtoc); 4003 if (ddi_copyout(&ext_vtoc, (void *)arg, 4004 sizeof (struct extvtoc), flag)) { 4005 return (EFAULT); 4006 } 4007 #endif 4008 4009 #elif defined(_SUNOS_VTOC_16) 4010 /* 4011 * The cl_vtoc structure is a "struct dk_vtoc" which is always 4012 * 32-bit to maintain compatibility with existing on-disk 4013 * structures. Thus, we need to convert the structure when copying 4014 * it out to extvtoc 4015 */ 4016 vtoc32tovtoc(cl->cl_vtoc, ext_vtoc); 4017 mutex_exit(CMLB_MUTEX(cl)); 4018 4019 if (ddi_copyout(&ext_vtoc, (void *)arg, sizeof (struct extvtoc), flag)) 4020 return (EFAULT); 4021 #else 4022 #error "No VTOC format defined." 4023 #endif 4024 4025 return (rval); 4026 } 4027 static int 4028 cmlb_dkio_get_efi(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 4029 { 4030 dk_efi_t user_efi; 4031 int rval = 0; 4032 void *buffer; 4033 diskaddr_t tgt_lba; 4034 4035 if (ddi_copyin(arg, &user_efi, sizeof (dk_efi_t), flag)) 4036 return (EFAULT); 4037 4038 user_efi.dki_data = (void *)(uintptr_t)user_efi.dki_data_64; 4039 4040 tgt_lba = user_efi.dki_lba; 4041 4042 mutex_enter(CMLB_MUTEX(cl)); 4043 if ((cmlb_check_update_blockcount(cl, tg_cookie) != 0) || 4044 (cl->cl_tgt_blocksize == 0)) { 4045 mutex_exit(CMLB_MUTEX(cl)); 4046 return (EINVAL); 4047 } 4048 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) 4049 tgt_lba = tgt_lba * cl->cl_tgt_blocksize / 4050 cl->cl_sys_blocksize; 4051 mutex_exit(CMLB_MUTEX(cl)); 4052 4053 buffer = kmem_alloc(user_efi.dki_length, KM_SLEEP); 4054 rval = DK_TG_READ(cl, buffer, tgt_lba, user_efi.dki_length, tg_cookie); 4055 if (rval == 0 && ddi_copyout(buffer, user_efi.dki_data, 4056 user_efi.dki_length, flag) != 0) 4057 rval = EFAULT; 4058 4059 kmem_free(buffer, user_efi.dki_length); 4060 return (rval); 4061 } 4062 4063 #if defined(_SUNOS_VTOC_8) 4064 /* 4065 * Function: cmlb_build_user_vtoc 4066 * 4067 * Description: This routine populates a pass by reference variable with the 4068 * current volume table of contents. 4069 * 4070 * Arguments: cl - driver soft state (unit) structure 4071 * user_vtoc - pointer to vtoc structure to be populated 4072 */ 4073 static void 4074 cmlb_build_user_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc) 4075 { 4076 struct dk_map2 *lpart; 4077 struct dk_map *lmap; 4078 struct partition *vpart; 4079 uint32_t nblks; 4080 int i; 4081 4082 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4083 4084 /* 4085 * Return vtoc structure fields in the provided VTOC area, addressed 4086 * by *vtoc. 4087 */ 4088 bzero(user_vtoc, sizeof (struct vtoc)); 4089 user_vtoc->v_bootinfo[0] = cl->cl_vtoc.v_bootinfo[0]; 4090 user_vtoc->v_bootinfo[1] = cl->cl_vtoc.v_bootinfo[1]; 4091 user_vtoc->v_bootinfo[2] = cl->cl_vtoc.v_bootinfo[2]; 4092 user_vtoc->v_sanity = VTOC_SANE; 4093 user_vtoc->v_version = cl->cl_vtoc.v_version; 4094 bcopy(cl->cl_vtoc.v_volume, user_vtoc->v_volume, LEN_DKL_VVOL); 4095 user_vtoc->v_sectorsz = cl->cl_sys_blocksize; 4096 user_vtoc->v_nparts = cl->cl_vtoc.v_nparts; 4097 4098 for (i = 0; i < 10; i++) 4099 user_vtoc->v_reserved[i] = cl->cl_vtoc.v_reserved[i]; 4100 4101 /* 4102 * Convert partitioning information. 4103 * 4104 * Note the conversion from starting cylinder number 4105 * to starting sector number. 4106 */ 4107 lmap = cl->cl_map; 4108 lpart = (struct dk_map2 *)cl->cl_vtoc.v_part; 4109 vpart = user_vtoc->v_part; 4110 4111 nblks = cl->cl_g.dkg_nsect * cl->cl_g.dkg_nhead; 4112 4113 for (i = 0; i < V_NUMPAR; i++) { 4114 vpart->p_tag = lpart->p_tag; 4115 vpart->p_flag = lpart->p_flag; 4116 vpart->p_start = lmap->dkl_cylno * nblks; 4117 vpart->p_size = lmap->dkl_nblk; 4118 lmap++; 4119 lpart++; 4120 vpart++; 4121 4122 /* (4364927) */ 4123 user_vtoc->timestamp[i] = (time_t)cl->cl_vtoc.v_timestamp[i]; 4124 } 4125 4126 bcopy(cl->cl_asciilabel, user_vtoc->v_asciilabel, LEN_DKL_ASCII); 4127 } 4128 #endif 4129 4130 static int 4131 cmlb_dkio_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 4132 void *tg_cookie) 4133 { 4134 struct partition64 p64; 4135 int rval = 0; 4136 uint_t nparts; 4137 efi_gpe_t *partitions; 4138 efi_gpt_t *buffer; 4139 diskaddr_t gpe_lba; 4140 4141 if (ddi_copyin((const void *)arg, &p64, 4142 sizeof (struct partition64), flag)) { 4143 return (EFAULT); 4144 } 4145 4146 buffer = kmem_alloc(EFI_MIN_ARRAY_SIZE, KM_SLEEP); 4147 rval = DK_TG_READ(cl, buffer, 1, cl->cl_sys_blocksize, tg_cookie); 4148 if (rval != 0) 4149 goto done_error; 4150 4151 cmlb_swap_efi_gpt(buffer); 4152 4153 if ((rval = cmlb_validate_efi(buffer)) != 0) 4154 goto done_error; 4155 4156 nparts = buffer->efi_gpt_NumberOfPartitionEntries; 4157 gpe_lba = buffer->efi_gpt_PartitionEntryLBA; 4158 if (p64.p_partno > nparts) { 4159 /* couldn't find it */ 4160 rval = ESRCH; 4161 goto done_error; 4162 } 4163 /* 4164 * if we're dealing with a partition that's out of the normal 4165 * 16K block, adjust accordingly 4166 */ 4167 gpe_lba += p64.p_partno / sizeof (efi_gpe_t); 4168 rval = DK_TG_READ(cl, buffer, gpe_lba, EFI_MIN_ARRAY_SIZE, tg_cookie); 4169 4170 if (rval) { 4171 goto done_error; 4172 } 4173 partitions = (efi_gpe_t *)buffer; 4174 4175 cmlb_swap_efi_gpe(nparts, partitions); 4176 4177 partitions += p64.p_partno; 4178 bcopy(&partitions->efi_gpe_PartitionTypeGUID, &p64.p_type, 4179 sizeof (struct uuid)); 4180 p64.p_start = partitions->efi_gpe_StartingLBA; 4181 p64.p_size = partitions->efi_gpe_EndingLBA - 4182 p64.p_start + 1; 4183 4184 if (ddi_copyout(&p64, (void *)arg, sizeof (struct partition64), flag)) 4185 rval = EFAULT; 4186 4187 done_error: 4188 kmem_free(buffer, EFI_MIN_ARRAY_SIZE); 4189 return (rval); 4190 } 4191 4192 4193 /* 4194 * Function: cmlb_dkio_set_vtoc 4195 * 4196 * Description: This routine is the driver entry point for handling user 4197 * requests to set the current volume table of contents 4198 * (DKIOCSVTOC). 4199 * 4200 * Arguments: 4201 * dev the device number 4202 * arg pointer to user provided vtoc structure used to set the 4203 * current vtoc. 4204 * 4205 * flag this argument is a pass through to ddi_copyxxx() 4206 * directly from the mode argument of ioctl(). 4207 * 4208 * tg_cookie cookie from target driver to be passed back to target 4209 * driver when we call back to it through tg_ops. 4210 * 4211 * Return Code: 0 4212 * EFAULT 4213 * ENXIO 4214 * EINVAL 4215 * ENOTSUP 4216 */ 4217 static int 4218 cmlb_dkio_set_vtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag, 4219 void *tg_cookie) 4220 { 4221 struct vtoc user_vtoc; 4222 int rval = 0; 4223 boolean_t internal; 4224 4225 internal = VOID2BOOLEAN( 4226 (cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0); 4227 4228 #ifdef _MULTI_DATAMODEL 4229 switch (ddi_model_convert_from(flag & FMODELS)) { 4230 case DDI_MODEL_ILP32: { 4231 struct vtoc32 user_vtoc32; 4232 4233 if (ddi_copyin((const void *)arg, &user_vtoc32, 4234 sizeof (struct vtoc32), flag)) { 4235 return (EFAULT); 4236 } 4237 vtoc32tovtoc(user_vtoc32, user_vtoc); 4238 break; 4239 } 4240 4241 case DDI_MODEL_NONE: 4242 if (ddi_copyin((const void *)arg, &user_vtoc, 4243 sizeof (struct vtoc), flag)) { 4244 return (EFAULT); 4245 } 4246 break; 4247 } 4248 #else /* ! _MULTI_DATAMODEL */ 4249 if (ddi_copyin((const void *)arg, &user_vtoc, 4250 sizeof (struct vtoc), flag)) { 4251 return (EFAULT); 4252 } 4253 #endif /* _MULTI_DATAMODEL */ 4254 4255 mutex_enter(CMLB_MUTEX(cl)); 4256 4257 if (cl->cl_blockcount > CMLB_OLDVTOC_LIMIT) { 4258 mutex_exit(CMLB_MUTEX(cl)); 4259 return (EOVERFLOW); 4260 } 4261 4262 #if defined(__i386) || defined(__amd64) 4263 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) { 4264 mutex_exit(CMLB_MUTEX(cl)); 4265 return (EINVAL); 4266 } 4267 #endif 4268 4269 if (cl->cl_g.dkg_ncyl == 0) { 4270 mutex_exit(CMLB_MUTEX(cl)); 4271 return (EINVAL); 4272 } 4273 4274 mutex_exit(CMLB_MUTEX(cl)); 4275 cmlb_clear_efi(cl, tg_cookie); 4276 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd"); 4277 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd,raw"); 4278 4279 /* 4280 * cmlb_dkio_set_vtoc creates duplicate minor nodes when 4281 * relabeling an SMI disk. To avoid that we remove them 4282 * before creating. 4283 * It should be OK to remove a non-existed minor node. 4284 */ 4285 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h"); 4286 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h,raw"); 4287 4288 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h", 4289 S_IFBLK, (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 4290 cl->cl_node_type, NULL, internal); 4291 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h,raw", 4292 S_IFCHR, (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 4293 cl->cl_node_type, NULL, internal); 4294 mutex_enter(CMLB_MUTEX(cl)); 4295 4296 if ((rval = cmlb_build_label_vtoc(cl, &user_vtoc)) == 0) { 4297 if ((rval = cmlb_write_label(cl, tg_cookie)) == 0) { 4298 if (cmlb_validate_geometry(cl, 4299 B_TRUE, 0, tg_cookie) != 0) { 4300 cmlb_dbg(CMLB_ERROR, cl, 4301 "cmlb_dkio_set_vtoc: " 4302 "Failed validate geometry\n"); 4303 } 4304 cl->cl_msglog_flag |= CMLB_ALLOW_2TB_WARN; 4305 } 4306 } 4307 mutex_exit(CMLB_MUTEX(cl)); 4308 return (rval); 4309 } 4310 4311 /* 4312 * Function: cmlb_dkio_set_extvtoc 4313 */ 4314 static int 4315 cmlb_dkio_set_extvtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag, 4316 void *tg_cookie) 4317 { 4318 int rval = 0; 4319 struct vtoc user_vtoc; 4320 boolean_t internal; 4321 4322 4323 /* 4324 * Checking callers data model does not make much sense here 4325 * since extvtoc will always be equivalent to 64bit vtoc. 4326 * What is important is whether the kernel is in 32 or 64 bit 4327 */ 4328 4329 #ifdef _LP64 4330 if (ddi_copyin((const void *)arg, &user_vtoc, 4331 sizeof (struct extvtoc), flag)) { 4332 return (EFAULT); 4333 } 4334 #else 4335 struct extvtoc user_extvtoc; 4336 if (ddi_copyin((const void *)arg, &user_extvtoc, 4337 sizeof (struct extvtoc), flag)) { 4338 return (EFAULT); 4339 } 4340 4341 vtoctovtoc32(user_extvtoc, user_vtoc); 4342 #endif 4343 4344 internal = VOID2BOOLEAN( 4345 (cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0); 4346 mutex_enter(CMLB_MUTEX(cl)); 4347 #if defined(__i386) || defined(__amd64) 4348 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) { 4349 mutex_exit(CMLB_MUTEX(cl)); 4350 return (EINVAL); 4351 } 4352 #endif 4353 4354 if (cl->cl_g.dkg_ncyl == 0) { 4355 mutex_exit(CMLB_MUTEX(cl)); 4356 return (EINVAL); 4357 } 4358 4359 mutex_exit(CMLB_MUTEX(cl)); 4360 cmlb_clear_efi(cl, tg_cookie); 4361 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd"); 4362 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd,raw"); 4363 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h", 4364 S_IFBLK, (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 4365 cl->cl_node_type, NULL, internal); 4366 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h,raw", 4367 S_IFCHR, (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 4368 cl->cl_node_type, NULL, internal); 4369 4370 mutex_enter(CMLB_MUTEX(cl)); 4371 4372 if ((rval = cmlb_build_label_vtoc(cl, &user_vtoc)) == 0) { 4373 if ((rval = cmlb_write_label(cl, tg_cookie)) == 0) { 4374 if (cmlb_validate_geometry(cl, 4375 B_TRUE, 0, tg_cookie) != 0) { 4376 cmlb_dbg(CMLB_ERROR, cl, 4377 "cmlb_dkio_set_vtoc: " 4378 "Failed validate geometry\n"); 4379 } 4380 } 4381 } 4382 mutex_exit(CMLB_MUTEX(cl)); 4383 return (rval); 4384 } 4385 4386 /* 4387 * Function: cmlb_build_label_vtoc 4388 * 4389 * Description: This routine updates the driver soft state current volume table 4390 * of contents based on a user specified vtoc. 4391 * 4392 * Arguments: cl - driver soft state (unit) structure 4393 * user_vtoc - pointer to vtoc structure specifying vtoc to be used 4394 * to update the driver soft state. 4395 * 4396 * Return Code: 0 4397 * EINVAL 4398 */ 4399 static int 4400 cmlb_build_label_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc) 4401 { 4402 struct dk_map *lmap; 4403 struct partition *vpart; 4404 uint_t nblks; 4405 #if defined(_SUNOS_VTOC_8) 4406 int ncyl; 4407 struct dk_map2 *lpart; 4408 #endif /* defined(_SUNOS_VTOC_8) */ 4409 int i; 4410 4411 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4412 4413 /* Sanity-check the vtoc */ 4414 if (user_vtoc->v_sanity != VTOC_SANE || 4415 user_vtoc->v_sectorsz != cl->cl_sys_blocksize || 4416 user_vtoc->v_nparts != V_NUMPAR) { 4417 cmlb_dbg(CMLB_INFO, cl, 4418 "cmlb_build_label_vtoc: vtoc not valid\n"); 4419 return (EINVAL); 4420 } 4421 4422 nblks = cl->cl_g.dkg_nsect * cl->cl_g.dkg_nhead; 4423 if (nblks == 0) { 4424 cmlb_dbg(CMLB_INFO, cl, 4425 "cmlb_build_label_vtoc: geom nblks is 0\n"); 4426 return (EINVAL); 4427 } 4428 4429 #if defined(_SUNOS_VTOC_8) 4430 vpart = user_vtoc->v_part; 4431 for (i = 0; i < V_NUMPAR; i++) { 4432 if (((unsigned)vpart->p_start % nblks) != 0) { 4433 cmlb_dbg(CMLB_INFO, cl, 4434 "cmlb_build_label_vtoc: p_start not multiply of" 4435 "nblks part %d p_start %d nblks %d\n", i, 4436 vpart->p_start, nblks); 4437 return (EINVAL); 4438 } 4439 ncyl = (unsigned)vpart->p_start / nblks; 4440 ncyl += (unsigned)vpart->p_size / nblks; 4441 if (((unsigned)vpart->p_size % nblks) != 0) { 4442 ncyl++; 4443 } 4444 if (ncyl > (int)cl->cl_g.dkg_ncyl) { 4445 cmlb_dbg(CMLB_INFO, cl, 4446 "cmlb_build_label_vtoc: ncyl %d > dkg_ncyl %d" 4447 "p_size %ld p_start %ld nblks %d part number %d" 4448 "tag %d\n", 4449 ncyl, cl->cl_g.dkg_ncyl, vpart->p_size, 4450 vpart->p_start, nblks, 4451 i, vpart->p_tag); 4452 4453 return (EINVAL); 4454 } 4455 vpart++; 4456 } 4457 #endif /* defined(_SUNOS_VTOC_8) */ 4458 4459 /* Put appropriate vtoc structure fields into the disk label */ 4460 #if defined(_SUNOS_VTOC_16) 4461 /* 4462 * The vtoc is always a 32bit data structure to maintain the 4463 * on-disk format. Convert "in place" instead of doing bcopy. 4464 */ 4465 vtoctovtoc32((*user_vtoc), (*((struct vtoc32 *)&(cl->cl_vtoc)))); 4466 4467 /* 4468 * in the 16-slice vtoc, starting sectors are expressed in 4469 * numbers *relative* to the start of the Solaris fdisk partition. 4470 */ 4471 lmap = cl->cl_map; 4472 vpart = user_vtoc->v_part; 4473 4474 for (i = 0; i < (int)user_vtoc->v_nparts; i++, lmap++, vpart++) { 4475 lmap->dkl_cylno = (unsigned)vpart->p_start / nblks; 4476 lmap->dkl_nblk = (unsigned)vpart->p_size; 4477 } 4478 4479 #elif defined(_SUNOS_VTOC_8) 4480 4481 cl->cl_vtoc.v_bootinfo[0] = (uint32_t)user_vtoc->v_bootinfo[0]; 4482 cl->cl_vtoc.v_bootinfo[1] = (uint32_t)user_vtoc->v_bootinfo[1]; 4483 cl->cl_vtoc.v_bootinfo[2] = (uint32_t)user_vtoc->v_bootinfo[2]; 4484 4485 cl->cl_vtoc.v_sanity = (uint32_t)user_vtoc->v_sanity; 4486 cl->cl_vtoc.v_version = (uint32_t)user_vtoc->v_version; 4487 4488 bcopy(user_vtoc->v_volume, cl->cl_vtoc.v_volume, LEN_DKL_VVOL); 4489 4490 cl->cl_vtoc.v_nparts = user_vtoc->v_nparts; 4491 4492 for (i = 0; i < 10; i++) 4493 cl->cl_vtoc.v_reserved[i] = user_vtoc->v_reserved[i]; 4494 4495 /* 4496 * Note the conversion from starting sector number 4497 * to starting cylinder number. 4498 * Return error if division results in a remainder. 4499 */ 4500 lmap = cl->cl_map; 4501 lpart = cl->cl_vtoc.v_part; 4502 vpart = user_vtoc->v_part; 4503 4504 for (i = 0; i < (int)user_vtoc->v_nparts; i++) { 4505 lpart->p_tag = vpart->p_tag; 4506 lpart->p_flag = vpart->p_flag; 4507 lmap->dkl_cylno = (unsigned)vpart->p_start / nblks; 4508 lmap->dkl_nblk = (unsigned)vpart->p_size; 4509 4510 lmap++; 4511 lpart++; 4512 vpart++; 4513 4514 /* (4387723) */ 4515 #ifdef _LP64 4516 if (user_vtoc->timestamp[i] > TIME32_MAX) { 4517 cl->cl_vtoc.v_timestamp[i] = TIME32_MAX; 4518 } else { 4519 cl->cl_vtoc.v_timestamp[i] = user_vtoc->timestamp[i]; 4520 } 4521 #else 4522 cl->cl_vtoc.v_timestamp[i] = user_vtoc->timestamp[i]; 4523 #endif 4524 } 4525 4526 bcopy(user_vtoc->v_asciilabel, cl->cl_asciilabel, LEN_DKL_ASCII); 4527 #else 4528 #error "No VTOC format defined." 4529 #endif 4530 return (0); 4531 } 4532 4533 /* 4534 * Function: cmlb_clear_efi 4535 * 4536 * Description: This routine clears all EFI labels. 4537 * 4538 * Arguments: 4539 * cl driver soft state (unit) structure 4540 * 4541 * tg_cookie cookie from target driver to be passed back to target 4542 * driver when we call back to it through tg_ops. 4543 * Return Code: void 4544 */ 4545 static void 4546 cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie) 4547 { 4548 efi_gpt_t *gpt; 4549 diskaddr_t cap; 4550 int rval; 4551 4552 ASSERT(!mutex_owned(CMLB_MUTEX(cl))); 4553 4554 mutex_enter(CMLB_MUTEX(cl)); 4555 cl->cl_reserved = -1; 4556 mutex_exit(CMLB_MUTEX(cl)); 4557 4558 gpt = kmem_alloc(cl->cl_sys_blocksize, KM_SLEEP); 4559 4560 if (DK_TG_READ(cl, gpt, 1, cl->cl_sys_blocksize, tg_cookie) != 0) { 4561 goto done; 4562 } 4563 4564 cmlb_swap_efi_gpt(gpt); 4565 rval = cmlb_validate_efi(gpt); 4566 if (rval == 0) { 4567 /* clear primary */ 4568 bzero(gpt, sizeof (efi_gpt_t)); 4569 if (rval = DK_TG_WRITE(cl, gpt, 1, cl->cl_sys_blocksize, 4570 tg_cookie)) { 4571 cmlb_dbg(CMLB_INFO, cl, 4572 "cmlb_clear_efi: clear primary label failed\n"); 4573 } 4574 } 4575 /* the backup */ 4576 rval = DK_TG_GETCAP(cl, &cap, tg_cookie); 4577 if (rval) { 4578 goto done; 4579 } 4580 4581 if ((rval = DK_TG_READ(cl, gpt, cap - 1, cl->cl_sys_blocksize, 4582 tg_cookie)) != 0) { 4583 goto done; 4584 } 4585 cmlb_swap_efi_gpt(gpt); 4586 rval = cmlb_validate_efi(gpt); 4587 if (rval == 0) { 4588 /* clear backup */ 4589 cmlb_dbg(CMLB_TRACE, cl, 4590 "cmlb_clear_efi clear backup@%lu\n", cap - 1); 4591 bzero(gpt, sizeof (efi_gpt_t)); 4592 if ((rval = DK_TG_WRITE(cl, gpt, cap - 1, cl->cl_sys_blocksize, 4593 tg_cookie))) { 4594 cmlb_dbg(CMLB_INFO, cl, 4595 "cmlb_clear_efi: clear backup label failed\n"); 4596 } 4597 } else { 4598 /* 4599 * Refer to comments related to off-by-1 at the 4600 * header of this file 4601 */ 4602 if ((rval = DK_TG_READ(cl, gpt, cap - 2, 4603 cl->cl_sys_blocksize, tg_cookie)) != 0) { 4604 goto done; 4605 } 4606 cmlb_swap_efi_gpt(gpt); 4607 rval = cmlb_validate_efi(gpt); 4608 if (rval == 0) { 4609 /* clear legacy backup EFI label */ 4610 cmlb_dbg(CMLB_TRACE, cl, 4611 "cmlb_clear_efi clear legacy backup@%lu\n", 4612 cap - 2); 4613 bzero(gpt, sizeof (efi_gpt_t)); 4614 if ((rval = DK_TG_WRITE(cl, gpt, cap - 2, 4615 cl->cl_sys_blocksize, tg_cookie))) { 4616 cmlb_dbg(CMLB_INFO, cl, 4617 "cmlb_clear_efi: clear legacy backup label " 4618 "failed\n"); 4619 } 4620 } 4621 } 4622 4623 done: 4624 kmem_free(gpt, cl->cl_sys_blocksize); 4625 } 4626 4627 /* 4628 * Function: cmlb_set_vtoc 4629 * 4630 * Description: This routine writes data to the appropriate positions 4631 * 4632 * Arguments: 4633 * cl driver soft state (unit) structure 4634 * 4635 * dkl the data to be written 4636 * 4637 * tg_cookie cookie from target driver to be passed back to target 4638 * driver when we call back to it through tg_ops. 4639 * 4640 * Return: void 4641 */ 4642 static int 4643 cmlb_set_vtoc(struct cmlb_lun *cl, struct dk_label *dkl, void *tg_cookie) 4644 { 4645 uint_t label_addr; 4646 int sec; 4647 diskaddr_t blk; 4648 int head; 4649 int cyl; 4650 int rval; 4651 4652 #if defined(__i386) || defined(__amd64) 4653 label_addr = cl->cl_solaris_offset + DK_LABEL_LOC; 4654 #else 4655 /* Write the primary label at block 0 of the solaris partition. */ 4656 label_addr = 0; 4657 #endif 4658 4659 rval = DK_TG_WRITE(cl, dkl, label_addr, cl->cl_sys_blocksize, 4660 tg_cookie); 4661 4662 if (rval != 0) { 4663 return (rval); 4664 } 4665 4666 /* 4667 * Calculate where the backup labels go. They are always on 4668 * the last alternate cylinder, but some older drives put them 4669 * on head 2 instead of the last head. They are always on the 4670 * first 5 odd sectors of the appropriate track. 4671 * 4672 * We have no choice at this point, but to believe that the 4673 * disk label is valid. Use the geometry of the disk 4674 * as described in the label. 4675 */ 4676 cyl = dkl->dkl_ncyl + dkl->dkl_acyl - 1; 4677 head = dkl->dkl_nhead - 1; 4678 4679 /* 4680 * Write and verify the backup labels. Make sure we don't try to 4681 * write past the last cylinder. 4682 */ 4683 for (sec = 1; ((sec < 5 * 2 + 1) && (sec < dkl->dkl_nsect)); sec += 2) { 4684 blk = (diskaddr_t)( 4685 (cyl * ((dkl->dkl_nhead * dkl->dkl_nsect) - dkl->dkl_apc)) + 4686 (head * dkl->dkl_nsect) + sec); 4687 #if defined(__i386) || defined(__amd64) 4688 blk += cl->cl_solaris_offset; 4689 #endif 4690 rval = DK_TG_WRITE(cl, dkl, blk, cl->cl_sys_blocksize, 4691 tg_cookie); 4692 cmlb_dbg(CMLB_INFO, cl, 4693 "cmlb_set_vtoc: wrote backup label %llx\n", blk); 4694 if (rval != 0) { 4695 goto exit; 4696 } 4697 } 4698 exit: 4699 return (rval); 4700 } 4701 4702 /* 4703 * Function: cmlb_clear_vtoc 4704 * 4705 * Description: This routine clears out the VTOC labels. 4706 * 4707 * Arguments: 4708 * cl driver soft state (unit) structure 4709 * 4710 * tg_cookie cookie from target driver to be passed back to target 4711 * driver when we call back to it through tg_ops. 4712 * 4713 * Return: void 4714 */ 4715 static void 4716 cmlb_clear_vtoc(struct cmlb_lun *cl, void *tg_cookie) 4717 { 4718 struct dk_label *dkl; 4719 4720 mutex_exit(CMLB_MUTEX(cl)); 4721 dkl = kmem_zalloc(cl->cl_sys_blocksize, KM_SLEEP); 4722 mutex_enter(CMLB_MUTEX(cl)); 4723 /* 4724 * cmlb_set_vtoc uses these fields in order to figure out 4725 * where to overwrite the backup labels 4726 */ 4727 dkl->dkl_apc = cl->cl_g.dkg_apc; 4728 dkl->dkl_ncyl = cl->cl_g.dkg_ncyl; 4729 dkl->dkl_acyl = cl->cl_g.dkg_acyl; 4730 dkl->dkl_nhead = cl->cl_g.dkg_nhead; 4731 dkl->dkl_nsect = cl->cl_g.dkg_nsect; 4732 mutex_exit(CMLB_MUTEX(cl)); 4733 (void) cmlb_set_vtoc(cl, dkl, tg_cookie); 4734 kmem_free(dkl, cl->cl_sys_blocksize); 4735 4736 mutex_enter(CMLB_MUTEX(cl)); 4737 } 4738 4739 /* 4740 * Function: cmlb_write_label 4741 * 4742 * Description: This routine will validate and write the driver soft state vtoc 4743 * contents to the device. 4744 * 4745 * Arguments: 4746 * cl cmlb handle 4747 * 4748 * tg_cookie cookie from target driver to be passed back to target 4749 * driver when we call back to it through tg_ops. 4750 * 4751 * 4752 * Return Code: the code returned by cmlb_send_scsi_cmd() 4753 * 0 4754 * EINVAL 4755 * ENXIO 4756 * ENOMEM 4757 */ 4758 static int 4759 cmlb_write_label(struct cmlb_lun *cl, void *tg_cookie) 4760 { 4761 struct dk_label *dkl; 4762 short sum; 4763 short *sp; 4764 int i; 4765 int rval; 4766 4767 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4768 mutex_exit(CMLB_MUTEX(cl)); 4769 dkl = kmem_zalloc(cl->cl_sys_blocksize, KM_SLEEP); 4770 mutex_enter(CMLB_MUTEX(cl)); 4771 4772 bcopy(&cl->cl_vtoc, &dkl->dkl_vtoc, sizeof (struct dk_vtoc)); 4773 dkl->dkl_rpm = cl->cl_g.dkg_rpm; 4774 dkl->dkl_pcyl = cl->cl_g.dkg_pcyl; 4775 dkl->dkl_apc = cl->cl_g.dkg_apc; 4776 dkl->dkl_intrlv = cl->cl_g.dkg_intrlv; 4777 dkl->dkl_ncyl = cl->cl_g.dkg_ncyl; 4778 dkl->dkl_acyl = cl->cl_g.dkg_acyl; 4779 dkl->dkl_nhead = cl->cl_g.dkg_nhead; 4780 dkl->dkl_nsect = cl->cl_g.dkg_nsect; 4781 4782 #if defined(_SUNOS_VTOC_8) 4783 dkl->dkl_obs1 = cl->cl_g.dkg_obs1; 4784 dkl->dkl_obs2 = cl->cl_g.dkg_obs2; 4785 dkl->dkl_obs3 = cl->cl_g.dkg_obs3; 4786 for (i = 0; i < NDKMAP; i++) { 4787 dkl->dkl_map[i].dkl_cylno = cl->cl_map[i].dkl_cylno; 4788 dkl->dkl_map[i].dkl_nblk = cl->cl_map[i].dkl_nblk; 4789 } 4790 bcopy(cl->cl_asciilabel, dkl->dkl_asciilabel, LEN_DKL_ASCII); 4791 #elif defined(_SUNOS_VTOC_16) 4792 dkl->dkl_skew = cl->cl_dkg_skew; 4793 #else 4794 #error "No VTOC format defined." 4795 #endif 4796 4797 dkl->dkl_magic = DKL_MAGIC; 4798 dkl->dkl_write_reinstruct = cl->cl_g.dkg_write_reinstruct; 4799 dkl->dkl_read_reinstruct = cl->cl_g.dkg_read_reinstruct; 4800 4801 /* Construct checksum for the new disk label */ 4802 sum = 0; 4803 sp = (short *)dkl; 4804 i = sizeof (struct dk_label) / sizeof (short); 4805 while (i--) { 4806 sum ^= *sp++; 4807 } 4808 dkl->dkl_cksum = sum; 4809 4810 mutex_exit(CMLB_MUTEX(cl)); 4811 4812 rval = cmlb_set_vtoc(cl, dkl, tg_cookie); 4813 exit: 4814 kmem_free(dkl, cl->cl_sys_blocksize); 4815 mutex_enter(CMLB_MUTEX(cl)); 4816 return (rval); 4817 } 4818 4819 static int 4820 cmlb_dkio_set_efi(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag, 4821 void *tg_cookie) 4822 { 4823 dk_efi_t user_efi; 4824 int rval = 0; 4825 void *buffer; 4826 diskaddr_t tgt_lba; 4827 boolean_t internal; 4828 4829 if (ddi_copyin(arg, &user_efi, sizeof (dk_efi_t), flag)) 4830 return (EFAULT); 4831 4832 internal = VOID2BOOLEAN( 4833 (cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0); 4834 4835 user_efi.dki_data = (void *)(uintptr_t)user_efi.dki_data_64; 4836 4837 buffer = kmem_alloc(user_efi.dki_length, KM_SLEEP); 4838 if (ddi_copyin(user_efi.dki_data, buffer, user_efi.dki_length, flag)) { 4839 rval = EFAULT; 4840 } else { 4841 /* 4842 * let's clear the vtoc labels and clear the softstate 4843 * vtoc. 4844 */ 4845 mutex_enter(CMLB_MUTEX(cl)); 4846 if (cl->cl_vtoc.v_sanity == VTOC_SANE) { 4847 cmlb_dbg(CMLB_TRACE, cl, 4848 "cmlb_dkio_set_efi: CLEAR VTOC\n"); 4849 if (cl->cl_label_from_media == CMLB_LABEL_VTOC) 4850 cmlb_clear_vtoc(cl, tg_cookie); 4851 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 4852 mutex_exit(CMLB_MUTEX(cl)); 4853 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h"); 4854 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h,raw"); 4855 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd", 4856 S_IFBLK, 4857 (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 4858 cl->cl_node_type, NULL, internal); 4859 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd,raw", 4860 S_IFCHR, 4861 (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 4862 cl->cl_node_type, NULL, internal); 4863 } else 4864 mutex_exit(CMLB_MUTEX(cl)); 4865 4866 tgt_lba = user_efi.dki_lba; 4867 4868 mutex_enter(CMLB_MUTEX(cl)); 4869 if ((cmlb_check_update_blockcount(cl, tg_cookie) != 0) || 4870 (cl->cl_tgt_blocksize == 0)) { 4871 kmem_free(buffer, user_efi.dki_length); 4872 mutex_exit(CMLB_MUTEX(cl)); 4873 return (EINVAL); 4874 } 4875 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) 4876 tgt_lba = tgt_lba * 4877 cl->cl_tgt_blocksize / cl->cl_sys_blocksize; 4878 4879 mutex_exit(CMLB_MUTEX(cl)); 4880 rval = DK_TG_WRITE(cl, buffer, tgt_lba, user_efi.dki_length, 4881 tg_cookie); 4882 4883 if (rval == 0) { 4884 mutex_enter(CMLB_MUTEX(cl)); 4885 cl->cl_f_geometry_is_valid = B_FALSE; 4886 mutex_exit(CMLB_MUTEX(cl)); 4887 } 4888 } 4889 kmem_free(buffer, user_efi.dki_length); 4890 return (rval); 4891 } 4892 4893 /* 4894 * Function: cmlb_dkio_get_mboot 4895 * 4896 * Description: This routine is the driver entry point for handling user 4897 * requests to get the current device mboot (DKIOCGMBOOT) 4898 * 4899 * Arguments: 4900 * arg pointer to user provided mboot structure specifying 4901 * the current mboot. 4902 * 4903 * flag this argument is a pass through to ddi_copyxxx() 4904 * directly from the mode argument of ioctl(). 4905 * 4906 * tg_cookie cookie from target driver to be passed back to target 4907 * driver when we call back to it through tg_ops. 4908 * 4909 * Return Code: 0 4910 * EINVAL 4911 * EFAULT 4912 * ENXIO 4913 */ 4914 static int 4915 cmlb_dkio_get_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 4916 { 4917 struct mboot *mboot; 4918 int rval; 4919 size_t buffer_size; 4920 4921 4922 #if defined(_SUNOS_VTOC_8) 4923 if ((!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) || (arg == NULL)) { 4924 #elif defined(_SUNOS_VTOC_16) 4925 if (arg == NULL) { 4926 #endif 4927 return (EINVAL); 4928 } 4929 4930 /* 4931 * Read the mboot block, located at absolute block 0 on the target. 4932 */ 4933 buffer_size = cl->cl_sys_blocksize; 4934 4935 cmlb_dbg(CMLB_TRACE, cl, 4936 "cmlb_dkio_get_mboot: allocation size: 0x%x\n", buffer_size); 4937 4938 mboot = kmem_zalloc(buffer_size, KM_SLEEP); 4939 if ((rval = DK_TG_READ(cl, mboot, 0, buffer_size, tg_cookie)) == 0) { 4940 if (ddi_copyout(mboot, (void *)arg, 4941 sizeof (struct mboot), flag) != 0) { 4942 rval = EFAULT; 4943 } 4944 } 4945 kmem_free(mboot, buffer_size); 4946 return (rval); 4947 } 4948 4949 4950 /* 4951 * Function: cmlb_dkio_set_mboot 4952 * 4953 * Description: This routine is the driver entry point for handling user 4954 * requests to validate and set the device master boot 4955 * (DKIOCSMBOOT). 4956 * 4957 * Arguments: 4958 * arg pointer to user provided mboot structure used to set the 4959 * master boot. 4960 * 4961 * flag this argument is a pass through to ddi_copyxxx() 4962 * directly from the mode argument of ioctl(). 4963 * 4964 * tg_cookie cookie from target driver to be passed back to target 4965 * driver when we call back to it through tg_ops. 4966 * 4967 * Return Code: 0 4968 * EINVAL 4969 * EFAULT 4970 * ENXIO 4971 */ 4972 static int 4973 cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 4974 { 4975 struct mboot *mboot = NULL; 4976 int rval; 4977 ushort_t magic; 4978 4979 4980 ASSERT(!mutex_owned(CMLB_MUTEX(cl))); 4981 4982 #if defined(_SUNOS_VTOC_8) 4983 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 4984 return (EINVAL); 4985 } 4986 #endif 4987 4988 if (arg == NULL) { 4989 return (EINVAL); 4990 } 4991 4992 mboot = kmem_zalloc(cl->cl_sys_blocksize, KM_SLEEP); 4993 4994 if (ddi_copyin((const void *)arg, mboot, 4995 cl->cl_sys_blocksize, flag) != 0) { 4996 kmem_free(mboot, cl->cl_sys_blocksize); 4997 return (EFAULT); 4998 } 4999 5000 /* Is this really a master boot record? */ 5001 magic = LE_16(mboot->signature); 5002 if (magic != MBB_MAGIC) { 5003 kmem_free(mboot, cl->cl_sys_blocksize); 5004 return (EINVAL); 5005 } 5006 5007 rval = DK_TG_WRITE(cl, mboot, 0, cl->cl_sys_blocksize, tg_cookie); 5008 5009 mutex_enter(CMLB_MUTEX(cl)); 5010 #if defined(__i386) || defined(__amd64) 5011 if (rval == 0) { 5012 /* 5013 * mboot has been written successfully. 5014 * update the fdisk and vtoc tables in memory 5015 */ 5016 rval = cmlb_update_fdisk_and_vtoc(cl, tg_cookie); 5017 if ((!cl->cl_f_geometry_is_valid) || (rval != 0)) { 5018 mutex_exit(CMLB_MUTEX(cl)); 5019 kmem_free(mboot, cl->cl_sys_blocksize); 5020 return (rval); 5021 } 5022 } 5023 5024 #ifdef __lock_lint 5025 cmlb_setup_default_geometry(cl, tg_cookie); 5026 #endif 5027 5028 #else 5029 if (rval == 0) { 5030 /* 5031 * mboot has been written successfully. 5032 * set up the default geometry and VTOC 5033 */ 5034 if (cl->cl_blockcount <= CMLB_EXTVTOC_LIMIT) 5035 cmlb_setup_default_geometry(cl, tg_cookie); 5036 } 5037 #endif 5038 cl->cl_msglog_flag |= CMLB_ALLOW_2TB_WARN; 5039 mutex_exit(CMLB_MUTEX(cl)); 5040 kmem_free(mboot, cl->cl_sys_blocksize); 5041 return (rval); 5042 } 5043 5044 5045 #if defined(__i386) || defined(__amd64) 5046 /*ARGSUSED*/ 5047 static int 5048 cmlb_dkio_set_ext_part(struct cmlb_lun *cl, caddr_t arg, int flag, 5049 void *tg_cookie) 5050 { 5051 int fdisk_rval; 5052 diskaddr_t capacity; 5053 5054 ASSERT(!mutex_owned(CMLB_MUTEX(cl))); 5055 5056 mutex_enter(CMLB_MUTEX(cl)); 5057 capacity = cl->cl_blockcount; 5058 fdisk_rval = cmlb_read_fdisk(cl, capacity, tg_cookie); 5059 if (fdisk_rval != 0) { 5060 mutex_exit(CMLB_MUTEX(cl)); 5061 return (fdisk_rval); 5062 } 5063 5064 mutex_exit(CMLB_MUTEX(cl)); 5065 return (fdisk_rval); 5066 } 5067 #endif 5068 5069 /* 5070 * Function: cmlb_setup_default_geometry 5071 * 5072 * Description: This local utility routine sets the default geometry as part of 5073 * setting the device mboot. 5074 * 5075 * Arguments: 5076 * cl driver soft state (unit) structure 5077 * 5078 * tg_cookie cookie from target driver to be passed back to target 5079 * driver when we call back to it through tg_ops. 5080 * 5081 * 5082 * Note: This may be redundant with cmlb_build_default_label. 5083 */ 5084 static void 5085 cmlb_setup_default_geometry(struct cmlb_lun *cl, void *tg_cookie) 5086 { 5087 struct cmlb_geom pgeom; 5088 struct cmlb_geom *pgeomp = &pgeom; 5089 int ret; 5090 int geom_base_cap = 1; 5091 5092 5093 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 5094 5095 /* zero out the soft state geometry and partition table. */ 5096 bzero(&cl->cl_g, sizeof (struct dk_geom)); 5097 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 5098 bzero(cl->cl_map, NDKMAP * (sizeof (struct dk_map))); 5099 5100 /* 5101 * For the rpm, we use the minimum for the disk. 5102 * For the head, cyl and number of sector per track, 5103 * if the capacity <= 1GB, head = 64, sect = 32. 5104 * else head = 255, sect 63 5105 * Note: the capacity should be equal to C*H*S values. 5106 * This will cause some truncation of size due to 5107 * round off errors. For CD-ROMs, this truncation can 5108 * have adverse side effects, so returning ncyl and 5109 * nhead as 1. The nsect will overflow for most of 5110 * CD-ROMs as nsect is of type ushort. 5111 */ 5112 if (cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8) { 5113 /* 5114 * newfs currently can not handle 255 ntracks for SPARC 5115 * so get the geometry from target driver instead of coming up 5116 * with one based on capacity. 5117 */ 5118 mutex_exit(CMLB_MUTEX(cl)); 5119 ret = DK_TG_GETPHYGEOM(cl, pgeomp, tg_cookie); 5120 mutex_enter(CMLB_MUTEX(cl)); 5121 5122 if (ret == 0) { 5123 geom_base_cap = 0; 5124 } else { 5125 cmlb_dbg(CMLB_ERROR, cl, 5126 "cmlb_setup_default_geometry: " 5127 "tg_getphygeom failed %d\n", ret); 5128 5129 /* do default setting, geometry based on capacity */ 5130 } 5131 } 5132 5133 if (geom_base_cap) { 5134 if (ISCD(cl)) { 5135 cl->cl_g.dkg_ncyl = 1; 5136 cl->cl_g.dkg_nhead = 1; 5137 cl->cl_g.dkg_nsect = cl->cl_blockcount; 5138 } else if (cl->cl_blockcount <= 0x1000) { 5139 /* Needed for unlabeled SCSI floppies. */ 5140 cl->cl_g.dkg_nhead = 2; 5141 cl->cl_g.dkg_ncyl = 80; 5142 cl->cl_g.dkg_pcyl = 80; 5143 cl->cl_g.dkg_nsect = cl->cl_blockcount / (2 * 80); 5144 } else if (cl->cl_blockcount <= 0x200000) { 5145 cl->cl_g.dkg_nhead = 64; 5146 cl->cl_g.dkg_nsect = 32; 5147 cl->cl_g.dkg_ncyl = cl->cl_blockcount / (64 * 32); 5148 } else { 5149 cl->cl_g.dkg_nhead = 255; 5150 5151 cl->cl_g.dkg_nsect = ((cl->cl_blockcount + 5152 (UINT16_MAX * 255 * 63) - 1) / 5153 (UINT16_MAX * 255 * 63)) * 63; 5154 5155 if (cl->cl_g.dkg_nsect == 0) 5156 cl->cl_g.dkg_nsect = (UINT16_MAX / 63) * 63; 5157 5158 cl->cl_g.dkg_ncyl = cl->cl_blockcount / 5159 (255 * cl->cl_g.dkg_nsect); 5160 } 5161 5162 cl->cl_g.dkg_acyl = 0; 5163 cl->cl_g.dkg_bcyl = 0; 5164 cl->cl_g.dkg_intrlv = 1; 5165 cl->cl_g.dkg_rpm = 200; 5166 if (cl->cl_g.dkg_pcyl == 0) 5167 cl->cl_g.dkg_pcyl = cl->cl_g.dkg_ncyl + 5168 cl->cl_g.dkg_acyl; 5169 } else { 5170 cl->cl_g.dkg_ncyl = (short)pgeomp->g_ncyl; 5171 cl->cl_g.dkg_acyl = pgeomp->g_acyl; 5172 cl->cl_g.dkg_nhead = pgeomp->g_nhead; 5173 cl->cl_g.dkg_nsect = pgeomp->g_nsect; 5174 cl->cl_g.dkg_intrlv = pgeomp->g_intrlv; 5175 cl->cl_g.dkg_rpm = pgeomp->g_rpm; 5176 cl->cl_g.dkg_pcyl = cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl; 5177 } 5178 5179 cl->cl_g.dkg_read_reinstruct = 0; 5180 cl->cl_g.dkg_write_reinstruct = 0; 5181 cl->cl_solaris_size = cl->cl_g.dkg_ncyl * 5182 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 5183 5184 cl->cl_map['a'-'a'].dkl_cylno = 0; 5185 cl->cl_map['a'-'a'].dkl_nblk = cl->cl_solaris_size; 5186 5187 cl->cl_map['c'-'a'].dkl_cylno = 0; 5188 cl->cl_map['c'-'a'].dkl_nblk = cl->cl_solaris_size; 5189 5190 cl->cl_vtoc.v_part[2].p_tag = V_BACKUP; 5191 cl->cl_vtoc.v_part[2].p_flag = V_UNMNT; 5192 cl->cl_vtoc.v_nparts = V_NUMPAR; 5193 cl->cl_vtoc.v_version = V_VERSION; 5194 (void) sprintf((char *)cl->cl_asciilabel, "DEFAULT cyl %d alt %d" 5195 " hd %d sec %d", cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, 5196 cl->cl_g.dkg_nhead, cl->cl_g.dkg_nsect); 5197 5198 cl->cl_f_geometry_is_valid = B_FALSE; 5199 } 5200 5201 5202 #if defined(__i386) || defined(__amd64) 5203 /* 5204 * Function: cmlb_update_fdisk_and_vtoc 5205 * 5206 * Description: This local utility routine updates the device fdisk and vtoc 5207 * as part of setting the device mboot. 5208 * 5209 * Arguments: 5210 * cl driver soft state (unit) structure 5211 * 5212 * tg_cookie cookie from target driver to be passed back to target 5213 * driver when we call back to it through tg_ops. 5214 * 5215 * 5216 * Return Code: 0 for success or errno-type return code. 5217 * 5218 * Note:x86: This looks like a duplicate of cmlb_validate_geometry(), but 5219 * these did exist separately in x86 sd.c. 5220 */ 5221 static int 5222 cmlb_update_fdisk_and_vtoc(struct cmlb_lun *cl, void *tg_cookie) 5223 { 5224 int count; 5225 int label_rc = 0; 5226 int fdisk_rval; 5227 diskaddr_t capacity; 5228 5229 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 5230 5231 if (cmlb_check_update_blockcount(cl, tg_cookie) != 0) 5232 return (EINVAL); 5233 5234 #if defined(_SUNOS_VTOC_16) 5235 /* 5236 * Set up the "whole disk" fdisk partition; this should always 5237 * exist, regardless of whether the disk contains an fdisk table 5238 * or vtoc. 5239 */ 5240 cl->cl_map[P0_RAW_DISK].dkl_cylno = 0; 5241 cl->cl_map[P0_RAW_DISK].dkl_nblk = cl->cl_blockcount; 5242 #endif /* defined(_SUNOS_VTOC_16) */ 5243 5244 /* 5245 * copy the lbasize and capacity so that if they're 5246 * reset while we're not holding the CMLB_MUTEX(cl), we will 5247 * continue to use valid values after the CMLB_MUTEX(cl) is 5248 * reacquired. 5249 */ 5250 capacity = cl->cl_blockcount; 5251 5252 /* 5253 * refresh the logical and physical geometry caches. 5254 * (data from mode sense format/rigid disk geometry pages, 5255 * and scsi_ifgetcap("geometry"). 5256 */ 5257 cmlb_resync_geom_caches(cl, capacity, tg_cookie); 5258 5259 /* 5260 * Only DIRECT ACCESS devices will have Scl labels. 5261 * CD's supposedly have a Scl label, too 5262 */ 5263 if (cl->cl_device_type == DTYPE_DIRECT || ISREMOVABLE(cl)) { 5264 fdisk_rval = cmlb_read_fdisk(cl, capacity, tg_cookie); 5265 if (fdisk_rval != 0) { 5266 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 5267 return (fdisk_rval); 5268 } 5269 5270 if (cl->cl_solaris_size <= DK_LABEL_LOC) { 5271 /* 5272 * Found fdisk table but no Solaris partition entry, 5273 * so don't call cmlb_uselabel() and don't create 5274 * a default label. 5275 */ 5276 label_rc = 0; 5277 cl->cl_f_geometry_is_valid = B_TRUE; 5278 goto no_solaris_partition; 5279 } 5280 } else if (capacity < 0) { 5281 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 5282 return (EINVAL); 5283 } 5284 5285 /* 5286 * For Removable media We reach here if we have found a 5287 * SOLARIS PARTITION. 5288 * If cl_f_geometry_is_valid is B_FALSE it indicates that the SOLARIS 5289 * PARTITION has changed from the previous one, hence we will setup a 5290 * default VTOC in this case. 5291 */ 5292 if (!cl->cl_f_geometry_is_valid) { 5293 /* if we get here it is writable */ 5294 /* we are called from SMBOOT, and after a write of fdisk */ 5295 cmlb_build_default_label(cl, tg_cookie); 5296 label_rc = 0; 5297 } 5298 5299 no_solaris_partition: 5300 5301 #if defined(_SUNOS_VTOC_16) 5302 /* 5303 * If we have valid geometry, set up the remaining fdisk partitions. 5304 * Note that dkl_cylno is not used for the fdisk map entries, so 5305 * we set it to an entirely bogus value. 5306 */ 5307 for (count = 0; count < FDISK_PARTS; count++) { 5308 cl->cl_map[FDISK_P1 + count].dkl_cylno = UINT32_MAX; 5309 cl->cl_map[FDISK_P1 + count].dkl_nblk = 5310 cl->cl_fmap[count].fmap_nblk; 5311 cl->cl_offset[FDISK_P1 + count] = 5312 cl->cl_fmap[count].fmap_start; 5313 } 5314 #endif 5315 5316 for (count = 0; count < NDKMAP; count++) { 5317 #if defined(_SUNOS_VTOC_8) 5318 struct dk_map *lp = &cl->cl_map[count]; 5319 cl->cl_offset[count] = 5320 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 5321 #elif defined(_SUNOS_VTOC_16) 5322 struct dkl_partition *vp = &cl->cl_vtoc.v_part[count]; 5323 cl->cl_offset[count] = vp->p_start + cl->cl_solaris_offset; 5324 #else 5325 #error "No VTOC format defined." 5326 #endif 5327 } 5328 5329 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 5330 return (label_rc); 5331 } 5332 #endif 5333 5334 #if defined(__i386) || defined(__amd64) 5335 static int 5336 cmlb_dkio_get_virtgeom(struct cmlb_lun *cl, caddr_t arg, int flag) 5337 { 5338 int err = 0; 5339 5340 /* Return the driver's notion of the media's logical geometry */ 5341 struct dk_geom disk_geom; 5342 struct dk_geom *dkgp = &disk_geom; 5343 5344 mutex_enter(CMLB_MUTEX(cl)); 5345 /* 5346 * If there is no HBA geometry available, or 5347 * if the HBA returned us something that doesn't 5348 * really fit into an Int 13/function 8 geometry 5349 * result, just fail the ioctl. See PSARC 1998/313. 5350 */ 5351 if (cl->cl_lgeom.g_nhead == 0 || 5352 cl->cl_lgeom.g_nsect == 0 || 5353 cl->cl_lgeom.g_ncyl > 1024) { 5354 mutex_exit(CMLB_MUTEX(cl)); 5355 err = EINVAL; 5356 } else { 5357 dkgp->dkg_ncyl = cl->cl_lgeom.g_ncyl; 5358 dkgp->dkg_acyl = cl->cl_lgeom.g_acyl; 5359 dkgp->dkg_pcyl = dkgp->dkg_ncyl + dkgp->dkg_acyl; 5360 dkgp->dkg_nhead = cl->cl_lgeom.g_nhead; 5361 dkgp->dkg_nsect = cl->cl_lgeom.g_nsect; 5362 5363 mutex_exit(CMLB_MUTEX(cl)); 5364 if (ddi_copyout(dkgp, (void *)arg, 5365 sizeof (struct dk_geom), flag)) { 5366 err = EFAULT; 5367 } else { 5368 err = 0; 5369 } 5370 } 5371 return (err); 5372 } 5373 #endif 5374 5375 #if defined(__i386) || defined(__amd64) 5376 static int 5377 cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t arg, int flag) 5378 { 5379 int err = 0; 5380 diskaddr_t capacity; 5381 5382 5383 /* Return the driver's notion of the media physical geometry */ 5384 struct dk_geom disk_geom; 5385 struct dk_geom *dkgp = &disk_geom; 5386 5387 mutex_enter(CMLB_MUTEX(cl)); 5388 5389 if (cl->cl_g.dkg_nhead != 0 && 5390 cl->cl_g.dkg_nsect != 0) { 5391 /* 5392 * We succeeded in getting a geometry, but 5393 * right now it is being reported as just the 5394 * Solaris fdisk partition, just like for 5395 * DKIOCGGEOM. We need to change that to be 5396 * correct for the entire disk now. 5397 */ 5398 bcopy(&cl->cl_g, dkgp, sizeof (*dkgp)); 5399 dkgp->dkg_acyl = 0; 5400 dkgp->dkg_ncyl = cl->cl_blockcount / 5401 (dkgp->dkg_nhead * dkgp->dkg_nsect); 5402 } else { 5403 bzero(dkgp, sizeof (struct dk_geom)); 5404 /* 5405 * This disk does not have a Solaris VTOC 5406 * so we must present a physical geometry 5407 * that will remain consistent regardless 5408 * of how the disk is used. This will ensure 5409 * that the geometry does not change regardless 5410 * of the fdisk partition type (ie. EFI, FAT32, 5411 * Solaris, etc). 5412 */ 5413 if (ISCD(cl)) { 5414 dkgp->dkg_nhead = cl->cl_pgeom.g_nhead; 5415 dkgp->dkg_nsect = cl->cl_pgeom.g_nsect; 5416 dkgp->dkg_ncyl = cl->cl_pgeom.g_ncyl; 5417 dkgp->dkg_acyl = cl->cl_pgeom.g_acyl; 5418 } else { 5419 /* 5420 * Invalid cl_blockcount can generate invalid 5421 * dk_geom and may result in division by zero 5422 * system failure. Should make sure blockcount 5423 * is valid before using it here. 5424 */ 5425 if (cl->cl_blockcount == 0) { 5426 mutex_exit(CMLB_MUTEX(cl)); 5427 err = EIO; 5428 return (err); 5429 } 5430 /* 5431 * Refer to comments related to off-by-1 at the 5432 * header of this file 5433 */ 5434 if (cl->cl_alter_behavior & CMLB_OFF_BY_ONE) 5435 capacity = cl->cl_blockcount - 1; 5436 else 5437 capacity = cl->cl_blockcount; 5438 5439 cmlb_convert_geometry(capacity, dkgp); 5440 dkgp->dkg_acyl = 0; 5441 dkgp->dkg_ncyl = capacity / 5442 (dkgp->dkg_nhead * dkgp->dkg_nsect); 5443 } 5444 } 5445 dkgp->dkg_pcyl = dkgp->dkg_ncyl + dkgp->dkg_acyl; 5446 5447 mutex_exit(CMLB_MUTEX(cl)); 5448 if (ddi_copyout(dkgp, (void *)arg, sizeof (struct dk_geom), flag)) 5449 err = EFAULT; 5450 5451 return (err); 5452 } 5453 #endif 5454 5455 #if defined(__i386) || defined(__amd64) 5456 static int 5457 cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag) 5458 { 5459 int err = 0; 5460 5461 /* 5462 * Return parameters describing the selected disk slice. 5463 * Note: this ioctl is for the intel platform only 5464 */ 5465 int part; 5466 5467 part = CMLBPART(dev); 5468 5469 mutex_enter(CMLB_MUTEX(cl)); 5470 /* don't check cl_solaris_size for pN */ 5471 if (part < P0_RAW_DISK && cl->cl_solaris_size == 0) { 5472 err = EIO; 5473 mutex_exit(CMLB_MUTEX(cl)); 5474 } else { 5475 struct part_info p; 5476 5477 p.p_start = (daddr_t)cl->cl_offset[part]; 5478 p.p_length = (int)cl->cl_map[part].dkl_nblk; 5479 mutex_exit(CMLB_MUTEX(cl)); 5480 #ifdef _MULTI_DATAMODEL 5481 switch (ddi_model_convert_from(flag & FMODELS)) { 5482 case DDI_MODEL_ILP32: 5483 { 5484 struct part_info32 p32; 5485 5486 p32.p_start = (daddr32_t)p.p_start; 5487 p32.p_length = p.p_length; 5488 if (ddi_copyout(&p32, (void *)arg, 5489 sizeof (p32), flag)) 5490 err = EFAULT; 5491 break; 5492 } 5493 5494 case DDI_MODEL_NONE: 5495 { 5496 if (ddi_copyout(&p, (void *)arg, sizeof (p), 5497 flag)) 5498 err = EFAULT; 5499 break; 5500 } 5501 } 5502 #else /* ! _MULTI_DATAMODEL */ 5503 if (ddi_copyout(&p, (void *)arg, sizeof (p), flag)) 5504 err = EFAULT; 5505 #endif /* _MULTI_DATAMODEL */ 5506 } 5507 return (err); 5508 } 5509 static int 5510 cmlb_dkio_extpartinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag) 5511 { 5512 int err = 0; 5513 5514 /* 5515 * Return parameters describing the selected disk slice. 5516 * Note: this ioctl is for the intel platform only 5517 */ 5518 int part; 5519 5520 part = CMLBPART(dev); 5521 5522 mutex_enter(CMLB_MUTEX(cl)); 5523 /* don't check cl_solaris_size for pN */ 5524 if (part < P0_RAW_DISK && cl->cl_solaris_size == 0) { 5525 err = EIO; 5526 mutex_exit(CMLB_MUTEX(cl)); 5527 } else { 5528 struct extpart_info p; 5529 5530 p.p_start = (diskaddr_t)cl->cl_offset[part]; 5531 p.p_length = (diskaddr_t)cl->cl_map[part].dkl_nblk; 5532 mutex_exit(CMLB_MUTEX(cl)); 5533 if (ddi_copyout(&p, (void *)arg, sizeof (p), flag)) 5534 err = EFAULT; 5535 } 5536 return (err); 5537 } 5538 #endif 5539 5540 int 5541 cmlb_prop_op(cmlb_handle_t cmlbhandle, 5542 dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 5543 char *name, caddr_t valuep, int *lengthp, int part, void *tg_cookie) 5544 { 5545 struct cmlb_lun *cl; 5546 diskaddr_t capacity; 5547 uint32_t lbasize; 5548 enum dp { DP_NBLOCKS, DP_BLKSIZE } dp; 5549 int callers_length; 5550 caddr_t buffer; 5551 uint64_t nblocks64; 5552 uint_t dblk; 5553 5554 /* Always fallback to ddi_prop_op... */ 5555 cl = (struct cmlb_lun *)cmlbhandle; 5556 if (cl == NULL) { 5557 fallback: return (ddi_prop_op(dev, dip, prop_op, mod_flags, 5558 name, valuep, lengthp)); 5559 } 5560 5561 /* Pick up capacity and blocksize information. */ 5562 capacity = cl->cl_blockcount; 5563 if (capacity == 0) 5564 goto fallback; 5565 lbasize = cl->cl_tgt_blocksize; 5566 if (lbasize == 0) 5567 lbasize = DEV_BSIZE; /* 0 -> DEV_BSIZE units */ 5568 5569 /* Check for dynamic property of whole device. */ 5570 if (dev == DDI_DEV_T_ANY) { 5571 /* Fallback to ddi_prop_op if we don't understand. */ 5572 if (strcmp(name, "device-nblocks") == 0) 5573 dp = DP_NBLOCKS; 5574 else if (strcmp(name, "device-blksize") == 0) 5575 dp = DP_BLKSIZE; 5576 else 5577 goto fallback; 5578 5579 /* get callers length, establish length of our dynamic prop */ 5580 callers_length = *lengthp; 5581 if (dp == DP_NBLOCKS) 5582 *lengthp = sizeof (uint64_t); 5583 else if (dp == DP_BLKSIZE) 5584 *lengthp = sizeof (uint32_t); 5585 5586 /* service request for the length of the property */ 5587 if (prop_op == PROP_LEN) 5588 return (DDI_PROP_SUCCESS); 5589 5590 switch (prop_op) { 5591 case PROP_LEN_AND_VAL_ALLOC: 5592 if ((buffer = kmem_alloc(*lengthp, 5593 (mod_flags & DDI_PROP_CANSLEEP) ? 5594 KM_SLEEP : KM_NOSLEEP)) == NULL) 5595 return (DDI_PROP_NO_MEMORY); 5596 *(caddr_t *)valuep = buffer; /* set callers buf */ 5597 break; 5598 5599 case PROP_LEN_AND_VAL_BUF: 5600 /* the length of the prop and the request must match */ 5601 if (callers_length != *lengthp) 5602 return (DDI_PROP_INVAL_ARG); 5603 buffer = valuep; /* get callers buf */ 5604 break; 5605 5606 default: 5607 return (DDI_PROP_INVAL_ARG); 5608 } 5609 5610 /* transfer the value into the buffer */ 5611 if (dp == DP_NBLOCKS) 5612 *((uint64_t *)buffer) = capacity; 5613 else if (dp == DP_BLKSIZE) 5614 *((uint32_t *)buffer) = lbasize; 5615 5616 return (DDI_PROP_SUCCESS); 5617 } 5618 5619 /* 5620 * Support dynamic size oriented properties of partition. Requests 5621 * issued under conditions where size is valid are passed to 5622 * ddi_prop_op_nblocks with the size information, otherwise the 5623 * request is passed to ddi_prop_op. Size depends on valid geometry. 5624 */ 5625 if (!cmlb_is_valid(cmlbhandle)) 5626 goto fallback; 5627 5628 /* Get partition nblocks value. */ 5629 (void) cmlb_partinfo(cmlbhandle, part, 5630 (diskaddr_t *)&nblocks64, NULL, NULL, NULL, tg_cookie); 5631 5632 /* 5633 * Assume partition information is in sys_blocksize units, compute 5634 * divisor for size(9P) property representation. 5635 */ 5636 dblk = lbasize / cl->cl_sys_blocksize; 5637 5638 /* Now let ddi_prop_op_nblocks_blksize() handle the request. */ 5639 return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op, mod_flags, 5640 name, valuep, lengthp, nblocks64 / dblk, lbasize)); 5641 } 5642