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