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