1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This module provides support for labeling operations for target 31 * drivers. 32 */ 33 34 #include <sys/scsi/scsi.h> 35 #include <sys/sunddi.h> 36 #include <sys/dklabel.h> 37 #include <sys/dkio.h> 38 #include <sys/vtoc.h> 39 #include <sys/dktp/fdisk.h> 40 #include <sys/vtrace.h> 41 #include <sys/efi_partition.h> 42 #include <sys/cmlb.h> 43 #include <sys/cmlb_impl.h> 44 45 /* 46 * Driver minor node structure and data table 47 */ 48 struct driver_minor_data { 49 char *name; 50 minor_t minor; 51 int type; 52 }; 53 54 static struct driver_minor_data dk_minor_data[] = { 55 {"a", 0, S_IFBLK}, 56 {"b", 1, S_IFBLK}, 57 {"c", 2, S_IFBLK}, 58 {"d", 3, S_IFBLK}, 59 {"e", 4, S_IFBLK}, 60 {"f", 5, S_IFBLK}, 61 {"g", 6, S_IFBLK}, 62 {"h", 7, S_IFBLK}, 63 #if defined(_SUNOS_VTOC_16) 64 {"i", 8, S_IFBLK}, 65 {"j", 9, S_IFBLK}, 66 {"k", 10, S_IFBLK}, 67 {"l", 11, S_IFBLK}, 68 {"m", 12, S_IFBLK}, 69 {"n", 13, S_IFBLK}, 70 {"o", 14, S_IFBLK}, 71 {"p", 15, S_IFBLK}, 72 #endif /* defined(_SUNOS_VTOC_16) */ 73 #if defined(_FIRMWARE_NEEDS_FDISK) 74 {"q", 16, S_IFBLK}, 75 {"r", 17, S_IFBLK}, 76 {"s", 18, S_IFBLK}, 77 {"t", 19, S_IFBLK}, 78 {"u", 20, S_IFBLK}, 79 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 80 {"a,raw", 0, S_IFCHR}, 81 {"b,raw", 1, S_IFCHR}, 82 {"c,raw", 2, S_IFCHR}, 83 {"d,raw", 3, S_IFCHR}, 84 {"e,raw", 4, S_IFCHR}, 85 {"f,raw", 5, S_IFCHR}, 86 {"g,raw", 6, S_IFCHR}, 87 {"h,raw", 7, S_IFCHR}, 88 #if defined(_SUNOS_VTOC_16) 89 {"i,raw", 8, S_IFCHR}, 90 {"j,raw", 9, S_IFCHR}, 91 {"k,raw", 10, S_IFCHR}, 92 {"l,raw", 11, S_IFCHR}, 93 {"m,raw", 12, S_IFCHR}, 94 {"n,raw", 13, S_IFCHR}, 95 {"o,raw", 14, S_IFCHR}, 96 {"p,raw", 15, S_IFCHR}, 97 #endif /* defined(_SUNOS_VTOC_16) */ 98 #if defined(_FIRMWARE_NEEDS_FDISK) 99 {"q,raw", 16, S_IFCHR}, 100 {"r,raw", 17, S_IFCHR}, 101 {"s,raw", 18, S_IFCHR}, 102 {"t,raw", 19, S_IFCHR}, 103 {"u,raw", 20, S_IFCHR}, 104 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 105 {0} 106 }; 107 108 static struct driver_minor_data dk_minor_data_efi[] = { 109 {"a", 0, S_IFBLK}, 110 {"b", 1, S_IFBLK}, 111 {"c", 2, S_IFBLK}, 112 {"d", 3, S_IFBLK}, 113 {"e", 4, S_IFBLK}, 114 {"f", 5, S_IFBLK}, 115 {"g", 6, S_IFBLK}, 116 {"wd", 7, S_IFBLK}, 117 #if defined(_FIRMWARE_NEEDS_FDISK) 118 {"q", 16, S_IFBLK}, 119 {"r", 17, S_IFBLK}, 120 {"s", 18, S_IFBLK}, 121 {"t", 19, S_IFBLK}, 122 {"u", 20, S_IFBLK}, 123 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 124 {"a,raw", 0, S_IFCHR}, 125 {"b,raw", 1, S_IFCHR}, 126 {"c,raw", 2, S_IFCHR}, 127 {"d,raw", 3, S_IFCHR}, 128 {"e,raw", 4, S_IFCHR}, 129 {"f,raw", 5, S_IFCHR}, 130 {"g,raw", 6, S_IFCHR}, 131 {"wd,raw", 7, S_IFCHR}, 132 #if defined(_FIRMWARE_NEEDS_FDISK) 133 {"q,raw", 16, S_IFCHR}, 134 {"r,raw", 17, S_IFCHR}, 135 {"s,raw", 18, S_IFCHR}, 136 {"t,raw", 19, S_IFCHR}, 137 {"u,raw", 20, S_IFCHR}, 138 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 139 {0} 140 }; 141 142 143 144 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 2595 cl->cl_g.dkg_nsect = ((cl->cl_blockcount + 2596 (UINT16_MAX * 255 * 63) - 1) / 2597 (UINT16_MAX * 255 * 63)) * 63; 2598 2599 if (cl->cl_g.dkg_nsect == 0) 2600 cl->cl_g.dkg_nsect = (UINT16_MAX / 63) * 63; 2601 2602 cl->cl_g.dkg_ncyl = cl->cl_blockcount / 2603 (255 * cl->cl_g.dkg_nsect); 2604 } 2605 2606 cl->cl_solaris_size = 2607 cl->cl_g.dkg_ncyl * cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 2608 2609 } 2610 2611 cl->cl_g.dkg_acyl = 0; 2612 cl->cl_g.dkg_bcyl = 0; 2613 cl->cl_g.dkg_rpm = 200; 2614 cl->cl_asciilabel[0] = '\0'; 2615 cl->cl_g.dkg_pcyl = cl->cl_g.dkg_ncyl; 2616 2617 cl->cl_map[0].dkl_cylno = 0; 2618 cl->cl_map[0].dkl_nblk = cl->cl_solaris_size; 2619 2620 cl->cl_map[2].dkl_cylno = 0; 2621 cl->cl_map[2].dkl_nblk = cl->cl_solaris_size; 2622 2623 #elif defined(_SUNOS_VTOC_16) 2624 2625 if (cl->cl_solaris_size == 0) { 2626 /* 2627 * Got fdisk table but no solaris entry therefore 2628 * don't create a default label 2629 */ 2630 cl->cl_f_geometry_is_valid = TRUE; 2631 return; 2632 } 2633 2634 /* 2635 * For CDs we continue to use the physical geometry to calculate 2636 * number of cylinders. All other devices must convert the 2637 * physical geometry (cmlb_geom) to values that will fit 2638 * in a dk_geom structure. 2639 */ 2640 if (ISCD(cl)) { 2641 phys_spc = cl->cl_pgeom.g_nhead * cl->cl_pgeom.g_nsect; 2642 } else { 2643 /* Convert physical geometry to disk geometry */ 2644 bzero(&cl_g, sizeof (struct dk_geom)); 2645 2646 /* 2647 * Refer to comments related to off-by-1 at the 2648 * header of this file. 2649 * Before caculating geometry, capacity should be 2650 * decreased by 1. 2651 */ 2652 2653 if (cl->cl_alter_behavior & CMLB_OFF_BY_ONE) 2654 capacity = cl->cl_blockcount - 1; 2655 else 2656 capacity = cl->cl_blockcount; 2657 2658 2659 cmlb_convert_geometry(capacity, &cl_g); 2660 bcopy(&cl_g, &cl->cl_g, sizeof (cl->cl_g)); 2661 phys_spc = cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 2662 } 2663 2664 ASSERT(phys_spc != 0); 2665 cl->cl_g.dkg_pcyl = cl->cl_solaris_size / phys_spc; 2666 if (cl->cl_alter_behavior & CMLB_FAKE_LABEL_ONE_PARTITION) { 2667 /* disable devid */ 2668 cl->cl_g.dkg_ncyl = cl->cl_g.dkg_pcyl; 2669 disksize = cl->cl_solaris_size; 2670 } else { 2671 cl->cl_g.dkg_acyl = DK_ACYL; 2672 cl->cl_g.dkg_ncyl = cl->cl_g.dkg_pcyl - DK_ACYL; 2673 disksize = cl->cl_g.dkg_ncyl * phys_spc; 2674 } 2675 2676 if (ISCD(cl)) { 2677 /* 2678 * CD's don't use the "heads * sectors * cyls"-type of 2679 * geometry, but instead use the entire capacity of the media. 2680 */ 2681 disksize = cl->cl_solaris_size; 2682 cl->cl_g.dkg_nhead = 1; 2683 cl->cl_g.dkg_nsect = 1; 2684 cl->cl_g.dkg_rpm = 2685 (cl->cl_pgeom.g_rpm == 0) ? 200 : cl->cl_pgeom.g_rpm; 2686 2687 cl->cl_vtoc.v_part[0].p_start = 0; 2688 cl->cl_vtoc.v_part[0].p_size = disksize; 2689 cl->cl_vtoc.v_part[0].p_tag = V_BACKUP; 2690 cl->cl_vtoc.v_part[0].p_flag = V_UNMNT; 2691 2692 cl->cl_map[0].dkl_cylno = 0; 2693 cl->cl_map[0].dkl_nblk = disksize; 2694 cl->cl_offset[0] = 0; 2695 2696 } else { 2697 /* 2698 * Hard disks and removable media cartridges 2699 */ 2700 cl->cl_g.dkg_rpm = 2701 (cl->cl_pgeom.g_rpm == 0) ? 3600: cl->cl_pgeom.g_rpm; 2702 cl->cl_vtoc.v_sectorsz = cl->cl_sys_blocksize; 2703 2704 /* Add boot slice */ 2705 cl->cl_vtoc.v_part[8].p_start = 0; 2706 cl->cl_vtoc.v_part[8].p_size = phys_spc; 2707 cl->cl_vtoc.v_part[8].p_tag = V_BOOT; 2708 cl->cl_vtoc.v_part[8].p_flag = V_UNMNT; 2709 2710 cl->cl_map[8].dkl_cylno = 0; 2711 cl->cl_map[8].dkl_nblk = phys_spc; 2712 cl->cl_offset[8] = 0; 2713 2714 if ((cl->cl_alter_behavior & 2715 CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT) && 2716 cl->cl_device_type == DTYPE_DIRECT) { 2717 cl->cl_vtoc.v_part[9].p_start = phys_spc; 2718 cl->cl_vtoc.v_part[9].p_size = 2 * phys_spc; 2719 cl->cl_vtoc.v_part[9].p_tag = V_ALTSCTR; 2720 cl->cl_vtoc.v_part[9].p_flag = 0; 2721 2722 cl->cl_map[9].dkl_cylno = 1; 2723 cl->cl_map[9].dkl_nblk = 2 * phys_spc; 2724 cl->cl_offset[9] = phys_spc; 2725 } 2726 } 2727 2728 cl->cl_g.dkg_apc = 0; 2729 cl->cl_vtoc.v_nparts = V_NUMPAR; 2730 cl->cl_vtoc.v_version = V_VERSION; 2731 2732 /* Add backup slice */ 2733 cl->cl_vtoc.v_part[2].p_start = 0; 2734 cl->cl_vtoc.v_part[2].p_size = disksize; 2735 cl->cl_vtoc.v_part[2].p_tag = V_BACKUP; 2736 cl->cl_vtoc.v_part[2].p_flag = V_UNMNT; 2737 2738 cl->cl_map[2].dkl_cylno = 0; 2739 cl->cl_map[2].dkl_nblk = disksize; 2740 cl->cl_offset[2] = 0; 2741 2742 /* 2743 * single slice (s0) covering the entire disk 2744 */ 2745 if (cl->cl_alter_behavior & CMLB_FAKE_LABEL_ONE_PARTITION) { 2746 cl->cl_vtoc.v_part[0].p_start = 0; 2747 cl->cl_vtoc.v_part[0].p_tag = V_UNASSIGNED; 2748 cl->cl_vtoc.v_part[0].p_flag = 0; 2749 cl->cl_vtoc.v_part[0].p_size = disksize; 2750 cl->cl_map[0].dkl_cylno = 0; 2751 cl->cl_map[0].dkl_nblk = disksize; 2752 cl->cl_offset[0] = 0; 2753 } 2754 2755 (void) sprintf(cl->cl_vtoc.v_asciilabel, "DEFAULT cyl %d alt %d" 2756 " hd %d sec %d", cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, 2757 cl->cl_g.dkg_nhead, cl->cl_g.dkg_nsect); 2758 2759 #else 2760 #error "No VTOC format defined." 2761 #endif 2762 2763 cl->cl_g.dkg_read_reinstruct = 0; 2764 cl->cl_g.dkg_write_reinstruct = 0; 2765 2766 cl->cl_g.dkg_intrlv = 1; 2767 2768 cl->cl_vtoc.v_sanity = VTOC_SANE; 2769 2770 cl->cl_f_geometry_is_valid = TRUE; 2771 cl->cl_vtoc_label_is_from_media = 0; 2772 2773 cmlb_dbg(CMLB_INFO, cl, 2774 "cmlb_build_default_label: Default label created: " 2775 "cyl: %d\tacyl: %d\tnhead: %d\tnsect: %d\tcap: %d\n", 2776 cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, cl->cl_g.dkg_nhead, 2777 cl->cl_g.dkg_nsect, cl->cl_blockcount); 2778 } 2779 2780 2781 #if defined(_FIRMWARE_NEEDS_FDISK) 2782 /* 2783 * Max CHS values, as they are encoded into bytes, for 1022/254/63 2784 */ 2785 #define LBA_MAX_SECT (63 | ((1022 & 0x300) >> 2)) 2786 #define LBA_MAX_CYL (1022 & 0xFF) 2787 #define LBA_MAX_HEAD (254) 2788 2789 2790 /* 2791 * Function: cmlb_has_max_chs_vals 2792 * 2793 * Description: Return TRUE if Cylinder-Head-Sector values are all at maximum. 2794 * 2795 * Arguments: fdp - ptr to CHS info 2796 * 2797 * Return Code: True or false 2798 * 2799 * Context: Any. 2800 */ 2801 static int 2802 cmlb_has_max_chs_vals(struct ipart *fdp) 2803 { 2804 return ((fdp->begcyl == LBA_MAX_CYL) && 2805 (fdp->beghead == LBA_MAX_HEAD) && 2806 (fdp->begsect == LBA_MAX_SECT) && 2807 (fdp->endcyl == LBA_MAX_CYL) && 2808 (fdp->endhead == LBA_MAX_HEAD) && 2809 (fdp->endsect == LBA_MAX_SECT)); 2810 } 2811 #endif 2812 2813 /* 2814 * Function: cmlb_dkio_get_geometry 2815 * 2816 * Description: This routine is the driver entry point for handling user 2817 * requests to get the device geometry (DKIOCGGEOM). 2818 * 2819 * Arguments: 2820 * arg pointer to user provided dk_geom structure specifying 2821 * the controller's notion of the current geometry. 2822 * 2823 * flag this argument is a pass through to ddi_copyxxx() 2824 * directly from the mode argument of ioctl(). 2825 * 2826 * tg_cookie cookie from target driver to be passed back to target 2827 * driver when we call back to it through tg_ops. 2828 * 2829 * Return Code: 0 2830 * EFAULT 2831 * ENXIO 2832 * EIO 2833 */ 2834 static int 2835 cmlb_dkio_get_geometry(struct cmlb_lun *cl, caddr_t arg, int flag, 2836 void *tg_cookie) 2837 { 2838 struct dk_geom *tmp_geom = NULL; 2839 int rval = 0; 2840 2841 /* 2842 * cmlb_validate_geometry does not spin a disk up 2843 * if it was spcl down. We need to make sure it 2844 * is ready. 2845 */ 2846 mutex_enter(CMLB_MUTEX(cl)); 2847 rval = cmlb_validate_geometry(cl, 1, 0, tg_cookie); 2848 #if defined(_SUNOS_VTOC_8) 2849 if (rval == EINVAL && 2850 cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8) { 2851 /* 2852 * This is to return a default label geometry even when we 2853 * do not really assume a default label for the device. 2854 * dad driver utilizes this. 2855 */ 2856 if (cl->cl_blockcount <= DK_MAX_BLOCKS) { 2857 cmlb_setup_default_geometry(cl, tg_cookie); 2858 rval = 0; 2859 } 2860 } 2861 #endif 2862 if (rval) { 2863 mutex_exit(CMLB_MUTEX(cl)); 2864 return (rval); 2865 } 2866 2867 #if defined(__i386) || defined(__amd64) 2868 if (cl->cl_solaris_size == 0) { 2869 mutex_exit(CMLB_MUTEX(cl)); 2870 return (EIO); 2871 } 2872 #endif 2873 2874 /* 2875 * Make a local copy of the soft state geometry to avoid some potential 2876 * race conditions associated with holding the mutex and updating the 2877 * write_reinstruct value 2878 */ 2879 tmp_geom = kmem_zalloc(sizeof (struct dk_geom), KM_SLEEP); 2880 bcopy(&cl->cl_g, tmp_geom, sizeof (struct dk_geom)); 2881 2882 if (tmp_geom->dkg_write_reinstruct == 0) { 2883 tmp_geom->dkg_write_reinstruct = 2884 (int)((int)(tmp_geom->dkg_nsect * tmp_geom->dkg_rpm * 2885 cmlb_rot_delay) / (int)60000); 2886 } 2887 mutex_exit(CMLB_MUTEX(cl)); 2888 2889 rval = ddi_copyout(tmp_geom, (void *)arg, sizeof (struct dk_geom), 2890 flag); 2891 if (rval != 0) { 2892 rval = EFAULT; 2893 } 2894 2895 kmem_free(tmp_geom, sizeof (struct dk_geom)); 2896 return (rval); 2897 2898 } 2899 2900 2901 /* 2902 * Function: cmlb_dkio_set_geometry 2903 * 2904 * Description: This routine is the driver entry point for handling user 2905 * requests to set the device geometry (DKIOCSGEOM). The actual 2906 * device geometry is not updated, just the driver "notion" of it. 2907 * 2908 * Arguments: 2909 * arg pointer to user provided dk_geom structure used to set 2910 * the controller's notion of the current geometry. 2911 * 2912 * flag this argument is a pass through to ddi_copyxxx() 2913 * directly from the mode argument of ioctl(). 2914 * 2915 * tg_cookie cookie from target driver to be passed back to target 2916 * driver when we call back to it through tg_ops. 2917 * 2918 * Return Code: 0 2919 * EFAULT 2920 * ENXIO 2921 * EIO 2922 */ 2923 static int 2924 cmlb_dkio_set_geometry(struct cmlb_lun *cl, caddr_t arg, int flag) 2925 { 2926 struct dk_geom *tmp_geom; 2927 struct dk_map *lp; 2928 int rval = 0; 2929 int i; 2930 2931 2932 #if defined(__i386) || defined(__amd64) 2933 if (cl->cl_solaris_size == 0) { 2934 return (EIO); 2935 } 2936 #endif 2937 /* 2938 * We need to copy the user specified geometry into local 2939 * storage and then update the softstate. We don't want to hold 2940 * the mutex and copyin directly from the user to the soft state 2941 */ 2942 tmp_geom = (struct dk_geom *) 2943 kmem_zalloc(sizeof (struct dk_geom), KM_SLEEP); 2944 rval = ddi_copyin(arg, tmp_geom, sizeof (struct dk_geom), flag); 2945 if (rval != 0) { 2946 kmem_free(tmp_geom, sizeof (struct dk_geom)); 2947 return (EFAULT); 2948 } 2949 2950 mutex_enter(CMLB_MUTEX(cl)); 2951 bcopy(tmp_geom, &cl->cl_g, sizeof (struct dk_geom)); 2952 for (i = 0; i < NDKMAP; i++) { 2953 lp = &cl->cl_map[i]; 2954 cl->cl_offset[i] = 2955 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 2956 #if defined(__i386) || defined(__amd64) 2957 cl->cl_offset[i] += cl->cl_solaris_offset; 2958 #endif 2959 } 2960 cl->cl_f_geometry_is_valid = FALSE; 2961 mutex_exit(CMLB_MUTEX(cl)); 2962 kmem_free(tmp_geom, sizeof (struct dk_geom)); 2963 2964 return (rval); 2965 } 2966 2967 /* 2968 * Function: cmlb_dkio_get_partition 2969 * 2970 * Description: This routine is the driver entry point for handling user 2971 * requests to get the partition table (DKIOCGAPART). 2972 * 2973 * Arguments: 2974 * arg pointer to user provided dk_allmap structure specifying 2975 * the controller's notion of the current partition table. 2976 * 2977 * flag this argument is a pass through to ddi_copyxxx() 2978 * directly from the mode argument of ioctl(). 2979 * 2980 * tg_cookie cookie from target driver to be passed back to target 2981 * driver when we call back to it through tg_ops. 2982 * 2983 * Return Code: 0 2984 * EFAULT 2985 * ENXIO 2986 * EIO 2987 */ 2988 static int 2989 cmlb_dkio_get_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 2990 void *tg_cookie) 2991 { 2992 int rval = 0; 2993 int size; 2994 2995 /* 2996 * Make sure the geometry is valid before getting the partition 2997 * information. 2998 */ 2999 mutex_enter(CMLB_MUTEX(cl)); 3000 if ((rval = cmlb_validate_geometry(cl, 1, 0, tg_cookie)) != 0) { 3001 mutex_exit(CMLB_MUTEX(cl)); 3002 return (rval); 3003 } 3004 mutex_exit(CMLB_MUTEX(cl)); 3005 3006 #if defined(__i386) || defined(__amd64) 3007 if (cl->cl_solaris_size == 0) { 3008 return (EIO); 3009 } 3010 #endif 3011 3012 #ifdef _MULTI_DATAMODEL 3013 switch (ddi_model_convert_from(flag & FMODELS)) { 3014 case DDI_MODEL_ILP32: { 3015 struct dk_map32 dk_map32[NDKMAP]; 3016 int i; 3017 3018 for (i = 0; i < NDKMAP; i++) { 3019 dk_map32[i].dkl_cylno = cl->cl_map[i].dkl_cylno; 3020 dk_map32[i].dkl_nblk = cl->cl_map[i].dkl_nblk; 3021 } 3022 size = NDKMAP * sizeof (struct dk_map32); 3023 rval = ddi_copyout(dk_map32, (void *)arg, size, flag); 3024 if (rval != 0) { 3025 rval = EFAULT; 3026 } 3027 break; 3028 } 3029 case DDI_MODEL_NONE: 3030 size = NDKMAP * sizeof (struct dk_map); 3031 rval = ddi_copyout(cl->cl_map, (void *)arg, size, flag); 3032 if (rval != 0) { 3033 rval = EFAULT; 3034 } 3035 break; 3036 } 3037 #else /* ! _MULTI_DATAMODEL */ 3038 size = NDKMAP * sizeof (struct dk_map); 3039 rval = ddi_copyout(cl->cl_map, (void *)arg, size, flag); 3040 if (rval != 0) { 3041 rval = EFAULT; 3042 } 3043 #endif /* _MULTI_DATAMODEL */ 3044 return (rval); 3045 } 3046 3047 /* 3048 * Function: cmlb_dkio_set_partition 3049 * 3050 * Description: This routine is the driver entry point for handling user 3051 * requests to set the partition table (DKIOCSAPART). The actual 3052 * device partition is not updated. 3053 * 3054 * Arguments: 3055 * arg - pointer to user provided dk_allmap structure used to set 3056 * the controller's notion of the partition table. 3057 * flag - this argument is a pass through to ddi_copyxxx() 3058 * directly from the mode argument of ioctl(). 3059 * 3060 * Return Code: 0 3061 * EINVAL 3062 * EFAULT 3063 * ENXIO 3064 * EIO 3065 */ 3066 static int 3067 cmlb_dkio_set_partition(struct cmlb_lun *cl, caddr_t arg, int flag) 3068 { 3069 struct dk_map dk_map[NDKMAP]; 3070 struct dk_map *lp; 3071 int rval = 0; 3072 int size; 3073 int i; 3074 #if defined(_SUNOS_VTOC_16) 3075 struct dkl_partition *vp; 3076 #endif 3077 3078 /* 3079 * Set the map for all logical partitions. We lock 3080 * the priority just to make sure an interrupt doesn't 3081 * come in while the map is half updated. 3082 */ 3083 _NOTE(DATA_READABLE_WITHOUT_LOCK(cmlb_lun::cl_solaris_size)) 3084 mutex_enter(CMLB_MUTEX(cl)); 3085 3086 if (cl->cl_blockcount > DK_MAX_BLOCKS) { 3087 mutex_exit(CMLB_MUTEX(cl)); 3088 return (ENOTSUP); 3089 } 3090 mutex_exit(CMLB_MUTEX(cl)); 3091 if (cl->cl_solaris_size == 0) { 3092 return (EIO); 3093 } 3094 3095 #ifdef _MULTI_DATAMODEL 3096 switch (ddi_model_convert_from(flag & FMODELS)) { 3097 case DDI_MODEL_ILP32: { 3098 struct dk_map32 dk_map32[NDKMAP]; 3099 3100 size = NDKMAP * sizeof (struct dk_map32); 3101 rval = ddi_copyin((void *)arg, dk_map32, size, flag); 3102 if (rval != 0) { 3103 return (EFAULT); 3104 } 3105 for (i = 0; i < NDKMAP; i++) { 3106 dk_map[i].dkl_cylno = dk_map32[i].dkl_cylno; 3107 dk_map[i].dkl_nblk = dk_map32[i].dkl_nblk; 3108 } 3109 break; 3110 } 3111 case DDI_MODEL_NONE: 3112 size = NDKMAP * sizeof (struct dk_map); 3113 rval = ddi_copyin((void *)arg, dk_map, size, flag); 3114 if (rval != 0) { 3115 return (EFAULT); 3116 } 3117 break; 3118 } 3119 #else /* ! _MULTI_DATAMODEL */ 3120 size = NDKMAP * sizeof (struct dk_map); 3121 rval = ddi_copyin((void *)arg, dk_map, size, flag); 3122 if (rval != 0) { 3123 return (EFAULT); 3124 } 3125 #endif /* _MULTI_DATAMODEL */ 3126 3127 mutex_enter(CMLB_MUTEX(cl)); 3128 /* Note: The size used in this bcopy is set based upon the data model */ 3129 bcopy(dk_map, cl->cl_map, size); 3130 #if defined(_SUNOS_VTOC_16) 3131 vp = (struct dkl_partition *)&(cl->cl_vtoc); 3132 #endif /* defined(_SUNOS_VTOC_16) */ 3133 for (i = 0; i < NDKMAP; i++) { 3134 lp = &cl->cl_map[i]; 3135 cl->cl_offset[i] = 3136 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 3137 #if defined(_SUNOS_VTOC_16) 3138 vp->p_start = cl->cl_offset[i]; 3139 vp->p_size = lp->dkl_nblk; 3140 vp++; 3141 #endif /* defined(_SUNOS_VTOC_16) */ 3142 #if defined(__i386) || defined(__amd64) 3143 cl->cl_offset[i] += cl->cl_solaris_offset; 3144 #endif 3145 } 3146 mutex_exit(CMLB_MUTEX(cl)); 3147 return (rval); 3148 } 3149 3150 3151 /* 3152 * Function: cmlb_dkio_get_vtoc 3153 * 3154 * Description: This routine is the driver entry point for handling user 3155 * requests to get the current volume table of contents 3156 * (DKIOCGVTOC). 3157 * 3158 * Arguments: 3159 * arg pointer to user provided vtoc structure specifying 3160 * the current vtoc. 3161 * 3162 * flag this argument is a pass through to ddi_copyxxx() 3163 * directly from the mode argument of ioctl(). 3164 * 3165 * tg_cookie cookie from target driver to be passed back to target 3166 * driver when we call back to it through tg_ops. 3167 * 3168 * Return Code: 0 3169 * EFAULT 3170 * ENXIO 3171 * EIO 3172 */ 3173 static int 3174 cmlb_dkio_get_vtoc(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 3175 { 3176 #if defined(_SUNOS_VTOC_8) 3177 struct vtoc user_vtoc; 3178 #endif /* defined(_SUNOS_VTOC_8) */ 3179 int rval = 0; 3180 3181 mutex_enter(CMLB_MUTEX(cl)); 3182 rval = cmlb_validate_geometry(cl, 1, 0, tg_cookie); 3183 3184 #if defined(_SUNOS_VTOC_8) 3185 if (rval == EINVAL && 3186 (cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8)) { 3187 /* 3188 * This is to return a default label even when we do not 3189 * really assume a default label for the device. 3190 * dad driver utilizes this. 3191 */ 3192 if (cl->cl_blockcount <= DK_MAX_BLOCKS) { 3193 cmlb_setup_default_geometry(cl, tg_cookie); 3194 rval = 0; 3195 } 3196 } 3197 #endif 3198 if (rval) { 3199 mutex_exit(CMLB_MUTEX(cl)); 3200 return (rval); 3201 } 3202 3203 #if defined(_SUNOS_VTOC_8) 3204 cmlb_build_user_vtoc(cl, &user_vtoc); 3205 mutex_exit(CMLB_MUTEX(cl)); 3206 3207 #ifdef _MULTI_DATAMODEL 3208 switch (ddi_model_convert_from(flag & FMODELS)) { 3209 case DDI_MODEL_ILP32: { 3210 struct vtoc32 user_vtoc32; 3211 3212 vtoctovtoc32(user_vtoc, user_vtoc32); 3213 if (ddi_copyout(&user_vtoc32, (void *)arg, 3214 sizeof (struct vtoc32), flag)) { 3215 return (EFAULT); 3216 } 3217 break; 3218 } 3219 3220 case DDI_MODEL_NONE: 3221 if (ddi_copyout(&user_vtoc, (void *)arg, 3222 sizeof (struct vtoc), flag)) { 3223 return (EFAULT); 3224 } 3225 break; 3226 } 3227 #else /* ! _MULTI_DATAMODEL */ 3228 if (ddi_copyout(&user_vtoc, (void *)arg, sizeof (struct vtoc), flag)) { 3229 return (EFAULT); 3230 } 3231 #endif /* _MULTI_DATAMODEL */ 3232 3233 #elif defined(_SUNOS_VTOC_16) 3234 mutex_exit(CMLB_MUTEX(cl)); 3235 3236 #ifdef _MULTI_DATAMODEL 3237 /* 3238 * The cl_vtoc structure is a "struct dk_vtoc" which is always 3239 * 32-bit to maintain compatibility with existing on-disk 3240 * structures. Thus, we need to convert the structure when copying 3241 * it out to a datamodel-dependent "struct vtoc" in a 64-bit 3242 * program. If the target is a 32-bit program, then no conversion 3243 * is necessary. 3244 */ 3245 /* LINTED: logical expression always true: op "||" */ 3246 ASSERT(sizeof (cl->cl_vtoc) == sizeof (struct vtoc32)); 3247 switch (ddi_model_convert_from(flag & FMODELS)) { 3248 case DDI_MODEL_ILP32: 3249 if (ddi_copyout(&(cl->cl_vtoc), (void *)arg, 3250 sizeof (cl->cl_vtoc), flag)) { 3251 return (EFAULT); 3252 } 3253 break; 3254 3255 case DDI_MODEL_NONE: { 3256 struct vtoc user_vtoc; 3257 3258 vtoc32tovtoc(cl->cl_vtoc, user_vtoc); 3259 if (ddi_copyout(&user_vtoc, (void *)arg, 3260 sizeof (struct vtoc), flag)) { 3261 return (EFAULT); 3262 } 3263 break; 3264 } 3265 } 3266 #else /* ! _MULTI_DATAMODEL */ 3267 if (ddi_copyout(&(cl->cl_vtoc), (void *)arg, sizeof (cl->cl_vtoc), 3268 flag)) { 3269 return (EFAULT); 3270 } 3271 #endif /* _MULTI_DATAMODEL */ 3272 #else 3273 #error "No VTOC format defined." 3274 #endif 3275 3276 return (rval); 3277 } 3278 3279 static int 3280 cmlb_dkio_get_efi(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 3281 { 3282 dk_efi_t user_efi; 3283 int rval = 0; 3284 void *buffer; 3285 diskaddr_t tgt_lba; 3286 3287 if (ddi_copyin(arg, &user_efi, sizeof (dk_efi_t), flag)) 3288 return (EFAULT); 3289 3290 user_efi.dki_data = (void *)(uintptr_t)user_efi.dki_data_64; 3291 3292 tgt_lba = user_efi.dki_lba; 3293 3294 mutex_enter(CMLB_MUTEX(cl)); 3295 if ((cmlb_check_update_blockcount(cl, tg_cookie) != 0) || 3296 (cl->cl_tgt_blocksize == 0)) { 3297 mutex_exit(CMLB_MUTEX(cl)); 3298 return (EINVAL); 3299 } 3300 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) 3301 tgt_lba = tgt_lba * cl->cl_tgt_blocksize / 3302 cl->cl_sys_blocksize; 3303 mutex_exit(CMLB_MUTEX(cl)); 3304 3305 buffer = kmem_alloc(user_efi.dki_length, KM_SLEEP); 3306 rval = DK_TG_READ(cl, buffer, tgt_lba, user_efi.dki_length, tg_cookie); 3307 if (rval == 0 && ddi_copyout(buffer, user_efi.dki_data, 3308 user_efi.dki_length, flag) != 0) 3309 rval = EFAULT; 3310 3311 kmem_free(buffer, user_efi.dki_length); 3312 return (rval); 3313 } 3314 3315 #if defined(_SUNOS_VTOC_8) 3316 /* 3317 * Function: cmlb_build_user_vtoc 3318 * 3319 * Description: This routine populates a pass by reference variable with the 3320 * current volume table of contents. 3321 * 3322 * Arguments: cl - driver soft state (unit) structure 3323 * user_vtoc - pointer to vtoc structure to be populated 3324 */ 3325 static void 3326 cmlb_build_user_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc) 3327 { 3328 struct dk_map2 *lpart; 3329 struct dk_map *lmap; 3330 struct partition *vpart; 3331 int nblks; 3332 int i; 3333 3334 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 3335 3336 /* 3337 * Return vtoc structure fields in the provided VTOC area, addressed 3338 * by *vtoc. 3339 */ 3340 bzero(user_vtoc, sizeof (struct vtoc)); 3341 user_vtoc->v_bootinfo[0] = cl->cl_vtoc.v_bootinfo[0]; 3342 user_vtoc->v_bootinfo[1] = cl->cl_vtoc.v_bootinfo[1]; 3343 user_vtoc->v_bootinfo[2] = cl->cl_vtoc.v_bootinfo[2]; 3344 user_vtoc->v_sanity = VTOC_SANE; 3345 user_vtoc->v_version = cl->cl_vtoc.v_version; 3346 bcopy(cl->cl_vtoc.v_volume, user_vtoc->v_volume, LEN_DKL_VVOL); 3347 user_vtoc->v_sectorsz = cl->cl_sys_blocksize; 3348 user_vtoc->v_nparts = cl->cl_vtoc.v_nparts; 3349 3350 for (i = 0; i < 10; i++) 3351 user_vtoc->v_reserved[i] = cl->cl_vtoc.v_reserved[i]; 3352 3353 /* 3354 * Convert partitioning information. 3355 * 3356 * Note the conversion from starting cylinder number 3357 * to starting sector number. 3358 */ 3359 lmap = cl->cl_map; 3360 lpart = (struct dk_map2 *)cl->cl_vtoc.v_part; 3361 vpart = user_vtoc->v_part; 3362 3363 nblks = cl->cl_g.dkg_nsect * cl->cl_g.dkg_nhead; 3364 3365 for (i = 0; i < V_NUMPAR; i++) { 3366 vpart->p_tag = lpart->p_tag; 3367 vpart->p_flag = lpart->p_flag; 3368 vpart->p_start = lmap->dkl_cylno * nblks; 3369 vpart->p_size = lmap->dkl_nblk; 3370 lmap++; 3371 lpart++; 3372 vpart++; 3373 3374 /* (4364927) */ 3375 user_vtoc->timestamp[i] = (time_t)cl->cl_vtoc.v_timestamp[i]; 3376 } 3377 3378 bcopy(cl->cl_asciilabel, user_vtoc->v_asciilabel, LEN_DKL_ASCII); 3379 } 3380 #endif 3381 3382 static int 3383 cmlb_dkio_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 3384 void *tg_cookie) 3385 { 3386 struct partition64 p64; 3387 int rval = 0; 3388 uint_t nparts; 3389 efi_gpe_t *partitions; 3390 efi_gpt_t *buffer; 3391 diskaddr_t gpe_lba; 3392 3393 if (ddi_copyin((const void *)arg, &p64, 3394 sizeof (struct partition64), flag)) { 3395 return (EFAULT); 3396 } 3397 3398 buffer = kmem_alloc(EFI_MIN_ARRAY_SIZE, KM_SLEEP); 3399 rval = DK_TG_READ(cl, buffer, 1, DEV_BSIZE, tg_cookie); 3400 if (rval != 0) 3401 goto done_error; 3402 3403 cmlb_swap_efi_gpt(buffer); 3404 3405 if ((rval = cmlb_validate_efi(buffer)) != 0) 3406 goto done_error; 3407 3408 nparts = buffer->efi_gpt_NumberOfPartitionEntries; 3409 gpe_lba = buffer->efi_gpt_PartitionEntryLBA; 3410 if (p64.p_partno > nparts) { 3411 /* couldn't find it */ 3412 rval = ESRCH; 3413 goto done_error; 3414 } 3415 /* 3416 * if we're dealing with a partition that's out of the normal 3417 * 16K block, adjust accordingly 3418 */ 3419 gpe_lba += p64.p_partno / sizeof (efi_gpe_t); 3420 rval = DK_TG_READ(cl, buffer, gpe_lba, EFI_MIN_ARRAY_SIZE, tg_cookie); 3421 3422 if (rval) { 3423 goto done_error; 3424 } 3425 partitions = (efi_gpe_t *)buffer; 3426 3427 cmlb_swap_efi_gpe(nparts, partitions); 3428 3429 partitions += p64.p_partno; 3430 bcopy(&partitions->efi_gpe_PartitionTypeGUID, &p64.p_type, 3431 sizeof (struct uuid)); 3432 p64.p_start = partitions->efi_gpe_StartingLBA; 3433 p64.p_size = partitions->efi_gpe_EndingLBA - 3434 p64.p_start + 1; 3435 3436 if (ddi_copyout(&p64, (void *)arg, sizeof (struct partition64), flag)) 3437 rval = EFAULT; 3438 3439 done_error: 3440 kmem_free(buffer, EFI_MIN_ARRAY_SIZE); 3441 return (rval); 3442 } 3443 3444 3445 /* 3446 * Function: cmlb_dkio_set_vtoc 3447 * 3448 * Description: This routine is the driver entry point for handling user 3449 * requests to set the current volume table of contents 3450 * (DKIOCSVTOC). 3451 * 3452 * Arguments: 3453 * dev the device number 3454 * arg pointer to user provided vtoc structure used to set the 3455 * current vtoc. 3456 * 3457 * flag this argument is a pass through to ddi_copyxxx() 3458 * directly from the mode argument of ioctl(). 3459 * 3460 * tg_cookie cookie from target driver to be passed back to target 3461 * driver when we call back to it through tg_ops. 3462 * 3463 * Return Code: 0 3464 * EFAULT 3465 * ENXIO 3466 * EINVAL 3467 * ENOTSUP 3468 */ 3469 static int 3470 cmlb_dkio_set_vtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag, 3471 void *tg_cookie) 3472 { 3473 struct vtoc user_vtoc; 3474 int rval = 0; 3475 3476 #ifdef _MULTI_DATAMODEL 3477 switch (ddi_model_convert_from(flag & FMODELS)) { 3478 case DDI_MODEL_ILP32: { 3479 struct vtoc32 user_vtoc32; 3480 3481 if (ddi_copyin((const void *)arg, &user_vtoc32, 3482 sizeof (struct vtoc32), flag)) { 3483 return (EFAULT); 3484 } 3485 vtoc32tovtoc(user_vtoc32, user_vtoc); 3486 break; 3487 } 3488 3489 case DDI_MODEL_NONE: 3490 if (ddi_copyin((const void *)arg, &user_vtoc, 3491 sizeof (struct vtoc), flag)) { 3492 return (EFAULT); 3493 } 3494 break; 3495 } 3496 #else /* ! _MULTI_DATAMODEL */ 3497 if (ddi_copyin((const void *)arg, &user_vtoc, 3498 sizeof (struct vtoc), flag)) { 3499 return (EFAULT); 3500 } 3501 #endif /* _MULTI_DATAMODEL */ 3502 3503 mutex_enter(CMLB_MUTEX(cl)); 3504 if (cl->cl_blockcount > DK_MAX_BLOCKS) { 3505 mutex_exit(CMLB_MUTEX(cl)); 3506 return (ENOTSUP); 3507 } 3508 3509 #if defined(__i386) || defined(__amd64) 3510 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) { 3511 mutex_exit(CMLB_MUTEX(cl)); 3512 return (EINVAL); 3513 } 3514 #endif 3515 3516 if (cl->cl_g.dkg_ncyl == 0) { 3517 mutex_exit(CMLB_MUTEX(cl)); 3518 return (EINVAL); 3519 } 3520 3521 mutex_exit(CMLB_MUTEX(cl)); 3522 cmlb_clear_efi(cl, tg_cookie); 3523 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd"); 3524 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd,raw"); 3525 (void) ddi_create_minor_node(CMLB_DEVINFO(cl), "h", 3526 S_IFBLK, (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 3527 cl->cl_node_type, NULL); 3528 (void) ddi_create_minor_node(CMLB_DEVINFO(cl), "h,raw", 3529 S_IFCHR, (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 3530 cl->cl_node_type, NULL); 3531 mutex_enter(CMLB_MUTEX(cl)); 3532 3533 if ((rval = cmlb_build_label_vtoc(cl, &user_vtoc)) == 0) { 3534 if ((rval = cmlb_write_label(cl, tg_cookie)) == 0) { 3535 if (cmlb_validate_geometry(cl, 1, 0, tg_cookie) != 0) { 3536 cmlb_dbg(CMLB_ERROR, cl, 3537 "cmlb_dkio_set_vtoc: " 3538 "Failed validate geometry\n"); 3539 } 3540 } 3541 } 3542 mutex_exit(CMLB_MUTEX(cl)); 3543 return (rval); 3544 } 3545 3546 3547 /* 3548 * Function: cmlb_build_label_vtoc 3549 * 3550 * Description: This routine updates the driver soft state current volume table 3551 * of contents based on a user specified vtoc. 3552 * 3553 * Arguments: cl - driver soft state (unit) structure 3554 * user_vtoc - pointer to vtoc structure specifying vtoc to be used 3555 * to update the driver soft state. 3556 * 3557 * Return Code: 0 3558 * EINVAL 3559 */ 3560 static int 3561 cmlb_build_label_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc) 3562 { 3563 struct dk_map *lmap; 3564 struct partition *vpart; 3565 int nblks; 3566 #if defined(_SUNOS_VTOC_8) 3567 int ncyl; 3568 struct dk_map2 *lpart; 3569 #endif /* defined(_SUNOS_VTOC_8) */ 3570 int i; 3571 3572 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 3573 3574 /* Sanity-check the vtoc */ 3575 if (user_vtoc->v_sanity != VTOC_SANE || 3576 user_vtoc->v_sectorsz != cl->cl_sys_blocksize || 3577 user_vtoc->v_nparts != V_NUMPAR) { 3578 cmlb_dbg(CMLB_INFO, cl, 3579 "cmlb_build_label_vtoc: vtoc not valid\n"); 3580 return (EINVAL); 3581 } 3582 3583 nblks = cl->cl_g.dkg_nsect * cl->cl_g.dkg_nhead; 3584 if (nblks == 0) { 3585 cmlb_dbg(CMLB_INFO, cl, 3586 "cmlb_build_label_vtoc: geom nblks is 0\n"); 3587 return (EINVAL); 3588 } 3589 3590 #if defined(_SUNOS_VTOC_8) 3591 vpart = user_vtoc->v_part; 3592 for (i = 0; i < V_NUMPAR; i++) { 3593 if ((vpart->p_start % nblks) != 0) { 3594 cmlb_dbg(CMLB_INFO, cl, 3595 "cmlb_build_label_vtoc: p_start not multiply of" 3596 "nblks part %d p_start %d nblks %d\n", i, 3597 vpart->p_start, nblks); 3598 return (EINVAL); 3599 } 3600 ncyl = vpart->p_start / nblks; 3601 ncyl += vpart->p_size / nblks; 3602 if ((vpart->p_size % nblks) != 0) { 3603 ncyl++; 3604 } 3605 if (ncyl > (int)cl->cl_g.dkg_ncyl) { 3606 cmlb_dbg(CMLB_INFO, cl, 3607 "cmlb_build_label_vtoc: ncyl %d > dkg_ncyl %d" 3608 "p_size %ld p_start %ld nblks %d part number %d" 3609 "tag %d\n", 3610 ncyl, cl->cl_g.dkg_ncyl, vpart->p_size, 3611 vpart->p_start, nblks, 3612 i, vpart->p_tag); 3613 3614 return (EINVAL); 3615 } 3616 vpart++; 3617 } 3618 #endif /* defined(_SUNOS_VTOC_8) */ 3619 3620 /* Put appropriate vtoc structure fields into the disk label */ 3621 #if defined(_SUNOS_VTOC_16) 3622 /* 3623 * The vtoc is always a 32bit data structure to maintain the 3624 * on-disk format. Convert "in place" instead of doing bcopy. 3625 */ 3626 vtoctovtoc32((*user_vtoc), (*((struct vtoc32 *)&(cl->cl_vtoc)))); 3627 3628 /* 3629 * in the 16-slice vtoc, starting sectors are expressed in 3630 * numbers *relative* to the start of the Solaris fdisk partition. 3631 */ 3632 lmap = cl->cl_map; 3633 vpart = user_vtoc->v_part; 3634 3635 for (i = 0; i < (int)user_vtoc->v_nparts; i++, lmap++, vpart++) { 3636 lmap->dkl_cylno = vpart->p_start / nblks; 3637 lmap->dkl_nblk = vpart->p_size; 3638 } 3639 3640 #elif defined(_SUNOS_VTOC_8) 3641 3642 cl->cl_vtoc.v_bootinfo[0] = (uint32_t)user_vtoc->v_bootinfo[0]; 3643 cl->cl_vtoc.v_bootinfo[1] = (uint32_t)user_vtoc->v_bootinfo[1]; 3644 cl->cl_vtoc.v_bootinfo[2] = (uint32_t)user_vtoc->v_bootinfo[2]; 3645 3646 cl->cl_vtoc.v_sanity = (uint32_t)user_vtoc->v_sanity; 3647 cl->cl_vtoc.v_version = (uint32_t)user_vtoc->v_version; 3648 3649 bcopy(user_vtoc->v_volume, cl->cl_vtoc.v_volume, LEN_DKL_VVOL); 3650 3651 cl->cl_vtoc.v_nparts = user_vtoc->v_nparts; 3652 3653 for (i = 0; i < 10; i++) 3654 cl->cl_vtoc.v_reserved[i] = user_vtoc->v_reserved[i]; 3655 3656 /* 3657 * Note the conversion from starting sector number 3658 * to starting cylinder number. 3659 * Return error if division results in a remainder. 3660 */ 3661 lmap = cl->cl_map; 3662 lpart = cl->cl_vtoc.v_part; 3663 vpart = user_vtoc->v_part; 3664 3665 for (i = 0; i < (int)user_vtoc->v_nparts; i++) { 3666 lpart->p_tag = vpart->p_tag; 3667 lpart->p_flag = vpart->p_flag; 3668 lmap->dkl_cylno = vpart->p_start / nblks; 3669 lmap->dkl_nblk = vpart->p_size; 3670 3671 lmap++; 3672 lpart++; 3673 vpart++; 3674 3675 /* (4387723) */ 3676 #ifdef _LP64 3677 if (user_vtoc->timestamp[i] > TIME32_MAX) { 3678 cl->cl_vtoc.v_timestamp[i] = TIME32_MAX; 3679 } else { 3680 cl->cl_vtoc.v_timestamp[i] = user_vtoc->timestamp[i]; 3681 } 3682 #else 3683 cl->cl_vtoc.v_timestamp[i] = user_vtoc->timestamp[i]; 3684 #endif 3685 } 3686 3687 bcopy(user_vtoc->v_asciilabel, cl->cl_asciilabel, LEN_DKL_ASCII); 3688 #else 3689 #error "No VTOC format defined." 3690 #endif 3691 return (0); 3692 } 3693 3694 /* 3695 * Function: cmlb_clear_efi 3696 * 3697 * Description: This routine clears all EFI labels. 3698 * 3699 * Arguments: 3700 * cl driver soft state (unit) structure 3701 * 3702 * tg_cookie cookie from target driver to be passed back to target 3703 * driver when we call back to it through tg_ops. 3704 * Return Code: void 3705 */ 3706 static void 3707 cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie) 3708 { 3709 efi_gpt_t *gpt; 3710 diskaddr_t cap; 3711 int rval; 3712 3713 ASSERT(!mutex_owned(CMLB_MUTEX(cl))); 3714 3715 mutex_enter(CMLB_MUTEX(cl)); 3716 cl->cl_reserved = -1; 3717 mutex_exit(CMLB_MUTEX(cl)); 3718 3719 gpt = kmem_alloc(sizeof (efi_gpt_t), KM_SLEEP); 3720 3721 if (DK_TG_READ(cl, gpt, 1, DEV_BSIZE, tg_cookie) != 0) { 3722 goto done; 3723 } 3724 3725 cmlb_swap_efi_gpt(gpt); 3726 rval = cmlb_validate_efi(gpt); 3727 if (rval == 0) { 3728 /* clear primary */ 3729 bzero(gpt, sizeof (efi_gpt_t)); 3730 if (rval = DK_TG_WRITE(cl, gpt, 1, EFI_LABEL_SIZE, tg_cookie)) { 3731 cmlb_dbg(CMLB_INFO, cl, 3732 "cmlb_clear_efi: clear primary label failed\n"); 3733 } 3734 } 3735 /* the backup */ 3736 rval = DK_TG_GETCAP(cl, &cap, tg_cookie); 3737 if (rval) { 3738 goto done; 3739 } 3740 3741 if ((rval = DK_TG_READ(cl, gpt, cap - 1, EFI_LABEL_SIZE, tg_cookie)) 3742 != 0) { 3743 goto done; 3744 } 3745 cmlb_swap_efi_gpt(gpt); 3746 rval = cmlb_validate_efi(gpt); 3747 if (rval == 0) { 3748 /* clear backup */ 3749 cmlb_dbg(CMLB_TRACE, cl, 3750 "cmlb_clear_efi clear backup@%lu\n", cap - 1); 3751 bzero(gpt, sizeof (efi_gpt_t)); 3752 if ((rval = DK_TG_WRITE(cl, gpt, cap - 1, EFI_LABEL_SIZE, 3753 tg_cookie))) { 3754 cmlb_dbg(CMLB_INFO, cl, 3755 "cmlb_clear_efi: clear backup label failed\n"); 3756 } 3757 } else { 3758 /* 3759 * Refer to comments related to off-by-1 at the 3760 * header of this file 3761 */ 3762 if ((rval = DK_TG_READ(cl, gpt, cap - 2, 3763 EFI_LABEL_SIZE, tg_cookie)) != 0) { 3764 goto done; 3765 } 3766 cmlb_swap_efi_gpt(gpt); 3767 rval = cmlb_validate_efi(gpt); 3768 if (rval == 0) { 3769 /* clear legacy backup EFI label */ 3770 cmlb_dbg(CMLB_TRACE, cl, 3771 "cmlb_clear_efi clear legacy backup@%lu\n", 3772 cap - 2); 3773 bzero(gpt, sizeof (efi_gpt_t)); 3774 if ((rval = DK_TG_WRITE(cl, gpt, cap - 2, 3775 EFI_LABEL_SIZE, tg_cookie))) { 3776 cmlb_dbg(CMLB_INFO, cl, 3777 "cmlb_clear_efi: clear legacy backup label " 3778 "failed\n"); 3779 } 3780 } 3781 } 3782 3783 done: 3784 kmem_free(gpt, sizeof (efi_gpt_t)); 3785 } 3786 3787 /* 3788 * Function: cmlb_set_vtoc 3789 * 3790 * Description: This routine writes data to the appropriate positions 3791 * 3792 * Arguments: 3793 * cl driver soft state (unit) structure 3794 * 3795 * dkl the data to be written 3796 * 3797 * tg_cookie cookie from target driver to be passed back to target 3798 * driver when we call back to it through tg_ops. 3799 * 3800 * Return: void 3801 */ 3802 static int 3803 cmlb_set_vtoc(struct cmlb_lun *cl, struct dk_label *dkl, void *tg_cookie) 3804 { 3805 uint_t label_addr; 3806 int sec; 3807 int blk; 3808 int head; 3809 int cyl; 3810 int rval; 3811 3812 #if defined(__i386) || defined(__amd64) 3813 label_addr = cl->cl_solaris_offset + DK_LABEL_LOC; 3814 #else 3815 /* Write the primary label at block 0 of the solaris partition. */ 3816 label_addr = 0; 3817 #endif 3818 3819 rval = DK_TG_WRITE(cl, dkl, label_addr, cl->cl_sys_blocksize, 3820 tg_cookie); 3821 3822 if (rval != 0) { 3823 return (rval); 3824 } 3825 3826 /* 3827 * Calculate where the backup labels go. They are always on 3828 * the last alternate cylinder, but some older drives put them 3829 * on head 2 instead of the last head. They are always on the 3830 * first 5 odd sectors of the appropriate track. 3831 * 3832 * We have no choice at this point, but to believe that the 3833 * disk label is valid. Use the geometry of the disk 3834 * as described in the label. 3835 */ 3836 cyl = dkl->dkl_ncyl + dkl->dkl_acyl - 1; 3837 head = dkl->dkl_nhead - 1; 3838 3839 /* 3840 * Write and verify the backup labels. Make sure we don't try to 3841 * write past the last cylinder. 3842 */ 3843 for (sec = 1; ((sec < 5 * 2 + 1) && (sec < dkl->dkl_nsect)); sec += 2) { 3844 blk = (daddr_t)( 3845 (cyl * ((dkl->dkl_nhead * dkl->dkl_nsect) - dkl->dkl_apc)) + 3846 (head * dkl->dkl_nsect) + sec); 3847 #if defined(__i386) || defined(__amd64) 3848 blk += cl->cl_solaris_offset; 3849 #endif 3850 rval = DK_TG_WRITE(cl, dkl, blk, cl->cl_sys_blocksize, 3851 tg_cookie); 3852 cmlb_dbg(CMLB_INFO, cl, 3853 "cmlb_set_vtoc: wrote backup label %d\n", blk); 3854 if (rval != 0) { 3855 goto exit; 3856 } 3857 } 3858 exit: 3859 return (rval); 3860 } 3861 3862 /* 3863 * Function: cmlb_clear_vtoc 3864 * 3865 * Description: This routine clears out the VTOC labels. 3866 * 3867 * Arguments: 3868 * cl driver soft state (unit) structure 3869 * 3870 * tg_cookie cookie from target driver to be passed back to target 3871 * driver when we call back to it through tg_ops. 3872 * 3873 * Return: void 3874 */ 3875 static void 3876 cmlb_clear_vtoc(struct cmlb_lun *cl, void *tg_cookie) 3877 { 3878 struct dk_label *dkl; 3879 3880 mutex_exit(CMLB_MUTEX(cl)); 3881 dkl = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 3882 mutex_enter(CMLB_MUTEX(cl)); 3883 /* 3884 * cmlb_set_vtoc uses these fields in order to figure out 3885 * where to overwrite the backup labels 3886 */ 3887 dkl->dkl_apc = cl->cl_g.dkg_apc; 3888 dkl->dkl_ncyl = cl->cl_g.dkg_ncyl; 3889 dkl->dkl_acyl = cl->cl_g.dkg_acyl; 3890 dkl->dkl_nhead = cl->cl_g.dkg_nhead; 3891 dkl->dkl_nsect = cl->cl_g.dkg_nsect; 3892 mutex_exit(CMLB_MUTEX(cl)); 3893 (void) cmlb_set_vtoc(cl, dkl, tg_cookie); 3894 kmem_free(dkl, sizeof (struct dk_label)); 3895 3896 mutex_enter(CMLB_MUTEX(cl)); 3897 } 3898 3899 /* 3900 * Function: cmlb_write_label 3901 * 3902 * Description: This routine will validate and write the driver soft state vtoc 3903 * contents to the device. 3904 * 3905 * Arguments: 3906 * cl cmlb handle 3907 * 3908 * tg_cookie cookie from target driver to be passed back to target 3909 * driver when we call back to it through tg_ops. 3910 * 3911 * 3912 * Return Code: the code returned by cmlb_send_scsi_cmd() 3913 * 0 3914 * EINVAL 3915 * ENXIO 3916 * ENOMEM 3917 */ 3918 static int 3919 cmlb_write_label(struct cmlb_lun *cl, void *tg_cookie) 3920 { 3921 struct dk_label *dkl; 3922 short sum; 3923 short *sp; 3924 int i; 3925 int rval; 3926 3927 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 3928 mutex_exit(CMLB_MUTEX(cl)); 3929 dkl = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 3930 mutex_enter(CMLB_MUTEX(cl)); 3931 3932 bcopy(&cl->cl_vtoc, &dkl->dkl_vtoc, sizeof (struct dk_vtoc)); 3933 dkl->dkl_rpm = cl->cl_g.dkg_rpm; 3934 dkl->dkl_pcyl = cl->cl_g.dkg_pcyl; 3935 dkl->dkl_apc = cl->cl_g.dkg_apc; 3936 dkl->dkl_intrlv = cl->cl_g.dkg_intrlv; 3937 dkl->dkl_ncyl = cl->cl_g.dkg_ncyl; 3938 dkl->dkl_acyl = cl->cl_g.dkg_acyl; 3939 dkl->dkl_nhead = cl->cl_g.dkg_nhead; 3940 dkl->dkl_nsect = cl->cl_g.dkg_nsect; 3941 3942 #if defined(_SUNOS_VTOC_8) 3943 dkl->dkl_obs1 = cl->cl_g.dkg_obs1; 3944 dkl->dkl_obs2 = cl->cl_g.dkg_obs2; 3945 dkl->dkl_obs3 = cl->cl_g.dkg_obs3; 3946 for (i = 0; i < NDKMAP; i++) { 3947 dkl->dkl_map[i].dkl_cylno = cl->cl_map[i].dkl_cylno; 3948 dkl->dkl_map[i].dkl_nblk = cl->cl_map[i].dkl_nblk; 3949 } 3950 bcopy(cl->cl_asciilabel, dkl->dkl_asciilabel, LEN_DKL_ASCII); 3951 #elif defined(_SUNOS_VTOC_16) 3952 dkl->dkl_skew = cl->cl_dkg_skew; 3953 #else 3954 #error "No VTOC format defined." 3955 #endif 3956 3957 dkl->dkl_magic = DKL_MAGIC; 3958 dkl->dkl_write_reinstruct = cl->cl_g.dkg_write_reinstruct; 3959 dkl->dkl_read_reinstruct = cl->cl_g.dkg_read_reinstruct; 3960 3961 /* Construct checksum for the new disk label */ 3962 sum = 0; 3963 sp = (short *)dkl; 3964 i = sizeof (struct dk_label) / sizeof (short); 3965 while (i--) { 3966 sum ^= *sp++; 3967 } 3968 dkl->dkl_cksum = sum; 3969 3970 mutex_exit(CMLB_MUTEX(cl)); 3971 3972 rval = cmlb_set_vtoc(cl, dkl, tg_cookie); 3973 exit: 3974 kmem_free(dkl, sizeof (struct dk_label)); 3975 mutex_enter(CMLB_MUTEX(cl)); 3976 return (rval); 3977 } 3978 3979 static int 3980 cmlb_dkio_set_efi(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag, 3981 void *tg_cookie) 3982 { 3983 dk_efi_t user_efi; 3984 int rval = 0; 3985 void *buffer; 3986 diskaddr_t tgt_lba; 3987 3988 if (ddi_copyin(arg, &user_efi, sizeof (dk_efi_t), flag)) 3989 return (EFAULT); 3990 3991 user_efi.dki_data = (void *)(uintptr_t)user_efi.dki_data_64; 3992 3993 buffer = kmem_alloc(user_efi.dki_length, KM_SLEEP); 3994 if (ddi_copyin(user_efi.dki_data, buffer, user_efi.dki_length, flag)) { 3995 rval = EFAULT; 3996 } else { 3997 /* 3998 * let's clear the vtoc labels and clear the softstate 3999 * vtoc. 4000 */ 4001 mutex_enter(CMLB_MUTEX(cl)); 4002 if (cl->cl_vtoc.v_sanity == VTOC_SANE) { 4003 cmlb_dbg(CMLB_TRACE, cl, 4004 "cmlb_dkio_set_efi: CLEAR VTOC\n"); 4005 if (cl->cl_vtoc_label_is_from_media) 4006 cmlb_clear_vtoc(cl, tg_cookie); 4007 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 4008 mutex_exit(CMLB_MUTEX(cl)); 4009 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h"); 4010 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h,raw"); 4011 (void) ddi_create_minor_node(CMLB_DEVINFO(cl), "wd", 4012 S_IFBLK, 4013 (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 4014 cl->cl_node_type, NULL); 4015 (void) ddi_create_minor_node(CMLB_DEVINFO(cl), "wd,raw", 4016 S_IFCHR, 4017 (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 4018 cl->cl_node_type, NULL); 4019 } else 4020 mutex_exit(CMLB_MUTEX(cl)); 4021 4022 tgt_lba = user_efi.dki_lba; 4023 4024 mutex_enter(CMLB_MUTEX(cl)); 4025 if ((cmlb_check_update_blockcount(cl, tg_cookie) != 0) || 4026 (cl->cl_tgt_blocksize == 0)) { 4027 kmem_free(buffer, user_efi.dki_length); 4028 mutex_exit(CMLB_MUTEX(cl)); 4029 return (EINVAL); 4030 } 4031 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) 4032 tgt_lba = tgt_lba * 4033 cl->cl_tgt_blocksize / cl->cl_sys_blocksize; 4034 4035 mutex_exit(CMLB_MUTEX(cl)); 4036 rval = DK_TG_WRITE(cl, buffer, tgt_lba, user_efi.dki_length, 4037 tg_cookie); 4038 4039 if (rval == 0) { 4040 mutex_enter(CMLB_MUTEX(cl)); 4041 cl->cl_f_geometry_is_valid = FALSE; 4042 mutex_exit(CMLB_MUTEX(cl)); 4043 } 4044 } 4045 kmem_free(buffer, user_efi.dki_length); 4046 return (rval); 4047 } 4048 4049 /* 4050 * Function: cmlb_dkio_get_mboot 4051 * 4052 * Description: This routine is the driver entry point for handling user 4053 * requests to get the current device mboot (DKIOCGMBOOT) 4054 * 4055 * Arguments: 4056 * arg pointer to user provided mboot structure specifying 4057 * the current mboot. 4058 * 4059 * flag this argument is a pass through to ddi_copyxxx() 4060 * directly from the mode argument of ioctl(). 4061 * 4062 * tg_cookie cookie from target driver to be passed back to target 4063 * driver when we call back to it through tg_ops. 4064 * 4065 * Return Code: 0 4066 * EINVAL 4067 * EFAULT 4068 * ENXIO 4069 */ 4070 static int 4071 cmlb_dkio_get_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 4072 { 4073 struct mboot *mboot; 4074 int rval; 4075 size_t buffer_size; 4076 4077 4078 #if defined(_SUNOS_VTOC_8) 4079 if ((!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) || (arg == NULL)) { 4080 #elif defined(_SUNOS_VTOC_16) 4081 if (arg == NULL) { 4082 #endif 4083 return (EINVAL); 4084 } 4085 4086 /* 4087 * Read the mboot block, located at absolute block 0 on the target. 4088 */ 4089 buffer_size = sizeof (struct mboot); 4090 4091 cmlb_dbg(CMLB_TRACE, cl, 4092 "cmlb_dkio_get_mboot: allocation size: 0x%x\n", buffer_size); 4093 4094 mboot = kmem_zalloc(buffer_size, KM_SLEEP); 4095 if ((rval = DK_TG_READ(cl, mboot, 0, buffer_size, tg_cookie)) == 0) { 4096 if (ddi_copyout(mboot, (void *)arg, 4097 sizeof (struct mboot), flag) != 0) { 4098 rval = EFAULT; 4099 } 4100 } 4101 kmem_free(mboot, buffer_size); 4102 return (rval); 4103 } 4104 4105 4106 /* 4107 * Function: cmlb_dkio_set_mboot 4108 * 4109 * Description: This routine is the driver entry point for handling user 4110 * requests to validate and set the device master boot 4111 * (DKIOCSMBOOT). 4112 * 4113 * Arguments: 4114 * arg pointer to user provided mboot structure used to set the 4115 * master boot. 4116 * 4117 * flag this argument is a pass through to ddi_copyxxx() 4118 * directly from the mode argument of ioctl(). 4119 * 4120 * tg_cookie cookie from target driver to be passed back to target 4121 * driver when we call back to it through tg_ops. 4122 * 4123 * Return Code: 0 4124 * EINVAL 4125 * EFAULT 4126 * ENXIO 4127 */ 4128 static int 4129 cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 4130 { 4131 struct mboot *mboot = NULL; 4132 int rval; 4133 ushort_t magic; 4134 4135 4136 ASSERT(!mutex_owned(CMLB_MUTEX(cl))); 4137 4138 #if defined(_SUNOS_VTOC_8) 4139 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 4140 return (EINVAL); 4141 } 4142 #endif 4143 4144 if (arg == NULL) { 4145 return (EINVAL); 4146 } 4147 4148 mboot = kmem_zalloc(sizeof (struct mboot), KM_SLEEP); 4149 4150 if (ddi_copyin((const void *)arg, mboot, 4151 sizeof (struct mboot), flag) != 0) { 4152 kmem_free(mboot, (size_t)(sizeof (struct mboot))); 4153 return (EFAULT); 4154 } 4155 4156 /* Is this really a master boot record? */ 4157 magic = LE_16(mboot->signature); 4158 if (magic != MBB_MAGIC) { 4159 kmem_free(mboot, (size_t)(sizeof (struct mboot))); 4160 return (EINVAL); 4161 } 4162 4163 rval = DK_TG_WRITE(cl, mboot, 0, cl->cl_sys_blocksize, tg_cookie); 4164 4165 mutex_enter(CMLB_MUTEX(cl)); 4166 #if defined(__i386) || defined(__amd64) 4167 if (rval == 0) { 4168 /* 4169 * mboot has been written successfully. 4170 * update the fdisk and vtoc tables in memory 4171 */ 4172 rval = cmlb_update_fdisk_and_vtoc(cl, tg_cookie); 4173 if ((cl->cl_f_geometry_is_valid == FALSE) || (rval != 0)) { 4174 mutex_exit(CMLB_MUTEX(cl)); 4175 kmem_free(mboot, (size_t)(sizeof (struct mboot))); 4176 return (rval); 4177 } 4178 } 4179 4180 #ifdef __lock_lint 4181 cmlb_setup_default_geometry(cl, tg_cookie); 4182 #endif 4183 4184 #else 4185 if (rval == 0) { 4186 /* 4187 * mboot has been written successfully. 4188 * set up the default geometry and VTOC 4189 */ 4190 if (cl->cl_blockcount <= DK_MAX_BLOCKS) 4191 cmlb_setup_default_geometry(cl, tg_cookie); 4192 } 4193 #endif 4194 mutex_exit(CMLB_MUTEX(cl)); 4195 kmem_free(mboot, (size_t)(sizeof (struct mboot))); 4196 return (rval); 4197 } 4198 4199 4200 /* 4201 * Function: cmlb_setup_default_geometry 4202 * 4203 * Description: This local utility routine sets the default geometry as part of 4204 * setting the device mboot. 4205 * 4206 * Arguments: 4207 * cl driver soft state (unit) structure 4208 * 4209 * tg_cookie cookie from target driver to be passed back to target 4210 * driver when we call back to it through tg_ops. 4211 * 4212 * 4213 * Note: This may be redundant with cmlb_build_default_label. 4214 */ 4215 static void 4216 cmlb_setup_default_geometry(struct cmlb_lun *cl, void *tg_cookie) 4217 { 4218 struct cmlb_geom pgeom; 4219 struct cmlb_geom *pgeomp = &pgeom; 4220 int ret; 4221 int geom_base_cap = 1; 4222 4223 4224 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4225 4226 /* zero out the soft state geometry and partition table. */ 4227 bzero(&cl->cl_g, sizeof (struct dk_geom)); 4228 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 4229 bzero(cl->cl_map, NDKMAP * (sizeof (struct dk_map))); 4230 4231 /* 4232 * For the rpm, we use the minimum for the disk. 4233 * For the head, cyl and number of sector per track, 4234 * if the capacity <= 1GB, head = 64, sect = 32. 4235 * else head = 255, sect 63 4236 * Note: the capacity should be equal to C*H*S values. 4237 * This will cause some truncation of size due to 4238 * round off errors. For CD-ROMs, this truncation can 4239 * have adverse side effects, so returning ncyl and 4240 * nhead as 1. The nsect will overflow for most of 4241 * CD-ROMs as nsect is of type ushort. 4242 */ 4243 if (cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8) { 4244 /* 4245 * newfs currently can not handle 255 ntracks for SPARC 4246 * so get the geometry from target driver instead of coming up 4247 * with one based on capacity. 4248 */ 4249 mutex_exit(CMLB_MUTEX(cl)); 4250 ret = DK_TG_GETPHYGEOM(cl, pgeomp, tg_cookie); 4251 mutex_enter(CMLB_MUTEX(cl)); 4252 4253 if (ret == 0) { 4254 geom_base_cap = 0; 4255 } else { 4256 cmlb_dbg(CMLB_ERROR, cl, 4257 "cmlb_setup_default_geometry: " 4258 "tg_getphygeom failed %d\n", ret); 4259 4260 /* do default setting, geometry based on capacity */ 4261 } 4262 } 4263 4264 if (geom_base_cap) { 4265 if (ISCD(cl)) { 4266 cl->cl_g.dkg_ncyl = 1; 4267 cl->cl_g.dkg_nhead = 1; 4268 cl->cl_g.dkg_nsect = cl->cl_blockcount; 4269 } else if (cl->cl_blockcount <= 0x1000) { 4270 /* Needed for unlabeled SCSI floppies. */ 4271 cl->cl_g.dkg_nhead = 2; 4272 cl->cl_g.dkg_ncyl = 80; 4273 cl->cl_g.dkg_pcyl = 80; 4274 cl->cl_g.dkg_nsect = cl->cl_blockcount / (2 * 80); 4275 } else if (cl->cl_blockcount <= 0x200000) { 4276 cl->cl_g.dkg_nhead = 64; 4277 cl->cl_g.dkg_nsect = 32; 4278 cl->cl_g.dkg_ncyl = cl->cl_blockcount / (64 * 32); 4279 } else { 4280 cl->cl_g.dkg_nhead = 255; 4281 4282 cl->cl_g.dkg_nsect = ((cl->cl_blockcount + 4283 (UINT16_MAX * 255 * 63) - 1) / 4284 (UINT16_MAX * 255 * 63)) * 63; 4285 4286 if (cl->cl_g.dkg_nsect == 0) 4287 cl->cl_g.dkg_nsect = (UINT16_MAX / 63) * 63; 4288 4289 cl->cl_g.dkg_ncyl = cl->cl_blockcount / 4290 (255 * cl->cl_g.dkg_nsect); 4291 } 4292 4293 cl->cl_g.dkg_acyl = 0; 4294 cl->cl_g.dkg_bcyl = 0; 4295 cl->cl_g.dkg_intrlv = 1; 4296 cl->cl_g.dkg_rpm = 200; 4297 if (cl->cl_g.dkg_pcyl == 0) 4298 cl->cl_g.dkg_pcyl = cl->cl_g.dkg_ncyl + 4299 cl->cl_g.dkg_acyl; 4300 } else { 4301 cl->cl_g.dkg_ncyl = (short)pgeomp->g_ncyl; 4302 cl->cl_g.dkg_acyl = pgeomp->g_acyl; 4303 cl->cl_g.dkg_nhead = pgeomp->g_nhead; 4304 cl->cl_g.dkg_nsect = pgeomp->g_nsect; 4305 cl->cl_g.dkg_intrlv = pgeomp->g_intrlv; 4306 cl->cl_g.dkg_rpm = pgeomp->g_rpm; 4307 cl->cl_g.dkg_pcyl = cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl; 4308 } 4309 4310 cl->cl_g.dkg_read_reinstruct = 0; 4311 cl->cl_g.dkg_write_reinstruct = 0; 4312 cl->cl_solaris_size = cl->cl_g.dkg_ncyl * 4313 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 4314 4315 cl->cl_map['a'-'a'].dkl_cylno = 0; 4316 cl->cl_map['a'-'a'].dkl_nblk = cl->cl_solaris_size; 4317 4318 cl->cl_map['c'-'a'].dkl_cylno = 0; 4319 cl->cl_map['c'-'a'].dkl_nblk = cl->cl_solaris_size; 4320 4321 cl->cl_vtoc.v_part[2].p_tag = V_BACKUP; 4322 cl->cl_vtoc.v_part[2].p_flag = V_UNMNT; 4323 cl->cl_vtoc.v_nparts = V_NUMPAR; 4324 cl->cl_vtoc.v_version = V_VERSION; 4325 (void) sprintf((char *)cl->cl_asciilabel, "DEFAULT cyl %d alt %d" 4326 " hd %d sec %d", cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, 4327 cl->cl_g.dkg_nhead, cl->cl_g.dkg_nsect); 4328 4329 cl->cl_f_geometry_is_valid = FALSE; 4330 } 4331 4332 4333 #if defined(__i386) || defined(__amd64) 4334 /* 4335 * Function: cmlb_update_fdisk_and_vtoc 4336 * 4337 * Description: This local utility routine updates the device fdisk and vtoc 4338 * as part of setting the device mboot. 4339 * 4340 * Arguments: 4341 * cl driver soft state (unit) structure 4342 * 4343 * tg_cookie cookie from target driver to be passed back to target 4344 * driver when we call back to it through tg_ops. 4345 * 4346 * 4347 * Return Code: 0 for success or errno-type return code. 4348 * 4349 * Note:x86: This looks like a duplicate of cmlb_validate_geometry(), but 4350 * these did exist separately in x86 sd.c. 4351 */ 4352 static int 4353 cmlb_update_fdisk_and_vtoc(struct cmlb_lun *cl, void *tg_cookie) 4354 { 4355 int count; 4356 int label_rc = 0; 4357 int fdisk_rval; 4358 diskaddr_t capacity; 4359 4360 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4361 4362 if (cmlb_check_update_blockcount(cl, tg_cookie) != 0) 4363 return (EINVAL); 4364 4365 #if defined(_SUNOS_VTOC_16) 4366 /* 4367 * Set up the "whole disk" fdisk partition; this should always 4368 * exist, regardless of whether the disk contains an fdisk table 4369 * or vtoc. 4370 */ 4371 cl->cl_map[P0_RAW_DISK].dkl_cylno = 0; 4372 cl->cl_map[P0_RAW_DISK].dkl_nblk = cl->cl_blockcount; 4373 #endif /* defined(_SUNOS_VTOC_16) */ 4374 4375 /* 4376 * copy the lbasize and capacity so that if they're 4377 * reset while we're not holding the CMLB_MUTEX(cl), we will 4378 * continue to use valid values after the CMLB_MUTEX(cl) is 4379 * reacquired. 4380 */ 4381 capacity = cl->cl_blockcount; 4382 4383 /* 4384 * refresh the logical and physical geometry caches. 4385 * (data from mode sense format/rigid disk geometry pages, 4386 * and scsi_ifgetcap("geometry"). 4387 */ 4388 cmlb_resync_geom_caches(cl, capacity, tg_cookie); 4389 4390 /* 4391 * Only DIRECT ACCESS devices will have Scl labels. 4392 * CD's supposedly have a Scl label, too 4393 */ 4394 if (cl->cl_device_type == DTYPE_DIRECT || ISREMOVABLE(cl)) { 4395 fdisk_rval = cmlb_read_fdisk(cl, capacity, tg_cookie); 4396 if (fdisk_rval != 0) { 4397 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4398 return (fdisk_rval); 4399 } 4400 4401 if (cl->cl_solaris_size <= DK_LABEL_LOC) { 4402 /* 4403 * Found fdisk table but no Solaris partition entry, 4404 * so don't call cmlb_uselabel() and don't create 4405 * a default label. 4406 */ 4407 label_rc = 0; 4408 cl->cl_f_geometry_is_valid = TRUE; 4409 goto no_solaris_partition; 4410 } 4411 } else if (capacity < 0) { 4412 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4413 return (EINVAL); 4414 } 4415 4416 /* 4417 * For Removable media We reach here if we have found a 4418 * SOLARIS PARTITION. 4419 * If cl_f_geometry_is_valid is FALSE it indicates that the SOLARIS 4420 * PARTITION has changed from the previous one, hence we will setup a 4421 * default VTOC in this case. 4422 */ 4423 if (cl->cl_f_geometry_is_valid == FALSE) { 4424 /* if we get here it is writable */ 4425 /* we are called from SMBOOT, and after a write of fdisk */ 4426 cmlb_build_default_label(cl, tg_cookie); 4427 label_rc = 0; 4428 } 4429 4430 no_solaris_partition: 4431 4432 #if defined(_SUNOS_VTOC_16) 4433 /* 4434 * If we have valid geometry, set up the remaining fdisk partitions. 4435 * Note that dkl_cylno is not used for the fdisk map entries, so 4436 * we set it to an entirely bogus value. 4437 */ 4438 for (count = 0; count < FD_NUMPART; count++) { 4439 cl->cl_map[FDISK_P1 + count].dkl_cylno = -1; 4440 cl->cl_map[FDISK_P1 + count].dkl_nblk = 4441 cl->cl_fmap[count].fmap_nblk; 4442 cl->cl_offset[FDISK_P1 + count] = 4443 cl->cl_fmap[count].fmap_start; 4444 } 4445 #endif 4446 4447 for (count = 0; count < NDKMAP; count++) { 4448 #if defined(_SUNOS_VTOC_8) 4449 struct dk_map *lp = &cl->cl_map[count]; 4450 cl->cl_offset[count] = 4451 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 4452 #elif defined(_SUNOS_VTOC_16) 4453 struct dkl_partition *vp = &cl->cl_vtoc.v_part[count]; 4454 cl->cl_offset[count] = vp->p_start + cl->cl_solaris_offset; 4455 #else 4456 #error "No VTOC format defined." 4457 #endif 4458 } 4459 4460 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4461 return (label_rc); 4462 } 4463 #endif 4464 4465 #if defined(__i386) || defined(__amd64) 4466 static int 4467 cmlb_dkio_get_virtgeom(struct cmlb_lun *cl, caddr_t arg, int flag) 4468 { 4469 int err = 0; 4470 4471 /* Return the driver's notion of the media's logical geometry */ 4472 struct dk_geom disk_geom; 4473 struct dk_geom *dkgp = &disk_geom; 4474 4475 mutex_enter(CMLB_MUTEX(cl)); 4476 /* 4477 * If there is no HBA geometry available, or 4478 * if the HBA returned us something that doesn't 4479 * really fit into an Int 13/function 8 geometry 4480 * result, just fail the ioctl. See PSARC 1998/313. 4481 */ 4482 if (cl->cl_lgeom.g_nhead == 0 || 4483 cl->cl_lgeom.g_nsect == 0 || 4484 cl->cl_lgeom.g_ncyl > 1024) { 4485 mutex_exit(CMLB_MUTEX(cl)); 4486 err = EINVAL; 4487 } else { 4488 dkgp->dkg_ncyl = cl->cl_lgeom.g_ncyl; 4489 dkgp->dkg_acyl = cl->cl_lgeom.g_acyl; 4490 dkgp->dkg_pcyl = dkgp->dkg_ncyl + dkgp->dkg_acyl; 4491 dkgp->dkg_nhead = cl->cl_lgeom.g_nhead; 4492 dkgp->dkg_nsect = cl->cl_lgeom.g_nsect; 4493 4494 mutex_exit(CMLB_MUTEX(cl)); 4495 if (ddi_copyout(dkgp, (void *)arg, 4496 sizeof (struct dk_geom), flag)) { 4497 err = EFAULT; 4498 } else { 4499 err = 0; 4500 } 4501 } 4502 return (err); 4503 } 4504 #endif 4505 4506 #if defined(__i386) || defined(__amd64) 4507 static int 4508 cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t arg, int flag) 4509 { 4510 int err = 0; 4511 diskaddr_t capacity; 4512 4513 4514 /* Return the driver's notion of the media physical geometry */ 4515 struct dk_geom disk_geom; 4516 struct dk_geom *dkgp = &disk_geom; 4517 4518 mutex_enter(CMLB_MUTEX(cl)); 4519 4520 if (cl->cl_g.dkg_nhead != 0 && 4521 cl->cl_g.dkg_nsect != 0) { 4522 /* 4523 * We succeeded in getting a geometry, but 4524 * right now it is being reported as just the 4525 * Solaris fdisk partition, just like for 4526 * DKIOCGGEOM. We need to change that to be 4527 * correct for the entire disk now. 4528 */ 4529 bcopy(&cl->cl_g, dkgp, sizeof (*dkgp)); 4530 dkgp->dkg_acyl = 0; 4531 dkgp->dkg_ncyl = cl->cl_blockcount / 4532 (dkgp->dkg_nhead * dkgp->dkg_nsect); 4533 } else { 4534 bzero(dkgp, sizeof (struct dk_geom)); 4535 /* 4536 * This disk does not have a Solaris VTOC 4537 * so we must present a physical geometry 4538 * that will remain consistent regardless 4539 * of how the disk is used. This will ensure 4540 * that the geometry does not change regardless 4541 * of the fdisk partition type (ie. EFI, FAT32, 4542 * Solaris, etc). 4543 */ 4544 if (ISCD(cl)) { 4545 dkgp->dkg_nhead = cl->cl_pgeom.g_nhead; 4546 dkgp->dkg_nsect = cl->cl_pgeom.g_nsect; 4547 dkgp->dkg_ncyl = cl->cl_pgeom.g_ncyl; 4548 dkgp->dkg_acyl = cl->cl_pgeom.g_acyl; 4549 } else { 4550 /* 4551 * Invalid cl_blockcount can generate invalid 4552 * dk_geom and may result in division by zero 4553 * system failure. Should make sure blockcount 4554 * is valid before using it here. 4555 */ 4556 if (cl->cl_blockcount == 0) { 4557 mutex_exit(CMLB_MUTEX(cl)); 4558 err = EIO; 4559 return (err); 4560 } 4561 /* 4562 * Refer to comments related to off-by-1 at the 4563 * header of this file 4564 */ 4565 if (cl->cl_alter_behavior & CMLB_OFF_BY_ONE) 4566 capacity = cl->cl_blockcount - 1; 4567 else 4568 capacity = cl->cl_blockcount; 4569 4570 cmlb_convert_geometry(capacity, dkgp); 4571 dkgp->dkg_acyl = 0; 4572 dkgp->dkg_ncyl = capacity / 4573 (dkgp->dkg_nhead * dkgp->dkg_nsect); 4574 } 4575 } 4576 dkgp->dkg_pcyl = dkgp->dkg_ncyl + dkgp->dkg_acyl; 4577 4578 mutex_exit(CMLB_MUTEX(cl)); 4579 if (ddi_copyout(dkgp, (void *)arg, sizeof (struct dk_geom), flag)) 4580 err = EFAULT; 4581 4582 return (err); 4583 } 4584 #endif 4585 4586 #if defined(__i386) || defined(__amd64) 4587 static int 4588 cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag) 4589 { 4590 int err = 0; 4591 4592 /* 4593 * Return parameters describing the selected disk slice. 4594 * Note: this ioctl is for the intel platform only 4595 */ 4596 int part; 4597 4598 part = CMLBPART(dev); 4599 4600 mutex_enter(CMLB_MUTEX(cl)); 4601 /* don't check cl_solaris_size for pN */ 4602 if (part < P0_RAW_DISK && cl->cl_solaris_size == 0) { 4603 err = EIO; 4604 mutex_exit(CMLB_MUTEX(cl)); 4605 } else { 4606 struct part_info p; 4607 4608 p.p_start = (daddr_t)cl->cl_offset[part]; 4609 p.p_length = (int)cl->cl_map[part].dkl_nblk; 4610 mutex_exit(CMLB_MUTEX(cl)); 4611 #ifdef _MULTI_DATAMODEL 4612 switch (ddi_model_convert_from(flag & FMODELS)) { 4613 case DDI_MODEL_ILP32: 4614 { 4615 struct part_info32 p32; 4616 4617 p32.p_start = (daddr32_t)p.p_start; 4618 p32.p_length = p.p_length; 4619 if (ddi_copyout(&p32, (void *)arg, 4620 sizeof (p32), flag)) 4621 err = EFAULT; 4622 break; 4623 } 4624 4625 case DDI_MODEL_NONE: 4626 { 4627 if (ddi_copyout(&p, (void *)arg, sizeof (p), 4628 flag)) 4629 err = EFAULT; 4630 break; 4631 } 4632 } 4633 #else /* ! _MULTI_DATAMODEL */ 4634 if (ddi_copyout(&p, (void *)arg, sizeof (p), flag)) 4635 err = EFAULT; 4636 #endif /* _MULTI_DATAMODEL */ 4637 } 4638 return (err); 4639 } 4640 #endif 4641