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