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