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