1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 2083 zl149053 * Common Development and Distribution License (the "License"). 6 2083 zl149053 * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 9889 Larry * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel /* 27 0 stevel * This file contains the code relating to label manipulation. 28 0 stevel */ 29 0 stevel 30 0 stevel #include "global.h" 31 0 stevel #include "label.h" 32 0 stevel #include "misc.h" 33 0 stevel #include "main.h" 34 0 stevel #include "partition.h" 35 0 stevel #include "ctlr_scsi.h" 36 5421 mishra #include "checkdev.h" 37 0 stevel #include <string.h> 38 0 stevel #include <stdlib.h> 39 0 stevel #include <memory.h> 40 0 stevel #include <sys/isa_defs.h> 41 0 stevel #include <sys/efi_partition.h> 42 0 stevel #include <sys/vtoc.h> 43 0 stevel #include <sys/uuid.h> 44 0 stevel #include <errno.h> 45 786 lclee #include <devid.h> 46 0 stevel 47 0 stevel #if defined(_FIRMWARE_NEEDS_FDISK) 48 0 stevel #include <sys/dktp/fdisk.h> 49 0 stevel #include "menu_fdisk.h" 50 0 stevel #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 51 0 stevel 52 0 stevel #ifndef WD_NODE 53 0 stevel #define WD_NODE 7 54 0 stevel #endif 55 0 stevel 56 0 stevel #ifdef __STDC__ 57 0 stevel /* 58 0 stevel * Prototypes for ANSI C compilers 59 0 stevel */ 60 0 stevel static int do_geometry_sanity_check(void); 61 7563 Prasad static int vtoc_to_label(struct dk_label *label, struct extvtoc *vtoc, 62 5084 johnlev struct dk_geom *geom, struct dk_cinfo *cinfo); 63 7563 Prasad extern int read_extvtoc(int, struct extvtoc *); 64 7563 Prasad extern int write_extvtoc(int, struct extvtoc *); 65 0 stevel static int vtoc64_to_label(struct efi_info *, struct dk_gpt *); 66 0 stevel 67 0 stevel #else /* __STDC__ */ 68 0 stevel 69 0 stevel /* 70 0 stevel * Prototypes for non-ANSI C compilers 71 0 stevel */ 72 0 stevel static int do_geometry_sanity_check(); 73 0 stevel static int vtoc_to_label(); 74 7563 Prasad extern int read_extvtoc(); 75 7563 Prasad extern int write_extvtoc(); 76 0 stevel static int vtoc64_to_label(); 77 0 stevel 78 0 stevel #endif /* __STDC__ */ 79 7563 Prasad 80 7563 Prasad #ifdef DEBUG 81 7563 Prasad static void dump_label(struct dk_label *label); 82 7563 Prasad #endif 83 0 stevel 84 0 stevel /* 85 0 stevel * This routine checks the given label to see if it is valid. 86 0 stevel */ 87 0 stevel int 88 0 stevel checklabel(label) 89 0 stevel register struct dk_label *label; 90 0 stevel { 91 0 stevel 92 0 stevel /* 93 0 stevel * Check the magic number. 94 0 stevel */ 95 0 stevel if (label->dkl_magic != DKL_MAGIC) 96 0 stevel return (0); 97 0 stevel /* 98 0 stevel * Check the checksum. 99 0 stevel */ 100 0 stevel if (checksum(label, CK_CHECKSUM) != 0) 101 0 stevel return (0); 102 0 stevel return (1); 103 0 stevel } 104 0 stevel 105 0 stevel /* 106 0 stevel * This routine checks or calculates the label checksum, depending on 107 0 stevel * the mode it is called in. 108 0 stevel */ 109 0 stevel int 110 0 stevel checksum(label, mode) 111 0 stevel struct dk_label *label; 112 0 stevel int mode; 113 0 stevel { 114 0 stevel register short *sp, sum = 0; 115 0 stevel register short count = (sizeof (struct dk_label)) / (sizeof (short)); 116 0 stevel 117 0 stevel /* 118 0 stevel * If we are generating a checksum, don't include the checksum 119 0 stevel * in the rolling xor. 120 0 stevel */ 121 0 stevel if (mode == CK_MAKESUM) 122 0 stevel count -= 1; 123 0 stevel sp = (short *)label; 124 0 stevel /* 125 0 stevel * Take the xor of all the half-words in the label. 126 0 stevel */ 127 0 stevel while (count--) { 128 0 stevel sum ^= *sp++; 129 0 stevel } 130 0 stevel /* 131 0 stevel * If we are checking the checksum, the total will be zero for 132 0 stevel * a correct checksum, so we can just return the sum. 133 0 stevel */ 134 0 stevel if (mode == CK_CHECKSUM) 135 0 stevel return (sum); 136 0 stevel /* 137 0 stevel * If we are generating the checksum, fill it in. 138 0 stevel */ 139 0 stevel else { 140 0 stevel label->dkl_cksum = sum; 141 0 stevel return (0); 142 0 stevel } 143 0 stevel } 144 0 stevel 145 0 stevel /* 146 0 stevel * This routine is used to extract the id string from the string stored 147 0 stevel * in a disk label. The problem is that the string in the label has 148 0 stevel * the physical characteristics of the drive appended to it. The approach 149 0 stevel * is to find the beginning of the physical attributes portion of the string 150 0 stevel * and truncate it there. 151 0 stevel */ 152 0 stevel int 153 0 stevel trim_id(id) 154 0 stevel char *id; 155 0 stevel { 156 0 stevel register char *c; 157 0 stevel 158 0 stevel /* 159 0 stevel * Start at the end of the string. When we match the word ' cyl', 160 0 stevel * we are at the beginning of the attributes. 161 0 stevel */ 162 0 stevel for (c = id + strlen(id); c >= id; c--) { 163 0 stevel if (strncmp(c, " cyl", strlen(" cyl")) == 0) { 164 0 stevel /* 165 0 stevel * Remove any white space. 166 0 stevel */ 167 0 stevel for (; (((*(c - 1) == ' ') || (*(c - 1) == '\t')) && 168 0 stevel (c >= id)); c--); 169 0 stevel break; 170 0 stevel } 171 0 stevel } 172 0 stevel /* 173 0 stevel * If we ran off the beginning of the string, something is wrong. 174 0 stevel */ 175 0 stevel if (c < id) 176 0 stevel return (-1); 177 0 stevel /* 178 0 stevel * Truncate the string. 179 0 stevel */ 180 0 stevel *c = '\0'; 181 0 stevel return (0); 182 0 stevel } 183 0 stevel 184 0 stevel /* 185 0 stevel * This routine is used by write_label() to do a quick sanity check on the 186 0 stevel * supplied geometry. This is not a thorough check. 187 0 stevel * 188 0 stevel * The SCSI READ_CAPACITY command is used here to get the capacity of the 189 0 stevel * disk. But, the available area to store data on a disk is usually less 190 0 stevel * than this. So, if the specified geometry evaluates to a value which falls 191 0 stevel * in this margin, then such illegal geometries can slip through the cracks. 192 0 stevel */ 193 0 stevel static int 194 0 stevel do_geometry_sanity_check() 195 0 stevel { 196 0 stevel struct scsi_capacity_16 capacity; 197 0 stevel 198 0 stevel if (uscsi_read_capacity(cur_file, &capacity)) { 199 0 stevel err_print("Warning: Unable to get capacity." 200 5084 johnlev " Cannot check geometry\n"); 201 0 stevel return (0); /* Just ignore this problem */ 202 0 stevel } 203 0 stevel 204 0 stevel if (capacity.sc_capacity < ncyl * nhead * nsect) { 205 0 stevel err_print("\nWarning: Current geometry overshoots " 206 5084 johnlev "actual geometry of disk\n\n"); 207 0 stevel if (check("Continue labelling disk") != 0) 208 0 stevel return (-1); 209 0 stevel return (0); /* Just ignore this problem */ 210 0 stevel } 211 0 stevel 212 0 stevel return (0); 213 0 stevel } 214 0 stevel 215 0 stevel /* 216 1060 gz161490 * create a clear EFI partition table when format is used 217 7563 Prasad * to convert an SMI label to an EFI label 218 0 stevel */ 219 0 stevel int 220 1067 gz161490 SMI_vtoc_to_EFI(int fd, struct dk_gpt **new_vtoc) 221 0 stevel { 222 1060 gz161490 int i; 223 1060 gz161490 struct dk_gpt *efi; 224 0 stevel 225 0 stevel if (efi_alloc_and_init(fd, EFI_NUMPAR, new_vtoc) != 0) { 226 5084 johnlev err_print("SMI vtoc to EFI failed\n"); 227 5084 johnlev return (-1); 228 0 stevel } 229 1060 gz161490 efi = *new_vtoc; 230 0 stevel 231 0 stevel /* 232 1060 gz161490 * create a clear EFI partition table: 233 1060 gz161490 * s0 takes the whole disk except the primary EFI lable, 234 1060 gz161490 * backup EFI labels, and the reserved partition. 235 1060 gz161490 * s1-s6 are unassigned slices. 236 0 stevel */ 237 1060 gz161490 efi->efi_parts[0].p_tag = V_USR; 238 1060 gz161490 efi->efi_parts[0].p_start = efi->efi_first_u_lba; 239 1060 gz161490 efi->efi_parts[0].p_size = efi->efi_last_u_lba - efi->efi_first_u_lba 240 4304 yl194034 - EFI_MIN_RESV_SIZE + 1; 241 0 stevel 242 1060 gz161490 /* 243 1060 gz161490 * s1-s6 are unassigned slices 244 1060 gz161490 */ 245 1060 gz161490 for (i = 1; i < efi->efi_nparts - 2; i++) { 246 1060 gz161490 efi->efi_parts[i].p_tag = V_UNASSIGNED; 247 1060 gz161490 efi->efi_parts[i].p_start = 0; 248 1060 gz161490 efi->efi_parts[i].p_size = 0; 249 0 stevel } 250 0 stevel 251 0 stevel /* 252 1060 gz161490 * the reserved slice 253 0 stevel */ 254 1060 gz161490 efi->efi_parts[efi->efi_nparts - 1].p_tag = V_RESERVED; 255 1060 gz161490 efi->efi_parts[efi->efi_nparts - 1].p_start = 256 4304 yl194034 efi->efi_last_u_lba - EFI_MIN_RESV_SIZE + 1; 257 1060 gz161490 efi->efi_parts[efi->efi_nparts - 1].p_size = EFI_MIN_RESV_SIZE; 258 0 stevel 259 0 stevel return (0); 260 0 stevel } 261 0 stevel 262 0 stevel /* 263 0 stevel * This routine constructs and writes a label on the disk. It writes both 264 0 stevel * the primary and backup labels. It assumes that there is a current 265 0 stevel * partition map already defined. It also notifies the SunOS kernel of 266 0 stevel * the label and partition information it has written on the disk. 267 0 stevel */ 268 0 stevel int 269 0 stevel write_label() 270 0 stevel { 271 0 stevel int error = 0, head, sec; 272 0 stevel struct dk_label label; 273 7563 Prasad struct extvtoc vtoc; 274 0 stevel struct dk_geom geom; 275 0 stevel struct dk_gpt *vtoc64; 276 0 stevel int nbackups; 277 9889 Larry char *new_label; 278 0 stevel 279 0 stevel #if defined(_SUNOS_VTOC_8) 280 0 stevel int i; 281 0 stevel #endif /* defined(_SUNOS_VTOC_8) */ 282 5421 mishra 283 5421 mishra /* 284 5421 mishra * Check to see if any partitions used for svm, vxvm or live upgrade 285 5421 mishra * are on the disk. If so, refuse to label the disk, but only 286 5421 mishra * if we are trying to shrink a partition in use. 287 5421 mishra */ 288 5421 mishra if (checkdevinuse(cur_disk->disk_name, (diskaddr_t)-1, 289 5421 mishra (diskaddr_t)-1, 0, 1)) { 290 5421 mishra err_print("Cannot label disk when " 291 5421 mishra "partitions are in use as described.\n"); 292 5421 mishra return (-1); 293 5421 mishra } 294 0 stevel 295 0 stevel /* 296 0 stevel * If EFI label, then write it out to disk 297 0 stevel */ 298 0 stevel if (cur_label == L_TYPE_EFI) { 299 5084 johnlev enter_critical(); 300 5084 johnlev vtoc64 = cur_parts->etoc; 301 5084 johnlev err_check(vtoc64); 302 5084 johnlev if (efi_write(cur_file, vtoc64) != 0) { 303 5084 johnlev err_print("Warning: error writing EFI.\n"); 304 5084 johnlev error = -1; 305 5084 johnlev } 306 0 stevel 307 5084 johnlev cur_disk->disk_flags |= DSK_LABEL; 308 5084 johnlev exit_critical(); 309 5084 johnlev return (error); 310 0 stevel } 311 0 stevel 312 0 stevel /* 313 0 stevel * Fill in a label structure with the geometry information. 314 0 stevel */ 315 0 stevel (void) memset((char *)&label, 0, sizeof (struct dk_label)); 316 9889 Larry new_label = zalloc(cur_blksz); 317 9889 Larry 318 0 stevel label.dkl_pcyl = pcyl; 319 0 stevel label.dkl_ncyl = ncyl; 320 0 stevel label.dkl_acyl = acyl; 321 0 stevel 322 0 stevel #if defined(_SUNOS_VTOC_16) 323 0 stevel label.dkl_bcyl = bcyl; 324 0 stevel #endif /* defined(_SUNOC_VTOC_16) */ 325 0 stevel 326 0 stevel label.dkl_nhead = nhead; 327 0 stevel label.dkl_nsect = nsect; 328 0 stevel label.dkl_apc = apc; 329 0 stevel label.dkl_intrlv = 1; 330 0 stevel label.dkl_rpm = cur_dtype->dtype_rpm; 331 0 stevel 332 0 stevel #if defined(_SUNOS_VTOC_8) 333 0 stevel /* 334 0 stevel * Also fill in the current partition information. 335 0 stevel */ 336 0 stevel for (i = 0; i < NDKMAP; i++) { 337 0 stevel label.dkl_map[i] = cur_parts->pinfo_map[i]; 338 0 stevel } 339 0 stevel #endif /* defined(_SUNOS_VTOC_8) */ 340 0 stevel 341 0 stevel label.dkl_magic = DKL_MAGIC; 342 0 stevel 343 0 stevel /* 344 0 stevel * Fill in the vtoc information 345 0 stevel */ 346 0 stevel label.dkl_vtoc = cur_parts->vtoc; 347 0 stevel 348 0 stevel /* 349 0 stevel * Use the current label 350 0 stevel */ 351 0 stevel bcopy(cur_disk->v_volume, label.dkl_vtoc.v_volume, LEN_DKL_VVOL); 352 0 stevel 353 0 stevel /* 354 0 stevel * Put asciilabel in; on x86 it's in the vtoc, not the label. 355 0 stevel */ 356 0 stevel (void) snprintf(label.dkl_asciilabel, sizeof (label.dkl_asciilabel), 357 0 stevel "%s cyl %d alt %d hd %d sec %d", 358 0 stevel cur_dtype->dtype_asciilabel, ncyl, acyl, nhead, nsect); 359 0 stevel 360 0 stevel #if defined(_SUNOS_VTOC_16) 361 0 stevel /* 362 9889 Larry * Also add in v_sectorsz, as the driver will. 363 0 stevel */ 364 9889 Larry label.dkl_vtoc.v_sectorsz = cur_blksz; 365 0 stevel #endif /* defined(_SUNOS_VTOC_16) */ 366 0 stevel 367 0 stevel /* 368 0 stevel * Generate the correct checksum. 369 0 stevel */ 370 0 stevel (void) checksum(&label, CK_MAKESUM); 371 0 stevel /* 372 0 stevel * Convert the label into a vtoc 373 0 stevel */ 374 0 stevel if (label_to_vtoc(&vtoc, &label) == -1) { 375 9889 Larry free(new_label); 376 0 stevel return (-1); 377 0 stevel } 378 0 stevel /* 379 0 stevel * Fill in the geometry info. This is critical that 380 0 stevel * we do this before writing the vtoc. 381 0 stevel */ 382 0 stevel bzero((caddr_t)&geom, sizeof (struct dk_geom)); 383 0 stevel geom.dkg_ncyl = ncyl; 384 0 stevel geom.dkg_acyl = acyl; 385 0 stevel 386 0 stevel #if defined(_SUNOS_VTOC_16) 387 0 stevel geom.dkg_bcyl = bcyl; 388 0 stevel #endif /* defined(_SUNOS_VTOC_16) */ 389 0 stevel 390 0 stevel geom.dkg_nhead = nhead; 391 0 stevel geom.dkg_nsect = nsect; 392 0 stevel geom.dkg_intrlv = 1; 393 0 stevel geom.dkg_apc = apc; 394 0 stevel geom.dkg_rpm = cur_dtype->dtype_rpm; 395 0 stevel geom.dkg_pcyl = pcyl; 396 0 stevel 397 0 stevel /* 398 0 stevel * Make a quick check to see that the geometry is being 399 0 stevel * written now is not way off from the actual capacity 400 0 stevel * of the disk. This is only an appoximate check and 401 0 stevel * is only for SCSI disks. 402 0 stevel */ 403 0 stevel if (SCSI && do_geometry_sanity_check() != 0) { 404 9889 Larry free(new_label); 405 0 stevel return (-1); 406 0 stevel } 407 0 stevel 408 0 stevel /* 409 0 stevel * Lock out interrupts so we do things in sync. 410 0 stevel */ 411 0 stevel enter_critical(); 412 0 stevel /* 413 0 stevel * Do the ioctl to tell the kernel the geometry. 414 0 stevel */ 415 0 stevel if (ioctl(cur_file, DKIOCSGEOM, &geom) == -1) { 416 0 stevel err_print("Warning: error setting drive geometry.\n"); 417 0 stevel error = -1; 418 0 stevel } 419 0 stevel /* 420 0 stevel * Write the vtoc. At the time of this writing, our 421 0 stevel * drivers convert the vtoc back to a label, and 422 0 stevel * then write both the primary and backup labels. 423 0 stevel * This is not a requirement, however, as we 424 0 stevel * always use an ioctl to read the vtoc from the 425 0 stevel * driver, so it can do as it likes. 426 0 stevel */ 427 7563 Prasad if (write_extvtoc(cur_file, &vtoc) != 0) { 428 0 stevel err_print("Warning: error writing VTOC.\n"); 429 0 stevel error = -1; 430 0 stevel } 431 0 stevel 432 0 stevel /* 433 0 stevel * Calculate where the backup labels went. They are always on 434 0 stevel * the last alternate cylinder, but some older drives put them 435 0 stevel * on head 2 instead of the last head. They are always on the 436 0 stevel * first 5 odd sectors of the appropriate track. 437 0 stevel */ 438 0 stevel if (cur_ctype->ctype_flags & CF_BLABEL) 439 0 stevel head = 2; 440 0 stevel else 441 0 stevel head = nhead - 1; 442 0 stevel /* 443 0 stevel * Read and verify the backup labels. 444 0 stevel */ 445 0 stevel nbackups = 0; 446 0 stevel for (sec = 1; ((sec < BAD_LISTCNT * 2 + 1) && (sec < nsect)); 447 0 stevel sec += 2) { 448 0 stevel if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, (diskaddr_t) 449 9889 Larry ((chs2bn(ncyl + acyl - 1, head, sec)) 450 9889 Larry + solaris_offset), 1, new_label, F_NORMAL, NULL)) { 451 9889 Larry err_print("Warning: error reading" 452 9889 Larry "backup label.\n"); 453 0 stevel error = -1; 454 0 stevel } else { 455 9889 Larry if (bcmp((char *)&label, new_label, 456 5084 johnlev sizeof (struct dk_label)) == 0) { 457 9889 Larry nbackups++; 458 0 stevel } 459 0 stevel } 460 0 stevel } 461 0 stevel if (nbackups != BAD_LISTCNT) { 462 0 stevel err_print("Warning: %s\n", nbackups == 0 ? 463 5084 johnlev "no backup labels" : "some backup labels incorrect"); 464 0 stevel } 465 0 stevel /* 466 0 stevel * Mark the current disk as labelled and notify the kernel of what 467 0 stevel * has happened. 468 0 stevel */ 469 0 stevel cur_disk->disk_flags |= DSK_LABEL; 470 0 stevel 471 0 stevel exit_critical(); 472 9889 Larry free(new_label); 473 0 stevel return (error); 474 0 stevel } 475 0 stevel 476 0 stevel 477 0 stevel /* 478 0 stevel * Read the label from the disk. 479 7563 Prasad * Do this via the read_extvtoc() library routine, then convert it to a label. 480 0 stevel * We also need a DKIOCGGEOM ioctl to get the disk's geometry. 481 0 stevel */ 482 0 stevel int 483 0 stevel read_label(int fd, struct dk_label *label) 484 0 stevel { 485 7563 Prasad struct extvtoc vtoc; 486 0 stevel struct dk_geom geom; 487 5084 johnlev struct dk_cinfo dkinfo; 488 0 stevel 489 7563 Prasad if (read_extvtoc(fd, &vtoc) < 0 || 490 5084 johnlev ioctl(fd, DKIOCGGEOM, &geom) == -1 || 491 5084 johnlev ioctl(fd, DKIOCINFO, &dkinfo) == -1) { 492 0 stevel return (-1); 493 0 stevel } 494 5084 johnlev 495 5084 johnlev return (vtoc_to_label(label, &vtoc, &geom, &dkinfo)); 496 0 stevel } 497 0 stevel 498 786 lclee int 499 786 lclee get_disk_info_from_devid(int fd, struct efi_info *label) 500 786 lclee { 501 786 lclee ddi_devid_t devid; 502 786 lclee char *s; 503 786 lclee int n; 504 786 lclee char *vid, *pid; 505 786 lclee int nvid, npid; 506 786 lclee struct dk_minfo minf; 507 786 lclee struct dk_cinfo dkinfo; 508 786 lclee 509 786 lclee if (devid_get(fd, &devid)) { 510 786 lclee if (option_msg && diag_msg) 511 786 lclee err_print("devid_get failed\n"); 512 786 lclee return (-1); 513 786 lclee } 514 786 lclee 515 786 lclee n = devid_sizeof(devid); 516 786 lclee s = (char *)devid; 517 786 lclee 518 786 lclee if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) { 519 786 lclee if (option_msg && diag_msg) 520 786 lclee err_print("DKIOCINFO failed\n"); 521 786 lclee return (-1); 522 786 lclee } 523 786 lclee 524 786 lclee if (dkinfo.dki_ctype != DKC_DIRECT) 525 786 lclee return (-1); 526 786 lclee 527 786 lclee vid = s+12; 528 786 lclee if (!(pid = strchr(vid, '='))) 529 786 lclee return (-1); 530 786 lclee nvid = pid - vid; 531 786 lclee pid += 1; 532 786 lclee npid = n - nvid - 13; 533 786 lclee 534 786 lclee if (nvid > 9) 535 786 lclee nvid = 9; 536 786 lclee if (npid > 17) { 537 786 lclee pid = pid + npid - 17; 538 786 lclee npid = 17; 539 786 lclee } 540 786 lclee 541 786 lclee if (ioctl(fd, DKIOCGMEDIAINFO, &minf) == -1) { 542 786 lclee devid_free(devid); 543 786 lclee return (-1); 544 786 lclee } 545 786 lclee 546 786 lclee (void) strlcpy(label->vendor, vid, nvid); 547 786 lclee (void) strlcpy(label->product, pid, npid); 548 786 lclee (void) strlcpy(label->revision, "0001", 5); 549 786 lclee label->capacity = minf.dki_capacity * minf.dki_lbsize / 512; 550 786 lclee 551 786 lclee devid_free(devid); 552 786 lclee return (0); 553 786 lclee } 554 786 lclee 555 0 stevel /* 556 0 stevel * Issue uscsi_inquiry and read_capacity commands to 557 0 stevel * retrieve the disk's Vendor, Product, Revision and 558 0 stevel * Capacity information. 559 0 stevel */ 560 0 stevel int 561 0 stevel get_disk_info(int fd, struct efi_info *label) 562 0 stevel { 563 0 stevel struct scsi_inquiry inquiry; 564 0 stevel struct scsi_capacity_16 capacity; 565 2083 zl149053 struct dk_minfo minf; 566 786 lclee 567 786 lclee if (!get_disk_info_from_devid(fd, label)) 568 786 lclee return (0); 569 0 stevel 570 0 stevel if (uscsi_inquiry(fd, (char *)&inquiry, sizeof (inquiry))) { 571 2083 zl149053 (void) strlcpy(label->vendor, "Unknown", 8); 572 2083 zl149053 (void) strlcpy(label->product, "Unknown", 8); 573 2083 zl149053 (void) strlcpy(label->revision, "0001", 5); 574 2083 zl149053 } else { 575 2083 zl149053 (void) strlcpy(label->vendor, inquiry.inq_vid, 9); 576 2083 zl149053 (void) strlcpy(label->product, inquiry.inq_pid, 17); 577 2083 zl149053 (void) strlcpy(label->revision, inquiry.inq_revision, 5); 578 0 stevel } 579 0 stevel 580 2083 zl149053 if (uscsi_read_capacity(fd, &capacity)) { 581 2083 zl149053 if (ioctl(fd, DKIOCGMEDIAINFO, &minf) == -1) { 582 2083 zl149053 err_print("Fetch Capacity failed\n"); 583 2083 zl149053 return (-1); 584 2083 zl149053 } 585 9889 Larry label->capacity = 586 9889 Larry minf.dki_capacity * minf.dki_lbsize / cur_blksz; 587 2083 zl149053 } else { 588 2083 zl149053 label->capacity = capacity.sc_capacity; 589 0 stevel 590 2083 zl149053 /* Since we are counting from zero, add 1 to capacity */ 591 2083 zl149053 label->capacity++; 592 2083 zl149053 } 593 2083 zl149053 594 0 stevel return (0); 595 0 stevel } 596 0 stevel 597 0 stevel int 598 0 stevel read_efi_label(int fd, struct efi_info *label) 599 0 stevel { 600 0 stevel struct dk_gpt *vtoc64; 601 0 stevel 602 0 stevel /* This could fail if there is no label already */ 603 0 stevel if (efi_alloc_and_read(fd, &vtoc64) < 0) { 604 0 stevel return (-1); 605 0 stevel } 606 0 stevel if (vtoc64_to_label(label, vtoc64) != 0) { 607 0 stevel err_print("vtoc64_to_label failed\n"); 608 0 stevel return (-1); 609 0 stevel } 610 0 stevel efi_free(vtoc64); 611 0 stevel if (get_disk_info(fd, label) != 0) { 612 0 stevel return (-1); 613 0 stevel } 614 0 stevel return (0); 615 0 stevel } 616 0 stevel 617 0 stevel 618 0 stevel /* 619 0 stevel * We've read a 64-bit label which has no geometry information. Use 620 0 stevel * some heuristics to fake up a geometry that would match the disk in 621 0 stevel * order to make the rest of format(1M) happy. 622 0 stevel */ 623 0 stevel static int 624 0 stevel vtoc64_to_label(struct efi_info *label, struct dk_gpt *vtoc) 625 0 stevel { 626 0 stevel int i, nparts = 0; 627 0 stevel struct dk_gpt *lmap; 628 0 stevel 629 0 stevel (void) memset((char *)label, 0, sizeof (struct efi_info)); 630 0 stevel 631 0 stevel /* XXX do a sanity check here for nparts */ 632 0 stevel nparts = vtoc->efi_nparts; 633 0 stevel lmap = (struct dk_gpt *) calloc(1, (sizeof (struct dk_part) * 634 5084 johnlev nparts) + sizeof (struct dk_gpt)); 635 0 stevel if (lmap == NULL) { 636 0 stevel err_print("vtoc64_to_label: unable to allocate lmap\n"); 637 0 stevel fullabort(); 638 0 stevel } 639 0 stevel label->e_parts = lmap; 640 0 stevel 641 0 stevel /* 642 0 stevel * Copy necessary portions 643 0 stevel * XXX Maybe we can use memcpy() ?? 644 0 stevel */ 645 0 stevel lmap->efi_version = vtoc->efi_version; 646 0 stevel lmap->efi_nparts = vtoc->efi_nparts; 647 0 stevel lmap->efi_part_size = vtoc->efi_part_size; 648 0 stevel lmap->efi_lbasize = vtoc->efi_lbasize; 649 0 stevel lmap->efi_last_lba = vtoc->efi_last_lba; 650 0 stevel lmap->efi_first_u_lba = vtoc->efi_first_u_lba; 651 0 stevel lmap->efi_last_u_lba = vtoc->efi_last_u_lba; 652 6590 yl194034 lmap->efi_altern_lba = vtoc->efi_altern_lba; 653 0 stevel lmap->efi_flags = vtoc->efi_flags; 654 0 stevel (void) memcpy((uchar_t *)&lmap->efi_disk_uguid, 655 5084 johnlev (uchar_t *)&vtoc->efi_disk_uguid, sizeof (struct uuid)); 656 0 stevel 657 0 stevel for (i = 0; i < nparts; i++) { 658 0 stevel lmap->efi_parts[i].p_tag = vtoc->efi_parts[i].p_tag; 659 0 stevel lmap->efi_parts[i].p_flag = vtoc->efi_parts[i].p_flag; 660 0 stevel lmap->efi_parts[i].p_start = vtoc->efi_parts[i].p_start; 661 0 stevel lmap->efi_parts[i].p_size = vtoc->efi_parts[i].p_size; 662 0 stevel (void) memcpy((uchar_t *)&lmap->efi_parts[i].p_uguid, 663 0 stevel (uchar_t *)&vtoc->efi_parts[i].p_uguid, 664 0 stevel sizeof (struct uuid)); 665 0 stevel if (vtoc->efi_parts[i].p_tag == V_RESERVED) { 666 0 stevel bcopy(vtoc->efi_parts[i].p_name, 667 0 stevel lmap->efi_parts[i].p_name, LEN_DKL_VVOL); 668 0 stevel } 669 0 stevel } 670 0 stevel return (0); 671 0 stevel } 672 0 stevel 673 0 stevel /* 674 0 stevel * Convert vtoc/geom to label. 675 0 stevel */ 676 0 stevel static int 677 7563 Prasad vtoc_to_label(struct dk_label *label, struct extvtoc *vtoc, 678 7563 Prasad struct dk_geom *geom, struct dk_cinfo *cinfo) 679 0 stevel { 680 0 stevel #if defined(_SUNOS_VTOC_8) 681 0 stevel struct dk_map32 *lmap; 682 0 stevel #elif defined(_SUNOS_VTOC_16) 683 0 stevel struct dkl_partition *lmap; 684 0 stevel #else 685 0 stevel #error No VTOC format defined. 686 0 stevel #endif /* defined(_SUNOS_VTOC_8) */ 687 0 stevel 688 7563 Prasad struct extpartition *vpart; 689 7563 Prasad ulong_t nblks; 690 0 stevel int i; 691 0 stevel 692 0 stevel (void) memset((char *)label, 0, sizeof (struct dk_label)); 693 0 stevel 694 0 stevel /* 695 0 stevel * Sanity-check the vtoc 696 0 stevel */ 697 9889 Larry if (vtoc->v_sanity != VTOC_SANE || 698 5084 johnlev vtoc->v_nparts != V_NUMPAR) { 699 0 stevel return (-1); 700 0 stevel } 701 0 stevel 702 0 stevel /* 703 0 stevel * Sanity check of geometry 704 0 stevel */ 705 0 stevel if (geom->dkg_ncyl == 0 || geom->dkg_nhead == 0 || 706 5084 johnlev geom->dkg_nsect == 0) { 707 0 stevel return (-1); 708 0 stevel } 709 0 stevel 710 0 stevel label->dkl_magic = DKL_MAGIC; 711 0 stevel 712 0 stevel /* 713 0 stevel * Copy necessary portions of the geometry information 714 0 stevel */ 715 0 stevel label->dkl_rpm = geom->dkg_rpm; 716 0 stevel label->dkl_pcyl = geom->dkg_pcyl; 717 0 stevel label->dkl_apc = geom->dkg_apc; 718 0 stevel label->dkl_intrlv = geom->dkg_intrlv; 719 0 stevel label->dkl_ncyl = geom->dkg_ncyl; 720 0 stevel label->dkl_acyl = geom->dkg_acyl; 721 0 stevel 722 0 stevel #if defined(_SUNOS_VTOC_16) 723 0 stevel label->dkl_bcyl = geom->dkg_bcyl; 724 0 stevel #endif /* defined(_SUNOS_VTOC_16) */ 725 0 stevel 726 0 stevel label->dkl_nhead = geom->dkg_nhead; 727 0 stevel label->dkl_nsect = geom->dkg_nsect; 728 0 stevel 729 0 stevel #if defined(_SUNOS_VTOC_8) 730 0 stevel label->dkl_obs1 = geom->dkg_obs1; 731 0 stevel label->dkl_obs2 = geom->dkg_obs2; 732 0 stevel label->dkl_obs3 = geom->dkg_obs3; 733 0 stevel #endif /* defined(_SUNOS_VTOC_8) */ 734 0 stevel 735 0 stevel label->dkl_write_reinstruct = geom->dkg_write_reinstruct; 736 0 stevel label->dkl_read_reinstruct = geom->dkg_read_reinstruct; 737 0 stevel 738 0 stevel /* 739 0 stevel * Copy vtoc structure fields into the disk label dk_vtoc 740 0 stevel */ 741 0 stevel label->dkl_vtoc.v_sanity = vtoc->v_sanity; 742 0 stevel label->dkl_vtoc.v_nparts = vtoc->v_nparts; 743 0 stevel label->dkl_vtoc.v_version = vtoc->v_version; 744 0 stevel 745 0 stevel (void) memcpy(label->dkl_vtoc.v_volume, vtoc->v_volume, 746 5084 johnlev LEN_DKL_VVOL); 747 0 stevel for (i = 0; i < V_NUMPAR; i++) { 748 0 stevel label->dkl_vtoc.v_part[i].p_tag = vtoc->v_part[i].p_tag; 749 0 stevel label->dkl_vtoc.v_part[i].p_flag = vtoc->v_part[i].p_flag; 750 7563 Prasad label->dkl_vtoc.v_timestamp[i] = vtoc->timestamp[i]; 751 0 stevel } 752 7563 Prasad 753 7563 Prasad for (i = 0; i < 10; i++) 754 7563 Prasad label->dkl_vtoc.v_reserved[i] = vtoc->v_reserved[i]; 755 7563 Prasad 756 7563 Prasad label->dkl_vtoc.v_bootinfo[0] = vtoc->v_bootinfo[0]; 757 7563 Prasad label->dkl_vtoc.v_bootinfo[1] = vtoc->v_bootinfo[1]; 758 7563 Prasad label->dkl_vtoc.v_bootinfo[2] = vtoc->v_bootinfo[2]; 759 0 stevel 760 0 stevel (void) memcpy(label->dkl_asciilabel, vtoc->v_asciilabel, 761 5084 johnlev LEN_DKL_ASCII); 762 0 stevel 763 0 stevel /* 764 0 stevel * Note the conversion from starting sector number 765 0 stevel * to starting cylinder number. 766 0 stevel * Return error if division results in a remainder. 767 5084 johnlev * 768 5084 johnlev * Note: don't check, if probing virtual disk in Xen 769 5084 johnlev * for that virtual disk will use fabricated # of headers 770 5084 johnlev * and sectors per track which may cause the capacity 771 5084 johnlev * not multiple of # of blocks per cylinder 772 0 stevel */ 773 0 stevel #if defined(_SUNOS_VTOC_8) 774 0 stevel lmap = label->dkl_map; 775 0 stevel 776 0 stevel #elif defined(_SUNOS_VTOC_16) 777 0 stevel lmap = label->dkl_vtoc.v_part; 778 0 stevel #else 779 0 stevel #error No VTOC format defined. 780 0 stevel #endif /* defined(_SUNOS_VTOC_8) */ 781 0 stevel 782 0 stevel vpart = vtoc->v_part; 783 0 stevel 784 7563 Prasad nblks = label->dkl_nsect * label->dkl_nhead; 785 0 stevel 786 0 stevel for (i = 0; i < NDKMAP; i++, lmap++, vpart++) { 787 5084 johnlev if (cinfo->dki_ctype != DKC_VBD) { 788 5084 johnlev if ((vpart->p_start % nblks) != 0 || 789 5084 johnlev (vpart->p_size % nblks) != 0) { 790 5084 johnlev return (-1); 791 5084 johnlev } 792 0 stevel } 793 0 stevel #if defined(_SUNOS_VTOC_8) 794 7563 Prasad lmap->dkl_cylno = (blkaddr32_t)(vpart->p_start / nblks); 795 7563 Prasad lmap->dkl_nblk = (blkaddr32_t)vpart->p_size; 796 0 stevel 797 0 stevel #elif defined(_SUNOS_VTOC_16) 798 7563 Prasad lmap->p_start = (blkaddr32_t)vpart->p_start; 799 7563 Prasad lmap->p_size = (blkaddr32_t)vpart->p_size; 800 0 stevel #else 801 0 stevel #error No VTOC format defined. 802 0 stevel #endif /* defined(_SUNOS_VTOC_8) */ 803 0 stevel } 804 0 stevel 805 0 stevel /* 806 0 stevel * Finally, make a checksum 807 0 stevel */ 808 0 stevel (void) checksum(label, CK_MAKESUM); 809 0 stevel 810 7563 Prasad #ifdef DEBUG 811 7563 Prasad if (option_msg && diag_msg) 812 7563 Prasad dump_label(label); 813 7563 Prasad #endif 814 0 stevel return (0); 815 0 stevel } 816 0 stevel 817 0 stevel 818 0 stevel 819 0 stevel /* 820 0 stevel * Extract a vtoc structure out of a valid label 821 0 stevel */ 822 0 stevel int 823 7563 Prasad label_to_vtoc(struct extvtoc *vtoc, struct dk_label *label) 824 0 stevel { 825 0 stevel #if defined(_SUNOS_VTOC_8) 826 0 stevel struct dk_map2 *lpart; 827 0 stevel struct dk_map32 *lmap; 828 7563 Prasad ulong_t nblks; 829 0 stevel 830 0 stevel #elif defined(_SUNOS_VTOC_16) 831 0 stevel struct dkl_partition *lpart; 832 0 stevel #else 833 0 stevel #error No VTOC format defined. 834 0 stevel #endif /* defined(_SUNOS_VTOC_8) */ 835 0 stevel 836 7563 Prasad struct extpartition *vpart; 837 0 stevel int i; 838 0 stevel 839 7563 Prasad (void) memset((char *)vtoc, 0, sizeof (struct extvtoc)); 840 0 stevel 841 0 stevel switch (label->dkl_vtoc.v_version) { 842 0 stevel case 0: 843 0 stevel /* 844 0 stevel * No valid vtoc information in the label. 845 0 stevel * Construct default p_flags and p_tags. 846 0 stevel */ 847 0 stevel vpart = vtoc->v_part; 848 0 stevel for (i = 0; i < V_NUMPAR; i++, vpart++) { 849 0 stevel vpart->p_tag = default_vtoc_map[i].p_tag; 850 0 stevel vpart->p_flag = default_vtoc_map[i].p_flag; 851 0 stevel } 852 0 stevel break; 853 0 stevel 854 0 stevel case V_VERSION: 855 0 stevel vpart = vtoc->v_part; 856 0 stevel lpart = label->dkl_vtoc.v_part; 857 0 stevel for (i = 0; i < V_NUMPAR; i++, vpart++, lpart++) { 858 0 stevel vpart->p_tag = lpart->p_tag; 859 0 stevel vpart->p_flag = lpart->p_flag; 860 0 stevel 861 0 stevel #if defined(_SUNOS_VTOC_16) 862 7563 Prasad vpart->p_start = (diskaddr_t)lpart->p_start; 863 7563 Prasad vpart->p_size = (diskaddr_t)lpart->p_size; 864 0 stevel #endif /* defined(_SUNOS_VTOC_16) */ 865 7563 Prasad vtoc->timestamp[i] = label->dkl_vtoc.v_timestamp[i]; 866 0 stevel } 867 0 stevel (void) memcpy(vtoc->v_volume, label->dkl_vtoc.v_volume, 868 5084 johnlev LEN_DKL_VVOL); 869 7563 Prasad 870 7563 Prasad for (i = 0; i < 10; i++) 871 7563 Prasad vtoc->v_reserved[i] = label->dkl_vtoc.v_reserved[i]; 872 7563 Prasad 873 7563 Prasad vtoc->v_bootinfo[0] = label->dkl_vtoc.v_bootinfo[0]; 874 7563 Prasad vtoc->v_bootinfo[1] = label->dkl_vtoc.v_bootinfo[1]; 875 7563 Prasad vtoc->v_bootinfo[2] = label->dkl_vtoc.v_bootinfo[2]; 876 0 stevel break; 877 0 stevel 878 0 stevel default: 879 0 stevel return (-1); 880 0 stevel } 881 0 stevel 882 0 stevel /* 883 0 stevel * XXX - this looks wrong to me.... 884 0 stevel * why are these values hardwired, rather than returned from 885 0 stevel * the real disk label? 886 0 stevel */ 887 0 stevel vtoc->v_sanity = VTOC_SANE; 888 0 stevel vtoc->v_version = V_VERSION; 889 9889 Larry vtoc->v_sectorsz = cur_blksz; 890 0 stevel vtoc->v_nparts = V_NUMPAR; 891 0 stevel 892 0 stevel (void) memcpy(vtoc->v_asciilabel, label->dkl_asciilabel, 893 5084 johnlev LEN_DKL_ASCII); 894 0 stevel 895 0 stevel #if defined(_SUNOS_VTOC_8) 896 0 stevel /* 897 0 stevel * Convert partitioning information. 898 0 stevel * Note the conversion from starting cylinder number 899 0 stevel * to starting sector number. 900 0 stevel */ 901 0 stevel lmap = label->dkl_map; 902 0 stevel vpart = vtoc->v_part; 903 0 stevel nblks = label->dkl_nsect * label->dkl_nhead; 904 0 stevel for (i = 0; i < V_NUMPAR; i++, vpart++, lmap++) { 905 7563 Prasad vpart->p_start = (diskaddr_t)(lmap->dkl_cylno * nblks); 906 7563 Prasad vpart->p_size = (diskaddr_t)lmap->dkl_nblk; 907 0 stevel } 908 0 stevel #endif /* defined(_SUNOS_VTOC_8) */ 909 0 stevel 910 0 stevel return (0); 911 0 stevel } 912 0 stevel 913 0 stevel /* 914 0 stevel * Input: File descriptor 915 7563 Prasad * Output: 1 if disk has an EFI label, 0 otherwise. 916 0 stevel */ 917 0 stevel 918 0 stevel int 919 0 stevel is_efi_type(int fd) 920 0 stevel { 921 7563 Prasad struct extvtoc vtoc; 922 0 stevel 923 7563 Prasad if (read_extvtoc(fd, &vtoc) == VT_ENOTSUP) { 924 7563 Prasad /* assume the disk has EFI label */ 925 7563 Prasad return (1); 926 0 stevel } 927 0 stevel return (0); 928 0 stevel } 929 0 stevel 930 0 stevel /* make sure the user specified something reasonable */ 931 0 stevel void 932 0 stevel err_check(struct dk_gpt *vtoc) 933 0 stevel { 934 0 stevel int resv_part = -1; 935 0 stevel int i, j; 936 0 stevel diskaddr_t istart, jstart, isize, jsize, endsect; 937 0 stevel int overlap = 0; 938 0 stevel 939 0 stevel /* 940 0 stevel * make sure no partitions overlap 941 0 stevel */ 942 0 stevel for (i = 0; i < vtoc->efi_nparts; i++) { 943 0 stevel /* It can't be unassigned and have an actual size */ 944 0 stevel if ((vtoc->efi_parts[i].p_tag == V_UNASSIGNED) && 945 0 stevel (vtoc->efi_parts[i].p_size != 0)) { 946 0 stevel (void) fprintf(stderr, 947 0 stevel "partition %d is \"unassigned\" but has a size of %llu\n", i, 948 5084 johnlev vtoc->efi_parts[i].p_size); 949 0 stevel } 950 0 stevel if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) { 951 0 stevel continue; 952 0 stevel } 953 0 stevel if (vtoc->efi_parts[i].p_tag == V_RESERVED) { 954 0 stevel if (resv_part != -1) { 955 5084 johnlev (void) fprintf(stderr, 956 5084 johnlev "found duplicate reserved partition at %d\n", i); 957 0 stevel } 958 0 stevel resv_part = i; 959 0 stevel if (vtoc->efi_parts[i].p_size != EFI_MIN_RESV_SIZE) 960 0 stevel (void) fprintf(stderr, 961 0 stevel "Warning: reserved partition size must be %d sectors\n", 962 5084 johnlev EFI_MIN_RESV_SIZE); 963 0 stevel } 964 0 stevel if ((vtoc->efi_parts[i].p_start < vtoc->efi_first_u_lba) || 965 0 stevel (vtoc->efi_parts[i].p_start > vtoc->efi_last_u_lba)) { 966 0 stevel (void) fprintf(stderr, 967 0 stevel "Partition %d starts at %llu\n", 968 0 stevel i, 969 0 stevel vtoc->efi_parts[i].p_start); 970 0 stevel (void) fprintf(stderr, 971 0 stevel "It must be between %llu and %llu.\n", 972 0 stevel vtoc->efi_first_u_lba, 973 0 stevel vtoc->efi_last_u_lba); 974 0 stevel } 975 0 stevel if ((vtoc->efi_parts[i].p_start + 976 0 stevel vtoc->efi_parts[i].p_size < 977 0 stevel vtoc->efi_first_u_lba) || 978 0 stevel (vtoc->efi_parts[i].p_start + 979 0 stevel vtoc->efi_parts[i].p_size > 980 0 stevel vtoc->efi_last_u_lba + 1)) { 981 0 stevel (void) fprintf(stderr, 982 0 stevel "Partition %d ends at %llu\n", 983 0 stevel i, 984 0 stevel vtoc->efi_parts[i].p_start + 985 0 stevel vtoc->efi_parts[i].p_size); 986 0 stevel (void) fprintf(stderr, 987 0 stevel "It must be between %llu and %llu.\n", 988 0 stevel vtoc->efi_first_u_lba, 989 0 stevel vtoc->efi_last_u_lba); 990 0 stevel } 991 0 stevel 992 0 stevel for (j = 0; j < vtoc->efi_nparts; j++) { 993 0 stevel isize = vtoc->efi_parts[i].p_size; 994 0 stevel jsize = vtoc->efi_parts[j].p_size; 995 0 stevel istart = vtoc->efi_parts[i].p_start; 996 0 stevel jstart = vtoc->efi_parts[j].p_start; 997 0 stevel if ((i != j) && (isize != 0) && (jsize != 0)) { 998 0 stevel endsect = jstart + jsize -1; 999 0 stevel if ((jstart <= istart) && 1000 0 stevel (istart <= endsect)) { 1001 0 stevel if (!overlap) { 1002 0 stevel (void) fprintf(stderr, 1003 0 stevel "label error: EFI Labels do not support overlapping partitions\n"); 1004 0 stevel } 1005 0 stevel (void) fprintf(stderr, 1006 0 stevel "Partition %d overlaps partition %d.\n", i, j); 1007 0 stevel overlap = 1; 1008 0 stevel } 1009 0 stevel } 1010 0 stevel } 1011 0 stevel } 1012 0 stevel /* make sure there is a reserved partition */ 1013 0 stevel if (resv_part == -1) { 1014 0 stevel (void) fprintf(stderr, 1015 5084 johnlev "no reserved partition found\n"); 1016 0 stevel } 1017 0 stevel } 1018 0 stevel 1019 7563 Prasad #ifdef DEBUG 1020 7563 Prasad static void 1021 0 stevel dump_label(label) 1022 0 stevel struct dk_label *label; 1023 0 stevel { 1024 0 stevel int i; 1025 0 stevel 1026 0 stevel fmt_print("%s\n", label->dkl_asciilabel); 1027 0 stevel 1028 0 stevel fmt_print("version: %d\n", label->dkl_vtoc.v_version); 1029 0 stevel fmt_print("volume: "); 1030 0 stevel for (i = 0; i < LEN_DKL_VVOL; i++) { 1031 0 stevel if (label->dkl_vtoc.v_volume[i] == 0) 1032 0 stevel break; 1033 0 stevel fmt_print("%c", label->dkl_vtoc.v_volume[i]); 1034 0 stevel } 1035 0 stevel fmt_print("\n"); 1036 0 stevel fmt_print("v_nparts: %d\n", label->dkl_vtoc.v_nparts); 1037 0 stevel fmt_print("v_sanity: %lx\n", label->dkl_vtoc.v_sanity); 1038 0 stevel 1039 0 stevel #if defined(_SUNOS_VTOC_8) 1040 0 stevel fmt_print("rpm: %d\n", label->dkl_rpm); 1041 0 stevel fmt_print("pcyl: %d\n", label->dkl_pcyl); 1042 0 stevel fmt_print("apc: %d\n", label->dkl_apc); 1043 0 stevel fmt_print("obs1: %d\n", label->dkl_obs1); 1044 0 stevel fmt_print("obs2: %d\n", label->dkl_obs2); 1045 0 stevel fmt_print("intrlv: %d\n", label->dkl_intrlv); 1046 0 stevel fmt_print("ncyl: %d\n", label->dkl_ncyl); 1047 0 stevel fmt_print("acyl: %d\n", label->dkl_acyl); 1048 0 stevel fmt_print("nhead: %d\n", label->dkl_nhead); 1049 0 stevel fmt_print("nsect: %d\n", label->dkl_nsect); 1050 0 stevel fmt_print("obs3: %d\n", label->dkl_obs3); 1051 0 stevel fmt_print("obs4: %d\n", label->dkl_obs4); 1052 0 stevel 1053 0 stevel #elif defined(_SUNOS_VTOC_16) 1054 0 stevel fmt_print("rpm: %d\n", label->dkl_rpm); 1055 0 stevel fmt_print("pcyl: %d\n", label->dkl_pcyl); 1056 0 stevel fmt_print("apc: %d\n", label->dkl_apc); 1057 0 stevel fmt_print("intrlv: %d\n", label->dkl_intrlv); 1058 0 stevel fmt_print("ncyl: %d\n", label->dkl_ncyl); 1059 0 stevel fmt_print("acyl: %d\n", label->dkl_acyl); 1060 0 stevel fmt_print("nhead: %d\n", label->dkl_nhead); 1061 0 stevel fmt_print("nsect: %d\n", label->dkl_nsect); 1062 0 stevel fmt_print("bcyl: %d\n", label->dkl_bcyl); 1063 0 stevel fmt_print("skew: %d\n", label->dkl_skew); 1064 0 stevel #else 1065 0 stevel #error No VTOC format defined. 1066 0 stevel #endif /* defined(_SUNOS_VTOC_8) */ 1067 0 stevel fmt_print("magic: %0x\n", label->dkl_magic); 1068 0 stevel fmt_print("cksum: %0x\n", label->dkl_cksum); 1069 0 stevel 1070 0 stevel for (i = 0; i < NDKMAP; i++) { 1071 0 stevel 1072 0 stevel #if defined(_SUNOS_VTOC_8) 1073 0 stevel fmt_print("%c: cyl=%d, blocks=%d", i+'a', 1074 0 stevel label->dkl_map[i].dkl_cylno, 1075 0 stevel label->dkl_map[i].dkl_nblk); 1076 0 stevel 1077 0 stevel #elif defined(_SUNOS_VTOC_16) 1078 7563 Prasad fmt_print("%c: start=%u, blocks=%u", i+'a', 1079 0 stevel label->dkl_vtoc.v_part[i].p_start, 1080 0 stevel label->dkl_vtoc.v_part[i].p_size); 1081 0 stevel #else 1082 0 stevel #error No VTOC format defined. 1083 0 stevel #endif /* defined(_SUNOS_VTOC_8) */ 1084 0 stevel 1085 0 stevel fmt_print(", tag=%d, flag=%d", 1086 0 stevel label->dkl_vtoc.v_part[i].p_tag, 1087 0 stevel label->dkl_vtoc.v_part[i].p_flag); 1088 0 stevel fmt_print("\n"); 1089 0 stevel } 1090 0 stevel 1091 0 stevel fmt_print("read_reinstruct: %d\n", label->dkl_read_reinstruct); 1092 0 stevel fmt_print("write_reinstruct: %d\n", label->dkl_write_reinstruct); 1093 0 stevel 1094 0 stevel fmt_print("bootinfo: "); 1095 0 stevel for (i = 0; i < 3; i++) { 1096 0 stevel fmt_print("0x%x ", label->dkl_vtoc.v_bootinfo[i]); 1097 0 stevel } 1098 0 stevel fmt_print("\n"); 1099 0 stevel 1100 0 stevel fmt_print("reserved: "); 1101 0 stevel for (i = 0; i < 10; i++) { 1102 0 stevel if ((i % 4) == 3) 1103 0 stevel fmt_print("\n"); 1104 0 stevel fmt_print("0x%x ", label->dkl_vtoc.v_reserved[i]); 1105 0 stevel } 1106 0 stevel fmt_print("\n"); 1107 0 stevel 1108 0 stevel fmt_print("timestamp:\n"); 1109 0 stevel for (i = 0; i < NDKMAP; i++) { 1110 0 stevel if ((i % 4) == 3) 1111 0 stevel fmt_print("\n"); 1112 0 stevel fmt_print("0x%x ", label->dkl_vtoc.v_timestamp[i]); 1113 0 stevel } 1114 0 stevel fmt_print("\n"); 1115 0 stevel 1116 0 stevel fmt_print("pad:\n"); 1117 0 stevel dump("", label->dkl_pad, LEN_DKL_PAD, HEX_ONLY); 1118 0 stevel 1119 0 stevel fmt_print("\n\n"); 1120 0 stevel } 1121 7563 Prasad #endif /* DEBUG */ 1122