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.
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.
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]
23 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
28 * This file contains the code relating to label manipulation.
34 #include <sys/isa_defs.h>
35 #include <sys/efi_partition.h>
40 #include <libdevinfo.h>
45 #include "partition.h"
46 #include "ctlr_scsi.h"
49 #if defined(_FIRMWARE_NEEDS_FDISK)
50 #include <sys/dktp/fdisk.h>
51 #include "menu_fdisk.h"
52 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */
60 * Prototypes for ANSI C compilers
62 static int do_geometry_sanity_check(void);
63 static int vtoc_to_label(struct dk_label
*label
, struct extvtoc
*vtoc
,
64 struct dk_geom
*geom
, struct dk_cinfo
*cinfo
);
65 extern int read_extvtoc(int, struct extvtoc
*);
66 extern int write_extvtoc(int, struct extvtoc
*);
67 static int vtoc64_to_label(struct efi_info
*, struct dk_gpt
*);
72 * Prototypes for non-ANSI C compilers
74 static int do_geometry_sanity_check();
75 static int vtoc_to_label();
76 extern int read_extvtoc();
77 extern int write_extvtoc();
78 static int vtoc64_to_label();
83 static void dump_label(struct dk_label
*label
);
87 * This routine checks the given label to see if it is valid.
91 register struct dk_label
*label
;
95 * Check the magic number.
97 if (label
->dkl_magic
!= DKL_MAGIC
)
100 * Check the checksum.
102 if (checksum(label
, CK_CHECKSUM
) != 0)
108 * This routine checks or calculates the label checksum, depending on
109 * the mode it is called in.
112 checksum(label
, mode
)
113 struct dk_label
*label
;
116 register short *sp
, sum
= 0;
117 register short count
= (sizeof (struct dk_label
)) / (sizeof (short));
120 * If we are generating a checksum, don't include the checksum
121 * in the rolling xor.
123 if (mode
== CK_MAKESUM
)
127 * Take the xor of all the half-words in the label.
133 * If we are checking the checksum, the total will be zero for
134 * a correct checksum, so we can just return the sum.
136 if (mode
== CK_CHECKSUM
)
139 * If we are generating the checksum, fill it in.
142 label
->dkl_cksum
= sum
;
148 * This routine is used to extract the id string from the string stored
149 * in a disk label. The problem is that the string in the label has
150 * the physical characteristics of the drive appended to it. The approach
151 * is to find the beginning of the physical attributes portion of the string
152 * and truncate it there.
161 * Start at the end of the string. When we match the word ' cyl',
162 * we are at the beginning of the attributes.
164 for (c
= id
+ strlen(id
); c
>= id
; c
--) {
165 if (strncmp(c
, " cyl", strlen(" cyl")) == 0) {
167 * Remove any white space.
169 for (; (((*(c
- 1) == ' ') || (*(c
- 1) == '\t')) &&
175 * If we ran off the beginning of the string, something is wrong.
180 * Truncate the string.
187 * This routine is used by write_label() to do a quick sanity check on the
188 * supplied geometry. This is not a thorough check.
190 * The SCSI READ_CAPACITY command is used here to get the capacity of the
191 * disk. But, the available area to store data on a disk is usually less
192 * than this. So, if the specified geometry evaluates to a value which falls
193 * in this margin, then such illegal geometries can slip through the cracks.
196 do_geometry_sanity_check()
198 struct scsi_capacity_16 capacity
;
200 if (uscsi_read_capacity(cur_file
, &capacity
)) {
201 err_print("Warning: Unable to get capacity."
202 " Cannot check geometry\n");
203 return (0); /* Just ignore this problem */
206 if (capacity
.sc_capacity
< ncyl
* nhead
* nsect
) {
207 err_print("\nWarning: Current geometry overshoots "
208 "actual geometry of disk\n\n");
209 if (check("Continue labelling disk") != 0)
211 return (0); /* Just ignore this problem */
218 * create a clear EFI partition table when format is used
219 * to convert an SMI label to an EFI label
222 SMI_vtoc_to_EFI(int fd
, struct dk_gpt
**new_vtoc
)
227 if (efi_alloc_and_init(fd
, EFI_NUMPAR
, new_vtoc
) != 0) {
228 err_print("SMI vtoc to EFI failed\n");
234 * create a clear EFI partition table:
235 * s0 takes the whole disk except the primary EFI lable,
236 * backup EFI labels, and the reserved partition.
237 * s1-s6 are unassigned slices.
239 efi
->efi_parts
[0].p_tag
= V_USR
;
240 efi
->efi_parts
[0].p_start
= efi
->efi_first_u_lba
;
241 efi
->efi_parts
[0].p_size
= efi
->efi_last_u_lba
- efi
->efi_first_u_lba
242 - EFI_MIN_RESV_SIZE
+ 1;
245 * s1-s6 are unassigned slices
247 for (i
= 1; i
< efi
->efi_nparts
- 2; i
++) {
248 efi
->efi_parts
[i
].p_tag
= V_UNASSIGNED
;
249 efi
->efi_parts
[i
].p_start
= 0;
250 efi
->efi_parts
[i
].p_size
= 0;
256 efi
->efi_parts
[efi
->efi_nparts
- 1].p_tag
= V_RESERVED
;
257 efi
->efi_parts
[efi
->efi_nparts
- 1].p_start
=
258 efi
->efi_last_u_lba
- EFI_MIN_RESV_SIZE
+ 1;
259 efi
->efi_parts
[efi
->efi_nparts
- 1].p_size
= EFI_MIN_RESV_SIZE
;
265 * This routine constructs and writes a label on the disk. It writes both
266 * the primary and backup labels. It assumes that there is a current
267 * partition map already defined. It also notifies the SunOS kernel of
268 * the label and partition information it has written on the disk.
273 int error
= 0, head
, sec
;
274 struct dk_label label
;
277 struct dk_gpt
*vtoc64
;
281 #if defined(_SUNOS_VTOC_8)
283 #endif /* defined(_SUNOS_VTOC_8) */
286 * Check to see if any partitions used for svm, vxvm or live upgrade
287 * are on the disk. If so, refuse to label the disk, but only
288 * if we are trying to shrink a partition in use.
290 if (checkdevinuse(cur_disk
->disk_name
, (diskaddr_t
)-1,
291 (diskaddr_t
)-1, 0, 1)) {
292 err_print("Cannot label disk when "
293 "partitions are in use as described.\n");
298 * If EFI label, then write it out to disk
300 if (cur_label
== L_TYPE_EFI
) {
302 vtoc64
= cur_parts
->etoc
;
304 if (efi_write(cur_file
, vtoc64
) != 0) {
305 err_print("Warning: error writing EFI.\n");
309 cur_disk
->disk_flags
|= DSK_LABEL
;
315 * Fill in a label structure with the geometry information.
317 (void) memset((char *)&label
, 0, sizeof (struct dk_label
));
318 new_label
= zalloc(cur_blksz
);
320 label
.dkl_pcyl
= pcyl
;
321 label
.dkl_ncyl
= ncyl
;
322 label
.dkl_acyl
= acyl
;
324 #if defined(_SUNOS_VTOC_16)
325 label
.dkl_bcyl
= bcyl
;
326 #endif /* defined(_SUNOC_VTOC_16) */
328 label
.dkl_nhead
= nhead
;
329 label
.dkl_nsect
= nsect
;
331 label
.dkl_intrlv
= 1;
332 label
.dkl_rpm
= cur_dtype
->dtype_rpm
;
334 #if defined(_SUNOS_VTOC_8)
336 * Also fill in the current partition information.
338 for (i
= 0; i
< NDKMAP
; i
++) {
339 label
.dkl_map
[i
] = cur_parts
->pinfo_map
[i
];
341 #endif /* defined(_SUNOS_VTOC_8) */
343 label
.dkl_magic
= DKL_MAGIC
;
346 * Fill in the vtoc information
348 label
.dkl_vtoc
= cur_parts
->vtoc
;
351 * Use the current label
353 bcopy(cur_disk
->v_volume
, label
.dkl_vtoc
.v_volume
, LEN_DKL_VVOL
);
356 * Put asciilabel in; on x86 it's in the vtoc, not the label.
358 (void) snprintf(label
.dkl_asciilabel
, sizeof (label
.dkl_asciilabel
),
359 "%s cyl %d alt %d hd %d sec %d",
360 cur_dtype
->dtype_asciilabel
, ncyl
, acyl
, nhead
, nsect
);
362 #if defined(_SUNOS_VTOC_16)
364 * Also add in v_sectorsz, as the driver will.
366 label
.dkl_vtoc
.v_sectorsz
= cur_blksz
;
367 #endif /* defined(_SUNOS_VTOC_16) */
370 * Generate the correct checksum.
372 (void) checksum(&label
, CK_MAKESUM
);
374 * Convert the label into a vtoc
376 if (label_to_vtoc(&vtoc
, &label
) == -1) {
381 * Fill in the geometry info. This is critical that
382 * we do this before writing the vtoc.
384 bzero((caddr_t
)&geom
, sizeof (struct dk_geom
));
385 geom
.dkg_ncyl
= ncyl
;
386 geom
.dkg_acyl
= acyl
;
388 #if defined(_SUNOS_VTOC_16)
389 geom
.dkg_bcyl
= bcyl
;
390 #endif /* defined(_SUNOS_VTOC_16) */
392 geom
.dkg_nhead
= nhead
;
393 geom
.dkg_nsect
= nsect
;
396 geom
.dkg_rpm
= cur_dtype
->dtype_rpm
;
397 geom
.dkg_pcyl
= pcyl
;
400 * Make a quick check to see that the geometry is being
401 * written now is not way off from the actual capacity
402 * of the disk. This is only an appoximate check and
403 * is only for SCSI disks.
405 if (SCSI
&& do_geometry_sanity_check() != 0) {
411 * Lock out interrupts so we do things in sync.
415 * Do the ioctl to tell the kernel the geometry.
417 if (ioctl(cur_file
, DKIOCSGEOM
, &geom
) == -1) {
418 err_print("Warning: error setting drive geometry.\n");
422 * Write the vtoc. At the time of this writing, our
423 * drivers convert the vtoc back to a label, and
424 * then write both the primary and backup labels.
425 * This is not a requirement, however, as we
426 * always use an ioctl to read the vtoc from the
427 * driver, so it can do as it likes.
429 if (write_extvtoc(cur_file
, &vtoc
) != 0) {
430 err_print("Warning: error writing VTOC.\n");
435 * Calculate where the backup labels went. They are always on
436 * the last alternate cylinder, but some older drives put them
437 * on head 2 instead of the last head. They are always on the
438 * first 5 odd sectors of the appropriate track.
440 if (cur_ctype
->ctype_flags
& CF_BLABEL
)
445 * Read and verify the backup labels.
448 for (sec
= 1; ((sec
< BAD_LISTCNT
* 2 + 1) && (sec
< nsect
));
450 if ((*cur_ops
->op_rdwr
)(DIR_READ
, cur_file
, (diskaddr_t
)
451 ((chs2bn(ncyl
+ acyl
- 1, head
, sec
))
452 + solaris_offset
), 1, new_label
, F_NORMAL
, NULL
)) {
453 err_print("Warning: error reading"
457 if (bcmp((char *)&label
, new_label
,
458 sizeof (struct dk_label
)) == 0) {
463 if (nbackups
!= BAD_LISTCNT
) {
464 err_print("Warning: %s\n", nbackups
== 0 ?
465 "no backup labels" : "some backup labels incorrect");
468 * Mark the current disk as labelled and notify the kernel of what
471 cur_disk
->disk_flags
|= DSK_LABEL
;
480 * Read the label from the disk.
481 * Do this via the read_extvtoc() library routine, then convert it to a label.
482 * We also need a DKIOCGGEOM ioctl to get the disk's geometry.
485 read_label(int fd
, struct dk_label
*label
)
489 struct dk_cinfo dkinfo
;
491 if (read_extvtoc(fd
, &vtoc
) < 0 ||
492 ioctl(fd
, DKIOCGGEOM
, &geom
) == -1 ||
493 ioctl(fd
, DKIOCINFO
, &dkinfo
) == -1) {
497 return (vtoc_to_label(label
, &vtoc
, &geom
, &dkinfo
));
501 get_disk_inquiry_prop(char *devpath
, char **vid
, char **pid
, char **rid
)
507 node
= di_init(devpath
, DINFOCPYALL
);
509 if (node
== DI_NODE_NIL
)
512 if (di_prop_lookup_strings(DDI_DEV_T_ANY
, node
,
513 "inquiry-vendor-id", &v
) != 1)
516 if (di_prop_lookup_strings(DDI_DEV_T_ANY
, node
,
517 "inquiry-product-id", &p
) != 1)
520 if (di_prop_lookup_strings(DDI_DEV_T_ANY
, node
,
521 "inquiry-revision-id", &r
) != 1)
528 if (*vid
== NULL
|| *pid
== NULL
|| *rid
== NULL
) {
543 get_disk_inquiry_uscsi(int fd
, char **vid
, char **pid
, char **rid
)
545 struct scsi_inquiry inquiry
;
547 if (uscsi_inquiry(fd
, (char *)&inquiry
, sizeof (inquiry
)))
550 *vid
= strndup(inquiry
.inq_vid
, 8);
551 *pid
= strndup(inquiry
.inq_pid
, 16);
552 *rid
= strndup(inquiry
.inq_revision
, 4);
554 if (*vid
== NULL
|| *pid
== NULL
|| *rid
== NULL
) {
565 get_disk_capacity(int fd
, uint64_t *capacity
)
567 struct dk_minfo minf
;
568 struct scsi_capacity_16 cap16
;
570 if (ioctl(fd
, DKIOCGMEDIAINFO
, &minf
) == 0) {
571 *capacity
= minf
.dki_capacity
* minf
.dki_lbsize
/ cur_blksz
;
575 if (uscsi_read_capacity(fd
, &cap16
) == 0) {
576 *capacity
= cap16
.sc_capacity
;
578 /* Since we are counting from zero, add 1 to capacity */
584 err_print("Fetch Capacity failed\n");
589 get_disk_inquiry_devid(int fd
, char **vid
, char **pid
, char **rid
)
594 struct dk_cinfo dkinfo
;
596 if (devid_get(fd
, &devid
)) {
597 if (option_msg
&& diag_msg
)
598 err_print("devid_get failed\n");
604 if (ioctl(fd
, DKIOCINFO
, &dkinfo
) == -1) {
605 if (option_msg
&& diag_msg
)
606 err_print("DKIOCINFO failed\n");
610 if (dkinfo
.dki_ctype
!= DKC_DIRECT
)
614 if (!(p
= strchr(v
, '=')))
620 *rid
= strdup("0001");
623 if (*vid
== NULL
|| *pid
== NULL
|| *rid
== NULL
) {
634 * Issue uscsi_inquiry and read_capacity commands to
635 * retrieve the disk's Vendor, Product, Revision and
636 * Capacity information.
639 get_disk_info(int fd
, struct efi_info
*label
, struct disk_info
*disk_info
)
641 (void) get_disk_capacity(fd
, &label
->capacity
);
643 if (get_disk_inquiry_prop(disk_info
->devfs_name
,
644 &label
->vendor
, &label
->product
, &label
->revision
) != 0) {
645 if (get_disk_inquiry_devid(fd
, &label
->vendor
, &label
->product
,
646 &label
->revision
) != 0) {
647 if (get_disk_inquiry_uscsi(fd
, &label
->vendor
,
648 &label
->product
, &label
->revision
) != 0) {
649 label
->vendor
= strdup("Unknown");
650 label
->product
= strdup("Unknown");
651 label
->revision
= strdup("0001");
652 if (label
->vendor
== NULL
||
653 label
->product
== NULL
||
654 label
->revision
== NULL
) {
656 free(label
->product
);
657 free(label
->revision
);
668 read_efi_label(int fd
, struct efi_info
*label
, struct disk_info
*disk_info
)
670 struct dk_gpt
*vtoc64
;
672 /* This could fail if there is no label already */
673 if (efi_alloc_and_read(fd
, &vtoc64
) < 0) {
676 if (vtoc64_to_label(label
, vtoc64
) != 0) {
677 err_print("vtoc64_to_label failed\n");
681 if (get_disk_info(fd
, label
, disk_info
) != 0) {
689 * We've read a 64-bit label which has no geometry information. Use
690 * some heuristics to fake up a geometry that would match the disk in
691 * order to make the rest of format(8) happy.
694 vtoc64_to_label(struct efi_info
*label
, struct dk_gpt
*vtoc
)
699 (void) memset((char *)label
, 0, sizeof (struct efi_info
));
701 /* XXX do a sanity check here for nparts */
702 nparts
= vtoc
->efi_nparts
;
703 lmap
= (struct dk_gpt
*) calloc(1, (sizeof (struct dk_part
) *
704 nparts
) + sizeof (struct dk_gpt
));
706 err_print("vtoc64_to_label: unable to allocate lmap\n");
709 label
->e_parts
= lmap
;
712 * Copy necessary portions
713 * XXX Maybe we can use memcpy() ??
715 lmap
->efi_version
= vtoc
->efi_version
;
716 lmap
->efi_nparts
= vtoc
->efi_nparts
;
717 lmap
->efi_part_size
= vtoc
->efi_part_size
;
718 lmap
->efi_lbasize
= vtoc
->efi_lbasize
;
719 lmap
->efi_last_lba
= vtoc
->efi_last_lba
;
720 lmap
->efi_first_u_lba
= vtoc
->efi_first_u_lba
;
721 lmap
->efi_last_u_lba
= vtoc
->efi_last_u_lba
;
722 lmap
->efi_altern_lba
= vtoc
->efi_altern_lba
;
723 lmap
->efi_flags
= vtoc
->efi_flags
;
724 (void) memcpy((uchar_t
*)&lmap
->efi_disk_uguid
,
725 (uchar_t
*)&vtoc
->efi_disk_uguid
, sizeof (struct uuid
));
727 for (i
= 0; i
< nparts
; i
++) {
728 lmap
->efi_parts
[i
].p_tag
= vtoc
->efi_parts
[i
].p_tag
;
729 lmap
->efi_parts
[i
].p_flag
= vtoc
->efi_parts
[i
].p_flag
;
730 lmap
->efi_parts
[i
].p_start
= vtoc
->efi_parts
[i
].p_start
;
731 lmap
->efi_parts
[i
].p_size
= vtoc
->efi_parts
[i
].p_size
;
732 (void) memcpy((uchar_t
*)&lmap
->efi_parts
[i
].p_uguid
,
733 (uchar_t
*)&vtoc
->efi_parts
[i
].p_uguid
,
734 sizeof (struct uuid
));
735 if (vtoc
->efi_parts
[i
].p_tag
== V_RESERVED
) {
736 bcopy(vtoc
->efi_parts
[i
].p_name
,
737 lmap
->efi_parts
[i
].p_name
, LEN_DKL_VVOL
);
744 * Convert vtoc/geom to label.
747 vtoc_to_label(struct dk_label
*label
, struct extvtoc
*vtoc
,
748 struct dk_geom
*geom
, struct dk_cinfo
*cinfo
)
750 #if defined(_SUNOS_VTOC_8)
751 struct dk_map32
*lmap
;
752 #elif defined(_SUNOS_VTOC_16)
753 struct dkl_partition
*lmap
;
755 #error No VTOC format defined.
756 #endif /* defined(_SUNOS_VTOC_8) */
758 struct extpartition
*vpart
;
762 (void) memset((char *)label
, 0, sizeof (struct dk_label
));
765 * Sanity-check the vtoc
767 if (vtoc
->v_sanity
!= VTOC_SANE
||
768 vtoc
->v_nparts
!= V_NUMPAR
) {
773 * Sanity check of geometry
775 if (geom
->dkg_ncyl
== 0 || geom
->dkg_nhead
== 0 ||
776 geom
->dkg_nsect
== 0) {
780 label
->dkl_magic
= DKL_MAGIC
;
783 * Copy necessary portions of the geometry information
785 label
->dkl_rpm
= geom
->dkg_rpm
;
786 label
->dkl_pcyl
= geom
->dkg_pcyl
;
787 label
->dkl_apc
= geom
->dkg_apc
;
788 label
->dkl_intrlv
= geom
->dkg_intrlv
;
789 label
->dkl_ncyl
= geom
->dkg_ncyl
;
790 label
->dkl_acyl
= geom
->dkg_acyl
;
792 #if defined(_SUNOS_VTOC_16)
793 label
->dkl_bcyl
= geom
->dkg_bcyl
;
794 #endif /* defined(_SUNOS_VTOC_16) */
796 label
->dkl_nhead
= geom
->dkg_nhead
;
797 label
->dkl_nsect
= geom
->dkg_nsect
;
799 #if defined(_SUNOS_VTOC_8)
800 label
->dkl_obs1
= geom
->dkg_obs1
;
801 label
->dkl_obs2
= geom
->dkg_obs2
;
802 label
->dkl_obs3
= geom
->dkg_obs3
;
803 #endif /* defined(_SUNOS_VTOC_8) */
805 label
->dkl_write_reinstruct
= geom
->dkg_write_reinstruct
;
806 label
->dkl_read_reinstruct
= geom
->dkg_read_reinstruct
;
809 * Copy vtoc structure fields into the disk label dk_vtoc
811 label
->dkl_vtoc
.v_sanity
= vtoc
->v_sanity
;
812 label
->dkl_vtoc
.v_nparts
= vtoc
->v_nparts
;
813 label
->dkl_vtoc
.v_version
= vtoc
->v_version
;
815 (void) memcpy(label
->dkl_vtoc
.v_volume
, vtoc
->v_volume
,
817 for (i
= 0; i
< V_NUMPAR
; i
++) {
818 label
->dkl_vtoc
.v_part
[i
].p_tag
= vtoc
->v_part
[i
].p_tag
;
819 label
->dkl_vtoc
.v_part
[i
].p_flag
= vtoc
->v_part
[i
].p_flag
;
820 label
->dkl_vtoc
.v_timestamp
[i
] = vtoc
->timestamp
[i
];
823 for (i
= 0; i
< 10; i
++)
824 label
->dkl_vtoc
.v_reserved
[i
] = vtoc
->v_reserved
[i
];
826 label
->dkl_vtoc
.v_bootinfo
[0] = vtoc
->v_bootinfo
[0];
827 label
->dkl_vtoc
.v_bootinfo
[1] = vtoc
->v_bootinfo
[1];
828 label
->dkl_vtoc
.v_bootinfo
[2] = vtoc
->v_bootinfo
[2];
830 (void) memcpy(label
->dkl_asciilabel
, vtoc
->v_asciilabel
,
834 * Note the conversion from starting sector number
835 * to starting cylinder number.
836 * Return error if division results in a remainder.
838 * Note: don't check, if probing virtual disk in Xen
839 * for that virtual disk will use fabricated # of headers
840 * and sectors per track which may cause the capacity
841 * not multiple of # of blocks per cylinder
843 #if defined(_SUNOS_VTOC_8)
844 lmap
= label
->dkl_map
;
846 #elif defined(_SUNOS_VTOC_16)
847 lmap
= label
->dkl_vtoc
.v_part
;
849 #error No VTOC format defined.
850 #endif /* defined(_SUNOS_VTOC_8) */
852 vpart
= vtoc
->v_part
;
854 nblks
= label
->dkl_nsect
* label
->dkl_nhead
;
856 for (i
= 0; i
< NDKMAP
; i
++, lmap
++, vpart
++) {
857 if (cinfo
->dki_ctype
!= DKC_VBD
) {
858 if ((vpart
->p_start
% nblks
) != 0 ||
859 (vpart
->p_size
% nblks
) != 0) {
863 #if defined(_SUNOS_VTOC_8)
864 lmap
->dkl_cylno
= (blkaddr32_t
)(vpart
->p_start
/ nblks
);
865 lmap
->dkl_nblk
= (blkaddr32_t
)vpart
->p_size
;
867 #elif defined(_SUNOS_VTOC_16)
868 lmap
->p_start
= (blkaddr32_t
)vpart
->p_start
;
869 lmap
->p_size
= (blkaddr32_t
)vpart
->p_size
;
871 #error No VTOC format defined.
872 #endif /* defined(_SUNOS_VTOC_8) */
876 * Finally, make a checksum
878 (void) checksum(label
, CK_MAKESUM
);
881 if (option_msg
&& diag_msg
)
890 * Extract a vtoc structure out of a valid label
893 label_to_vtoc(struct extvtoc
*vtoc
, struct dk_label
*label
)
895 #if defined(_SUNOS_VTOC_8)
896 struct dk_map2
*lpart
;
897 struct dk_map32
*lmap
;
900 #elif defined(_SUNOS_VTOC_16)
901 struct dkl_partition
*lpart
;
903 #error No VTOC format defined.
904 #endif /* defined(_SUNOS_VTOC_8) */
906 struct extpartition
*vpart
;
909 (void) memset((char *)vtoc
, 0, sizeof (struct extvtoc
));
911 switch (label
->dkl_vtoc
.v_version
) {
914 * No valid vtoc information in the label.
915 * Construct default p_flags and p_tags.
917 vpart
= vtoc
->v_part
;
918 for (i
= 0; i
< V_NUMPAR
; i
++, vpart
++) {
919 vpart
->p_tag
= default_vtoc_map
[i
].p_tag
;
920 vpart
->p_flag
= default_vtoc_map
[i
].p_flag
;
925 vpart
= vtoc
->v_part
;
926 lpart
= label
->dkl_vtoc
.v_part
;
927 for (i
= 0; i
< V_NUMPAR
; i
++, vpart
++, lpart
++) {
928 vpart
->p_tag
= lpart
->p_tag
;
929 vpart
->p_flag
= lpart
->p_flag
;
931 #if defined(_SUNOS_VTOC_16)
932 vpart
->p_start
= (diskaddr_t
)lpart
->p_start
;
933 vpart
->p_size
= (diskaddr_t
)lpart
->p_size
;
934 #endif /* defined(_SUNOS_VTOC_16) */
935 vtoc
->timestamp
[i
] = label
->dkl_vtoc
.v_timestamp
[i
];
937 (void) memcpy(vtoc
->v_volume
, label
->dkl_vtoc
.v_volume
,
940 for (i
= 0; i
< 10; i
++)
941 vtoc
->v_reserved
[i
] = label
->dkl_vtoc
.v_reserved
[i
];
943 vtoc
->v_bootinfo
[0] = label
->dkl_vtoc
.v_bootinfo
[0];
944 vtoc
->v_bootinfo
[1] = label
->dkl_vtoc
.v_bootinfo
[1];
945 vtoc
->v_bootinfo
[2] = label
->dkl_vtoc
.v_bootinfo
[2];
953 * XXX - this looks wrong to me....
954 * why are these values hardwired, rather than returned from
955 * the real disk label?
957 vtoc
->v_sanity
= VTOC_SANE
;
958 vtoc
->v_version
= V_VERSION
;
959 vtoc
->v_sectorsz
= cur_blksz
;
960 vtoc
->v_nparts
= V_NUMPAR
;
962 (void) memcpy(vtoc
->v_asciilabel
, label
->dkl_asciilabel
,
965 #if defined(_SUNOS_VTOC_8)
967 * Convert partitioning information.
968 * Note the conversion from starting cylinder number
969 * to starting sector number.
971 lmap
= label
->dkl_map
;
972 vpart
= vtoc
->v_part
;
973 nblks
= label
->dkl_nsect
* label
->dkl_nhead
;
974 for (i
= 0; i
< V_NUMPAR
; i
++, vpart
++, lmap
++) {
975 vpart
->p_start
= (diskaddr_t
)(lmap
->dkl_cylno
* nblks
);
976 vpart
->p_size
= (diskaddr_t
)lmap
->dkl_nblk
;
978 #endif /* defined(_SUNOS_VTOC_8) */
984 * Input: File descriptor
985 * Output: 1 if disk has an EFI label, 0 otherwise.
993 if (read_extvtoc(fd
, &vtoc
) == VT_ENOTSUP
) {
994 /* assume the disk has EFI label */
1000 /* make sure the user specified something reasonable */
1002 err_check(struct dk_gpt
*vtoc
)
1006 diskaddr_t istart
, jstart
, isize
, jsize
, endsect
;
1010 * make sure no partitions overlap
1012 for (i
= 0; i
< vtoc
->efi_nparts
; i
++) {
1013 /* It can't be unassigned and have an actual size */
1014 if ((vtoc
->efi_parts
[i
].p_tag
== V_UNASSIGNED
) &&
1015 (vtoc
->efi_parts
[i
].p_size
!= 0)) {
1016 (void) fprintf(stderr
,
1017 "partition %d is \"unassigned\" but has a size of %llu\n", i
,
1018 vtoc
->efi_parts
[i
].p_size
);
1020 if (vtoc
->efi_parts
[i
].p_tag
== V_UNASSIGNED
) {
1023 if (vtoc
->efi_parts
[i
].p_tag
== V_RESERVED
) {
1024 if (resv_part
!= -1) {
1025 (void) fprintf(stderr
,
1026 "found duplicate reserved partition at %d\n", i
);
1029 if (vtoc
->efi_parts
[i
].p_size
!= EFI_MIN_RESV_SIZE
)
1030 (void) fprintf(stderr
,
1031 "Warning: reserved partition size must be %d sectors\n",
1034 if ((vtoc
->efi_parts
[i
].p_start
< vtoc
->efi_first_u_lba
) ||
1035 (vtoc
->efi_parts
[i
].p_start
> vtoc
->efi_last_u_lba
)) {
1036 (void) fprintf(stderr
,
1037 "Partition %d starts at %llu\n",
1039 vtoc
->efi_parts
[i
].p_start
);
1040 (void) fprintf(stderr
,
1041 "It must be between %llu and %llu.\n",
1042 vtoc
->efi_first_u_lba
,
1043 vtoc
->efi_last_u_lba
);
1045 if ((vtoc
->efi_parts
[i
].p_start
+
1046 vtoc
->efi_parts
[i
].p_size
<
1047 vtoc
->efi_first_u_lba
) ||
1048 (vtoc
->efi_parts
[i
].p_start
+
1049 vtoc
->efi_parts
[i
].p_size
>
1050 vtoc
->efi_last_u_lba
+ 1)) {
1051 (void) fprintf(stderr
,
1052 "Partition %d ends at %llu\n",
1054 vtoc
->efi_parts
[i
].p_start
+
1055 vtoc
->efi_parts
[i
].p_size
);
1056 (void) fprintf(stderr
,
1057 "It must be between %llu and %llu.\n",
1058 vtoc
->efi_first_u_lba
,
1059 vtoc
->efi_last_u_lba
);
1062 for (j
= 0; j
< vtoc
->efi_nparts
; j
++) {
1063 isize
= vtoc
->efi_parts
[i
].p_size
;
1064 jsize
= vtoc
->efi_parts
[j
].p_size
;
1065 istart
= vtoc
->efi_parts
[i
].p_start
;
1066 jstart
= vtoc
->efi_parts
[j
].p_start
;
1067 if ((i
!= j
) && (isize
!= 0) && (jsize
!= 0)) {
1068 endsect
= jstart
+ jsize
-1;
1069 if ((jstart
<= istart
) &&
1070 (istart
<= endsect
)) {
1072 (void) fprintf(stderr
,
1073 "label error: EFI Labels do not support overlapping partitions\n");
1075 (void) fprintf(stderr
,
1076 "Partition %d overlaps partition %d.\n", i
, j
);
1082 /* make sure there is a reserved partition */
1083 if (resv_part
== -1) {
1084 (void) fprintf(stderr
,
1085 "no reserved partition found\n");
1092 struct dk_label
*label
;
1096 fmt_print("%s\n", label
->dkl_asciilabel
);
1098 fmt_print("version: %d\n", label
->dkl_vtoc
.v_version
);
1099 fmt_print("volume: ");
1100 for (i
= 0; i
< LEN_DKL_VVOL
; i
++) {
1101 if (label
->dkl_vtoc
.v_volume
[i
] == 0)
1103 fmt_print("%c", label
->dkl_vtoc
.v_volume
[i
]);
1106 fmt_print("v_nparts: %d\n", label
->dkl_vtoc
.v_nparts
);
1107 fmt_print("v_sanity: %lx\n", label
->dkl_vtoc
.v_sanity
);
1109 #if defined(_SUNOS_VTOC_8)
1110 fmt_print("rpm: %d\n", label
->dkl_rpm
);
1111 fmt_print("pcyl: %d\n", label
->dkl_pcyl
);
1112 fmt_print("apc: %d\n", label
->dkl_apc
);
1113 fmt_print("obs1: %d\n", label
->dkl_obs1
);
1114 fmt_print("obs2: %d\n", label
->dkl_obs2
);
1115 fmt_print("intrlv: %d\n", label
->dkl_intrlv
);
1116 fmt_print("ncyl: %d\n", label
->dkl_ncyl
);
1117 fmt_print("acyl: %d\n", label
->dkl_acyl
);
1118 fmt_print("nhead: %d\n", label
->dkl_nhead
);
1119 fmt_print("nsect: %d\n", label
->dkl_nsect
);
1120 fmt_print("obs3: %d\n", label
->dkl_obs3
);
1121 fmt_print("obs4: %d\n", label
->dkl_obs4
);
1123 #elif defined(_SUNOS_VTOC_16)
1124 fmt_print("rpm: %d\n", label
->dkl_rpm
);
1125 fmt_print("pcyl: %d\n", label
->dkl_pcyl
);
1126 fmt_print("apc: %d\n", label
->dkl_apc
);
1127 fmt_print("intrlv: %d\n", label
->dkl_intrlv
);
1128 fmt_print("ncyl: %d\n", label
->dkl_ncyl
);
1129 fmt_print("acyl: %d\n", label
->dkl_acyl
);
1130 fmt_print("nhead: %d\n", label
->dkl_nhead
);
1131 fmt_print("nsect: %d\n", label
->dkl_nsect
);
1132 fmt_print("bcyl: %d\n", label
->dkl_bcyl
);
1133 fmt_print("skew: %d\n", label
->dkl_skew
);
1135 #error No VTOC format defined.
1136 #endif /* defined(_SUNOS_VTOC_8) */
1137 fmt_print("magic: %0x\n", label
->dkl_magic
);
1138 fmt_print("cksum: %0x\n", label
->dkl_cksum
);
1140 for (i
= 0; i
< NDKMAP
; i
++) {
1142 #if defined(_SUNOS_VTOC_8)
1143 fmt_print("%c: cyl=%d, blocks=%d", i
+'a',
1144 label
->dkl_map
[i
].dkl_cylno
,
1145 label
->dkl_map
[i
].dkl_nblk
);
1147 #elif defined(_SUNOS_VTOC_16)
1148 fmt_print("%c: start=%u, blocks=%u", i
+'a',
1149 label
->dkl_vtoc
.v_part
[i
].p_start
,
1150 label
->dkl_vtoc
.v_part
[i
].p_size
);
1152 #error No VTOC format defined.
1153 #endif /* defined(_SUNOS_VTOC_8) */
1155 fmt_print(", tag=%d, flag=%d",
1156 label
->dkl_vtoc
.v_part
[i
].p_tag
,
1157 label
->dkl_vtoc
.v_part
[i
].p_flag
);
1161 fmt_print("read_reinstruct: %d\n", label
->dkl_read_reinstruct
);
1162 fmt_print("write_reinstruct: %d\n", label
->dkl_write_reinstruct
);
1164 fmt_print("bootinfo: ");
1165 for (i
= 0; i
< 3; i
++) {
1166 fmt_print("0x%x ", label
->dkl_vtoc
.v_bootinfo
[i
]);
1170 fmt_print("reserved: ");
1171 for (i
= 0; i
< 10; i
++) {
1174 fmt_print("0x%x ", label
->dkl_vtoc
.v_reserved
[i
]);
1178 fmt_print("timestamp:\n");
1179 for (i
= 0; i
< NDKMAP
; i
++) {
1182 fmt_print("0x%x ", label
->dkl_vtoc
.v_timestamp
[i
]);
1186 fmt_print("pad:\n");
1187 dump("", label
->dkl_pad
, LEN_DKL_PAD
, HEX_ONLY
);