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