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