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