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